1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-24 23:22:30 +01:00

Initial revision

This commit is contained in:
scottc
1998-09-29 22:36:29 +00:00
commit 9d2e6ef9f1
527 changed files with 138651 additions and 0 deletions

101
src/GNUstep.h Normal file
View File

@@ -0,0 +1,101 @@
/* GNUstep.h-- stuff for compatibility with GNUstep applications
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMGNUSTEP_H_
#define WMGNUSTEP_H_
/*
* Kluge for when proplist.h is included too. proplist.h #defines BOOL
* and Xmd.h (which is indirectly included from Xproto.h) typedefs BOOL.
* The worst is that the BOOL from Xmd.h is a 8bit type, while BOOL from
* proplist.h is int...
*/
#ifdef BOOL
#define WINGS_BOOL_FLAG
#undef BOOL
#endif
#include <X11/Xproto.h>
#ifdef WINGS_BOOL_FLAG
#define BOOL int
#undef WINGS_BOOL_FLAG
#endif
#define WINDOWMAKER_WM_MINIATURIZE_WINDOW "_WINDOWMAKER_WM_MINIATURIZE_WINDOW"
#define GNUSTEP_WM_ATTR_NAME "_GNUSTEP_WM_ATTR"
#ifndef _WINGS_H_
/* window stacking level */
enum {
WMNormalWindowLevel = 0,
WMFloatingWindowLevel = 3,
WMDockWindowLevel = 5,
WMSubmenuWindowLevel = 10,
WMMainMenuWindowLevel = 20
};
/* window attributes */
enum {
WMBorderlessWindowMask = 0,
WMTitledWindowMask = 1,
WMClosableWindowMask = 2,
WMMiniaturizableWindowMask = 4,
WMResizableWindowMask = 8
};
#endif /* _WINGS_H_ */
/* GNUstep protocols atom names */
#define GNUSTEP_WM_RESIZEBAR "_GNUSTEP_WM_RESIZEBAR"
typedef struct {
CARD32 flags;
CARD32 window_style;
CARD32 window_level;
CARD32 reserved;
Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
Pixmap close_pixmap; /* pixmap for close button */
Pixmap miniaturize_mask; /* miniaturize pixmap mask */
Pixmap close_mask; /* close pixmap mask */
CARD32 extra_flags;
} GNUstepWMAttributes;
#define GSWindowStyleAttr (1<<0)
#define GSWindowLevelAttr (1<<1)
#define GSMiniaturizePixmapAttr (1<<3)
#define GSClosePixmapAttr (1<<4)
#define GSMiniaturizeMaskAttr (1<<5)
#define GSCloseMaskAttr (1<<6)
#define GSExtraFlagsAttr (1<<7)
/* extra flags */
#define GSDocumentEditedFlag (1<<0)
#define GSNoApplicationIconFlag (1<<5)
#define WMFHideOtherApplications 10
#define WMFHideApplication 12
#endif

121
src/Makefile.am Normal file
View File

@@ -0,0 +1,121 @@
nlsdir = @NLSDIR@
AUTOMAKE_OPTIONS = no-dependencies
BUILT_SOURCES = wconfig.h
bin_PROGRAMS = wmaker
EXTRA_DIST = wmnotify.c wmnotdef.h wmnotify.h
wmaker_SOURCES = \
GNUstep.h \
WindowMaker.h \
actions.c \
actions.h \
appicon.c \
appicon.h \
application.c \
application.h \
appmenu.c \
appmenu.h \
balloon.c \
balloon.h \
client.c \
client.h \
colormap.c \
config.h \
def_pixmaps.h \
defaults.c \
defaults.h \
dialog.c \
dialog.h \
dock.c \
dockedapp.c \
dock.h \
event.c \
framewin.c \
framewin.h \
funcs.h \
icon.c \
icon.h \
keybind.h \
list.c \
list.h \
main.c \
menu.c \
menu.h \
misc.c \
motif.h \
moveres.c \
pixmap.c \
pixmap.h \
placement.c \
properties.c \
properties.h \
proplist.c \
resources.c \
resources.h \
rootmenu.c \
screen.c \
screen.h \
session.h \
session.c \
shutdown.c \
stacking.c \
stacking.h \
startup.c \
superfluous.c \
superfluous.h \
switchmenu.c \
texture.c \
texture.h \
xmodifier.h \
xmodifier.c \
xutil.c \
xutil.h \
wconfig.h \
wcore.c \
wcore.h \
wdefaults.c \
wdefaults.h \
window.c \
window.h \
winmenu.c \
winspector.h \
winspector.c \
workspace.c \
workspace.h \
wmsound.c \
wmsound.h \
text.c \
text.h
CPPFLAGS = \
@CPPFLAGS@ \
@SHAPE@ @I18N@ @X_LOCALE@ \
@DFLAGS@ \
-DNLSDIR="\"$(nlsdir)\"" \
-DPKGDATADIR="\"$(pkgdatadir)\"" \
-DPIXMAPDIR="\"$(pixmapdir)\""
INCLUDES = \
-I$(top_srcdir)/wrlib \
-I$(top_srcdir)/WINGs \
@XCFLAGS@ \
@LIBPL_INC_PATH@
wmaker_LDADD = \
$(top_builddir)/WINGs/libWINGs.a\
$(top_builddir)/wrlib/libwraster.a\
@LIBPL_LIBS@ \
@XLFLAGS@ \
@GFXLIBS@ \
@XLIBS@ \
@X_EXTRA_LIBS@ \
@INTLIBS@ \
-lm

432
src/Makefile.in Normal file
View File

@@ -0,0 +1,432 @@
# Makefile.in generated automatically by automake 1.3 from Makefile.am
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
CC = @CC@
CPP_PATH = @CPP_PATH@
DFLAGS = @DFLAGS@
GFXFLAGS = @GFXFLAGS@
GFXLIBS = @GFXLIBS@
I18N = @I18N@
I18N_MB = @I18N_MB@
ICONEXT = @ICONEXT@
INTLIBS = @INTLIBS@
LIBPL_INC_PATH = @LIBPL_INC_PATH@
LIBPL_LIBS = @LIBPL_LIBS@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
MOFILES = @MOFILES@
NLSDIR = @NLSDIR@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
REDUCE_APPICONS = @REDUCE_APPICONS@
SHAPE = @SHAPE@
SOUND = @SOUND@
VERSION = @VERSION@
WPMOFILES = @WPMOFILES@
XCFLAGS = @XCFLAGS@
XGETTEXT = @XGETTEXT@
XLFLAGS = @XLFLAGS@
XLIBS = @XLIBS@
XSHM = @XSHM@
X_EXTRA_LIBS = @X_EXTRA_LIBS@
X_LOCALE = @X_LOCALE@
pixmapdir = @pixmapdir@
wprefsdir = @wprefsdir@
nlsdir = @NLSDIR@
AUTOMAKE_OPTIONS = no-dependencies
BUILT_SOURCES = wconfig.h
bin_PROGRAMS = wmaker
EXTRA_DIST = wmnotify.c wmnotdef.h wmnotify.h
wmaker_SOURCES = \
GNUstep.h \
WindowMaker.h \
actions.c \
actions.h \
appicon.c \
appicon.h \
application.c \
application.h \
appmenu.c \
appmenu.h \
balloon.c \
balloon.h \
client.c \
client.h \
colormap.c \
config.h \
def_pixmaps.h \
defaults.c \
defaults.h \
dialog.c \
dialog.h \
dock.c \
dockedapp.c \
dock.h \
event.c \
framewin.c \
framewin.h \
funcs.h \
icon.c \
icon.h \
keybind.h \
list.c \
list.h \
main.c \
menu.c \
menu.h \
misc.c \
motif.h \
moveres.c \
pixmap.c \
pixmap.h \
placement.c \
properties.c \
properties.h \
proplist.c \
resources.c \
resources.h \
rootmenu.c \
screen.c \
screen.h \
session.h \
session.c \
shutdown.c \
stacking.c \
stacking.h \
startup.c \
superfluous.c \
superfluous.h \
switchmenu.c \
texture.c \
texture.h \
xmodifier.h \
xmodifier.c \
xutil.c \
xutil.h \
wconfig.h \
wcore.c \
wcore.h \
wdefaults.c \
wdefaults.h \
window.c \
window.h \
winmenu.c \
winspector.h \
winspector.c \
workspace.c \
workspace.h \
wmsound.c \
wmsound.h \
text.c \
text.h
CPPFLAGS = \
@CPPFLAGS@ \
@SHAPE@ @I18N@ @X_LOCALE@ \
@DFLAGS@ \
-DNLSDIR="\"$(nlsdir)\"" \
-DPKGDATADIR="\"$(pkgdatadir)\"" \
-DPIXMAPDIR="\"$(pixmapdir)\""
INCLUDES = \
-I$(top_srcdir)/wrlib \
-I$(top_srcdir)/WINGs \
@XCFLAGS@ \
@LIBPL_INC_PATH@
wmaker_LDADD = \
$(top_builddir)/WINGs/libWINGs.a\
$(top_builddir)/wrlib/libwraster.a\
@LIBPL_LIBS@ \
@XLFLAGS@ \
@GFXLIBS@ \
@XLIBS@ \
@X_EXTRA_LIBS@ \
@INTLIBS@ \
-lm
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = wconfig.h
PROGRAMS = $(bin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir) -I.
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
X_PRE_LIBS = @X_PRE_LIBS@
wmaker_OBJECTS = actions.o appicon.o application.o appmenu.o balloon.o \
client.o colormap.o defaults.o dialog.o dock.o dockedapp.o event.o \
framewin.o icon.o list.o main.o menu.o misc.o moveres.o pixmap.o \
placement.o properties.o proplist.o resources.o rootmenu.o screen.o \
session.o shutdown.o stacking.o startup.o superfluous.o switchmenu.o \
texture.o xmodifier.o xutil.o wcore.o wdefaults.o window.o winmenu.o \
winspector.o workspace.o wmsound.o text.o
wmaker_DEPENDENCIES = $(top_builddir)/WINGs/libWINGs.a \
$(top_builddir)/wrlib/libwraster.a
wmaker_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in config.h.in stamp-h.in \
wconfig.h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
SOURCES = $(wmaker_SOURCES)
OBJECTS = $(wmaker_OBJECTS)
all: Makefile $(PROGRAMS) config.h
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
config.h: stamp-h
@:
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=src/config.h \
$(SHELL) ./config.status
@echo timestamp > stamp-h
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/stamp-h.in
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f config.h
maintainer-clean-hdr:
wconfig.h: $(top_builddir)/config.status wconfig.h.in
cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
mostlyclean-binPROGRAMS:
clean-binPROGRAMS:
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
distclean-binPROGRAMS:
maintainer-clean-binPROGRAMS:
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
list='$(bin_PROGRAMS)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \
done
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
wmaker: $(wmaker_OBJECTS) $(wmaker_DEPENDENCIES)
@rm -f wmaker
$(LINK) $(wmaker_LDFLAGS) $(wmaker_OBJECTS) $(wmaker_LDADD) $(LIBS)
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = src
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
info:
dvi:
check: all
$(MAKE)
installcheck:
install-exec: install-binPROGRAMS
@$(NORMAL_INSTALL)
install-data:
@$(NORMAL_INSTALL)
install: install-exec install-data all
@:
uninstall: uninstall-binPROGRAMS
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
$(mkinstalldirs) $(DATADIR)$(bindir)
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-hdr mostlyclean-binPROGRAMS \
mostlyclean-compile mostlyclean-tags \
mostlyclean-generic
clean: clean-hdr clean-binPROGRAMS clean-compile clean-tags \
clean-generic mostlyclean
distclean: distclean-hdr distclean-binPROGRAMS distclean-compile \
distclean-tags distclean-generic clean
-rm -f config.status
maintainer-clean: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir info dvi installcheck \
install-exec install-data install uninstall all installdirs \
mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

328
src/WindowMaker.h Normal file
View File

@@ -0,0 +1,328 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WINDOWMAKER_H_
#define WINDOWMAKER_H_
#include "wconfig.h"
#include <assert.h>
#include "WINGs.h"
#include "WUtil.h"
#if HAVE_LIBINTL_H && I18N
# include <libintl.h>
# define _(text) gettext(text)
#else
# define _(text) (text)
#endif
/* max. number of distinct window levels */
#define MAX_WINDOW_LEVELS 5
/* class codes */
typedef enum {
WCLASS_UNKNOWN = 0,
WCLASS_WINDOW = 1, /* managed client windows */
WCLASS_MENU = 2, /* root menus */
WCLASS_APPICON = 3,
WCLASS_DUMMYWINDOW = 4, /* window that holds window group leader */
WCLASS_MINIWINDOW = 5,
WCLASS_DOCK_ICON = 6,
WCLASS_PAGER = 7,
WCLASS_TEXT_INPUT = 8,
WCLASS_FRAME = 9
} WClassType;
/*
* WObjDescriptor will be used by the event dispatcher to
* send events to a particular object through the methods in the
* method table. If all objects of the same class share the
* same methods, the class method table should be used, otherwise
* a new method table must be created for each object.
* It is also assigned to find the parent structure of a given
* window (like the WWindow or WMenu for a button)
*/
typedef struct WObjDescriptor {
void *self; /* the object that will be called */
/* event handlers */
void (*handle_expose)(struct WObjDescriptor *sender, XEvent *event);
void (*handle_mousedown)(struct WObjDescriptor *sender, XEvent *event);
void (*handle_anything)(struct WObjDescriptor *sender, XEvent *event);
void (*handle_enternotify)(struct WObjDescriptor *sender, XEvent *event);
void (*handle_leavenotify)(struct WObjDescriptor *sender, XEvent *event);
WClassType parent_type; /* type code of the parent */
void *parent; /* parent object (WWindow or WMenu) */
} WObjDescriptor;
/* internal buttons */
#define WBUT_CLOSE 0
#define WBUT_BROKENCLOSE 1
#define WBUT_ICONIFY 2
#define WBUT_KILL 3
#define PRED_BPIXMAPS 4 /* count of WBUT icons */
/* cursors */
#define WCUR_DEFAULT 0
#define WCUR_NORMAL 0
#define WCUR_MOVE 1
#define WCUR_RESIZE 2
#define WCUR_WAIT 3
#define WCUR_ARROW 4
#define WCUR_QUESTION 5
#define WCUR_TEXT 6
#define WCUR_LAST 7
/* geometry displays */
#define WDIS_NEW 0 /* new style */
#define WDIS_CENTER 1 /* center of screen */
#define WDIS_TOPLEFT 2 /* top left corner of screen */
#define WDIS_FRAME_CENTER 3 /* center of the frame */
/* keyboard input focus mode */
#define WKF_CLICK 0
#define WKF_POINTER 1
#define WKF_SLOPPY 2
/* window placement mode */
#define WPM_MANUAL 0
#define WPM_CASCADE 1
#define WPM_SMART 2
#define WPM_RANDOM 3
/* text justification */
#define WTJ_CENTER 0
#define WTJ_LEFT 1
#define WTJ_RIGHT 2
/* icon box positions */
#define WIB_BOTTOM 0
#define WIB_TOP 1
#define WIB_LEFT 2
#define WIB_RIGHT 3
/* iconification styles */
#define WIS_ZOOM 0
#define WIS_TWIST 1
#define WIS_FLIP 2
#define WIS_NONE 3
/* switchmenu actions */
#define ACTION_ADD 0
#define ACTION_REMOVE 1
#define ACTION_CHANGE 2
#define ACTION_CHANGE_WORKSPACE 3
#define ACTION_CHANGE_STATE 4
/* speeds */
#define SPEED_ULTRAFAST 0
#define SPEED_FAST 1
#define SPEED_MEDIUM 2
#define SPEED_SLOW 3
#define SPEED_ULTRASLOW 4
/* startup warnings */
#define WAR_DEFAULTS_DIR 1 /* created defaults DB directory */
/* window states */
#define WS_FOCUSED 0
#define WS_UNFOCUSED 1
#define WS_PFOCUSED 2
/* clip title colors */
#define CLIP_NORMAL 0
#define CLIP_COLLAPSED 1
/* icon yard position */
#define IY_VERT 1
#define IY_HORIZ 0
#define IY_TOP 2
#define IY_BOTTOM 0
#define IY_RIGHT 4
#define IY_LEFT 0
typedef struct W2Color {
char *color1;
char *color2;
} W2Color;
typedef struct WCoord {
int x, y;
} WCoord;
typedef struct WPreferences {
char **pixmap_path; /* NULL terminated array of */
/* paths to find pixmaps */
char **icon_path; /* NULL terminated array of */
/* paths to find icons */
char size_display; /* display type for resize geometry */
char move_display; /* display type for move geometry */
char window_placement; /* window placement mode */
char colormap_mode; /* colormap focus mode */
char focus_mode; /* window focusing mode */
char opaque_move; /* update window position during */
/* move */
char wrap_menus; /* wrap menus at edge of screen */
char scrollable_menus; /* let them be scrolled */
char align_menus; /* align menu with their parents */
char use_saveunders; /* turn on SaveUnders for menus,
* icons etc. */
char no_window_under_dock;
char no_window_over_icons;
WCoord window_place_origin; /* Offset for windows placed on
* screen */
char constrain_window_size; /* don't let windows get bigger than
* screen */
char circ_raise; /* raise window when Alt-tabbing */
char ignore_focus_click;
char on_top_transients; /* transient windows are kept on top
* of their owners */
char title_justification; /* titlebar text alignment */
char no_dithering; /* use dithering or not */
char no_sound; /* enable/disable sound */
char no_animations; /* enable/disable animations */
char no_autowrap; /* wrap workspace when window is moved
* to the edge */
char auto_arrange_icons; /* automagically arrange icons */
char icon_box_position; /* position to place icons */
char iconification_style; /* position to place icons */
char disable_root_mouse; /* disable mouse actions in root window */
char auto_focus; /* focus window when it's mapped */
char *icon_back_file; /* background image for icons */
WCoord *root_menu_pos; /* initial position of the root menu*/
WCoord *app_menu_pos;
WCoord *win_menu_pos;
int icon_yard; /* aka iconbox */
int raise_delay; /* delay for autoraise. 0 is disabled */
int cmap_size; /* size of dithering colormap in colors
* per channel */
int icon_size; /* size of the icon */
char ws_advance; /* Create new workspace and advance */
char ws_cycle; /* Cycle existing workspaces */
unsigned int modifier_mask; /* mask to use as kbd modifier */
char save_session_on_exit; /* automatically save session on exit */
char sticky_icons; /* If miniwindows will be onmipresent */
char dont_confirm_kill; /* do not confirm Kill application */
char dont_blink;
/* Appearance options */
char new_style; /* Use newstyle buttons */
char superfluous; /* Use superfluous things */
/* root window mouse bindings */
char select_button; /* button for window selection */
char windowl_button; /* button for window list menu */
char menu_button; /* button for app menu */
/* balloon text */
char window_balloon;
char miniwin_balloon;
char appicon_balloon;
/* some constants */
int dblclick_time; /* double click delay time in ms */
/* animate menus */
int menu_scroll_speed; /* how fast menus are scrolled */
/* animate icon sliding */
int icon_slide_speed; /* icon slide animation speed */
/* shading animation */
int shade_speed;
int edge_resistance;
struct {
unsigned int nodock:1; /* don't display the dock */
unsigned int noclip:1; /* don't display the clip */
unsigned int nocpp:1; /* don't use cpp */
} flags; /* internal flags */
} WPreferences;
/****** Global Variables ******/
extern Display *dpy;
extern char *ProgName;
extern unsigned int ValidModMask;
/****** Global Functions ******/
extern void wAbort(Bool dumpCore);
#endif

1740
src/actions.c Normal file

File diff suppressed because it is too large Load Diff

63
src/actions.h Normal file
View File

@@ -0,0 +1,63 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMACTIONS_H_
#define WMACTIONS_H_
#include "window.h"
#define MAX_HORIZONTAL 1
#define MAX_VERTICAL 2
void wSetFocusTo(WScreen *scr, WWindow *wwin);
int wMouseMoveWindow(WWindow *wwin, XEvent *ev);
void wMouseResizeWindow(WWindow *wwin, XEvent *ev);
void wShadeWindow(WWindow *wwin);
void wUnshadeWindow(WWindow *wwin);
void wIconifyWindow(WWindow *wwin);
void wDeiconifyWindow(WWindow *wwin);
void wSelectWindows(WScreen *scr, XEvent *ev);
void wSelectWindow(WWindow *wwin);
void wUnselectWindows();
void wMaximizeWindow(WWindow *wwin, int directions);
void wUnmaximizeWindow(WWindow *wwin);
void wHideOtherApplications(WWindow *wwin);
void wShowAllWindows(WScreen *scr);
void wHideApplication(WApplication *wapp);
void wUnhideApplication(WApplication *wapp, Bool miniwindows,
Bool bringToCurrentWS);
void wRefreshDesktop(WScreen *scr);
void wArrangeIcons(WScreen *scr, Bool arrangeAll);
#endif

855
src/appicon.c Normal file
View File

@@ -0,0 +1,855 @@
/* appicon.c- icon for applications (not mini-window)
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "window.h"
#include "icon.h"
#include "appicon.h"
#include "actions.h"
#include "stacking.h"
#include "dock.h"
#include "funcs.h"
#include "defaults.h"
#include "workspace.h"
#include "superfluous.h"
#include "menu.h"
#include "framewin.h"
#include "dialog.h"
#include "client.h"
/*
* icon_file for the dock is got from the preferences file by
* using the classname/instancename
*/
/**** Global variables ****/
extern Cursor wCursor[WCUR_LAST];
extern WPreferences wPreferences;
#define MOD_MASK wPreferences.modifier_mask
void appIconMouseDown(WObjDescriptor *desc, XEvent *event);
static void iconDblClick(WObjDescriptor *desc, XEvent *event);
static void iconExpose(WObjDescriptor *desc, XEvent *event);
WAppIcon*
wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
char *wm_class, int tile)
{
WAppIcon *dicon;
char *path;
dicon = wmalloc(sizeof(WAppIcon));
wretain(dicon);
memset(dicon, 0, sizeof(WAppIcon));
dicon->yindex = -1;
dicon->xindex = -1;
dicon->prev = NULL;
dicon->next = scr->app_icon_list;
if (scr->app_icon_list) {
scr->app_icon_list->prev = dicon;
}
scr->app_icon_list = dicon;
if (command) {
dicon->command = wstrdup(command);
}
if (wm_class)
dicon->wm_class = wstrdup(wm_class);
if (wm_instance)
dicon->wm_instance = wstrdup(wm_instance);
path = wDefaultGetIconFile(scr, wm_instance, wm_class, True);
if (!path && command) {
wApplicationExtractDirPackIcon(scr, command, wm_instance, wm_class);
path = wDefaultGetIconFile(scr, wm_instance, wm_class, False);
}
if (path)
path = FindImage(wPreferences.icon_path, path);
dicon->icon = wIconCreateWithIconFile(scr, path, tile);
if (path)
free(path);
#ifdef REDUCE_APPICONS
dicon->num_apps = 0;
#endif
/* will be overriden by dock */
dicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
dicon->icon->core->descriptor.handle_expose = iconExpose;
dicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
dicon->icon->core->descriptor.parent = dicon;
AddToStackList(dicon->icon->core);
return dicon;
}
WAppIcon*
wAppIconCreate(WWindow *leader_win)
{
WAppIcon *aicon;
#ifdef REDUCE_APPICONS
WAppIcon *atmp;
WAppIconAppList *applist;
char *tinstance, *tclass;
#endif
WScreen *scr = leader_win->screen_ptr;
aicon = wmalloc(sizeof(WAppIcon));
wretain(aicon);
memset(aicon, 0, sizeof(WAppIcon));
#ifdef REDUCE_APPICONS
applist = wmalloc(sizeof(WAppIconAppList));
memset(applist, 0, sizeof(WAppIconAppList));
applist->wapp = wApplicationOf(leader_win->main_window);
aicon->applist = applist;
if (applist->wapp == NULL) {
/* Something's wrong. wApplicationOf() should always return a
* valid structure. Rather than violate assumptions, bail. -cls
*/
free(applist);
wrelease(aicon);
return NULL;
}
#endif
aicon->yindex = -1;
aicon->xindex = -1;
aicon->prev = NULL;
aicon->next = scr->app_icon_list;
if (scr->app_icon_list) {
#ifdef REDUCE_APPICONS
/* If we aren't going to have a match, jump straight to new appicon */
if (leader_win->wm_class == NULL || leader_win->wm_class == NULL)
atmp = NULL;
else
atmp = scr->app_icon_list;
while (atmp != NULL) {
if ((tinstance = atmp->wm_instance) == NULL)
tinstance = "";
if ((tclass = atmp->wm_class) == NULL)
tclass = "";
if ((strcmp(leader_win->wm_class, tclass) == 0) &&
(strcmp(leader_win->wm_instance, tinstance) == 0))
{
/* We have a winner */
wrelease(aicon);
atmp->num_apps++;
applist->next = atmp->applist;
if (atmp->applist)
atmp->applist->prev = applist;
atmp->applist = applist;
if (atmp->docked) {
wDockSimulateLaunch(atmp->dock, atmp);
}
return atmp;
}
atmp = atmp->next;
}
if (atmp == NULL) {
#endif
scr->app_icon_list->prev = aicon;
#ifdef REDUCE_APPICONS
}
#endif
}
scr->app_icon_list = aicon;
if (leader_win->wm_class)
aicon->wm_class = wstrdup(leader_win->wm_class);
if (leader_win->wm_instance)
aicon->wm_instance = wstrdup(leader_win->wm_instance);
#ifdef REDUCE_APPICONS
aicon->num_apps = 1;
#endif
aicon->icon = wIconCreate(leader_win);
/* will be overriden if docked */
aicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
aicon->icon->core->descriptor.handle_expose = iconExpose;
aicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
aicon->icon->core->descriptor.parent = aicon;
AddToStackList(aicon->icon->core);
aicon->icon->show_title = 0;
wIconUpdate(aicon->icon);
return aicon;
}
void
wAppIconDestroy(WAppIcon *aicon)
{
WScreen *scr = aicon->icon->core->screen_ptr;
#ifdef REDUCE_APPICONS
WAppIconAppList *aptmp;
#endif
RemoveFromStackList(aicon->icon->core);
wIconDestroy(aicon->icon);
if (aicon->command)
free(aicon->command);
#ifdef OFFIX_DND
if (aicon->dnd_command)
free(aicon->dnd_command);
#endif
if (aicon->wm_instance)
free(aicon->wm_instance);
if (aicon->wm_class)
free(aicon->wm_class);
#ifdef REDUCE_APPICONS
/* There should never be a list but just in case */
if (aicon->applist != NULL) {
aptmp = aicon->applist;
while (aptmp->next) {
aptmp = aptmp->next;
free(aptmp->prev);
}
free(aptmp);
}
#endif
if (aicon == scr->app_icon_list) {
if (aicon->next)
aicon->next->prev = NULL;
scr->app_icon_list = aicon->next;
}
else {
if (aicon->next)
aicon->next->prev = aicon->prev;
if (aicon->prev)
aicon->prev->next = aicon->next;
}
aicon->destroyed = 1;
wrelease(aicon);
}
#ifdef NEWAPPICON
static void
drawCorner(WIcon *icon, WWindow *wwin, int active)
{
WScreen *scr = wwin->screen_ptr;
XPoint points[3];
GC gc;
points[0].x = 2;
points[0].y = 2;
points[1].x = 12;
points[1].y = 2;
points[2].x = 2;
points[2].y = 12;
if (active) {
gc=scr->focused_texture->any.gc;
} else {
gc=scr->unfocused_texture->any.gc;
}
XFillPolygon(dpy, icon->core->window, gc, points, 3,
Convex, CoordModeOrigin);
}
#endif /* NEWAPPICON */
void
wAppIconMove(WAppIcon *aicon, int x, int y)
{
XMoveWindow(dpy, aicon->icon->core->window, x, y);
aicon->x_pos = x;
aicon->y_pos = y;
}
#ifdef WS_INDICATOR
static void
updateDockNumbers(WScreen *scr)
{
int length;
char *ws_numbers;
GC numbers_gc;
XGCValues my_gc_values;
unsigned long my_v_mask = (GCForeground);
WAppIcon *dicon = scr->dock->icon_array[0];
my_gc_values.foreground = scr->white_pixel;
numbers_gc = XCreateGC(dpy, dicon->icon->core->window,
my_v_mask, &my_gc_values);
ws_numbers = malloc(20);
sprintf(ws_numbers, "%i [ %i ]", scr->current_workspace+1,
((scr->current_workspace/10)+1));
length = strlen(ws_numbers);
XClearArea(dpy, dicon->icon->core->window, 2, 2, 50,
scr->icon_title_font->y+1, False);
#ifndef I18N_MB
XSetFont(dpy, numbers_gc, scr->icon_title_font->font->fid);
XSetForeground(dpy, numbers_gc, scr->black_pixel);
XDrawString(dpy, dicon->icon->core->window,
numbers_gc, 4, scr->icon_title_font->y+3, ws_numbers, length);
XSetForeground(dpy, numbers_gc, scr->white_pixel);
XDrawString(dpy, dicon->icon->core->window,
numbers_gc, 3, scr->icon_title_font->y+2, ws_numbers, length);
#else
XSetForeground(dpy, numbers_gc, scr->black_pixel);
XmbDrawString(dpy, dicon->icon->core->window,
scr->icon_title_font->font, numbers_gc, 4,
scr->icon_title_font->y+3, ws_numbers, length);
XSetForeground(dpy, numbers_gc, scr->white_pixel);
XmbDrawString(dpy, dicon->icon->core->window,
scr->icon_title_font->font, numbers_gc, 3,
scr->icon_title_font->y+2, ws_numbers, length);
#endif /* I18N_MB */
XFreeGC(dpy, numbers_gc);
free(ws_numbers);
}
#endif /* WS_INDICATOR */
void
wAppIconPaint(WAppIcon *aicon)
{
WScreen *scr = aicon->icon->core->screen_ptr;
wIconPaint(aicon->icon);
# ifdef WS_INDICATOR
if (aicon->docked && scr->dock && aicon->yindex==0)
updateDockNumbers(scr);
# endif
if (scr->dock_dots && aicon->docked && !aicon->running
&& aicon->command!=NULL) {
XSetClipMask(dpy, scr->copy_gc, scr->dock_dots->mask);
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
XCopyArea(dpy, scr->dock_dots->image, aicon->icon->core->window,
scr->copy_gc, 0, 0, scr->dock_dots->width,
scr->dock_dots->height, 0, 0);
}
#ifdef NEWAPPICON
if (!wPreferences.strict_ns && aicon->icon->owner!=NULL) {
int active=0;
if (aicon->main_window==None) {
active = (aicon->icon->owner->flags.focused ? 1 : 0);
} else {
WApplication *wapp;
wapp = wApplicationOf(aicon->main_window);
if (!wapp) {
active = aicon->icon->owner->flags.focused;
wwarning("error in wAppIconPaint(). Please report it");
} else {
active = wapp->main_window_desc->flags.focused;
if (wapp->main_window_desc->flags.hidden
|| !wapp->main_window_desc->flags.mapped)
active = -1;
}
}
if (active>=0)
drawCorner(aicon->icon, aicon->icon->owner, active);
}
#endif /* NEWAPPICON */
XSetClipMask(dpy, scr->copy_gc, None);
if (aicon->launching) {
XFillRectangle(dpy, aicon->icon->core->window, scr->stipple_gc,
0, 0, wPreferences.icon_size, wPreferences.icon_size);
}
}
#define canBeDocked(wwin) ((wwin) && ((wwin)->wm_class||(wwin)->wm_instance))
#ifdef REDUCE_APPICONS
unsigned int
wAppIconReduceAppCount(WApplication *wapp)
{
WAppIconAppList *applist;
if (wapp == NULL)
return 0;
if (wapp->app_icon == NULL)
return 0;
/* If given a main window, check the applist
* and remove the if it exists
*/
applist = wapp->app_icon->applist;
while (applist != NULL) {
if (applist->wapp == wapp) {
/* If this app owns the appicon, change the appicon's
* owner to the next app in the list or NULL
*/
if (wapp->app_icon->icon->owner == applist->wapp->main_window_desc)
{
if (applist->next) {
wapp->app_icon->icon->owner = applist->next->wapp->main_window_desc;
} else if (applist->prev) {
wapp->app_icon->icon->owner = applist->prev->wapp->main_window_desc;
} else {
wapp->app_icon->icon->owner = NULL;
}
}
if (applist->prev)
applist->prev->next = applist->next;
if (applist->next)
applist->next->prev = applist->prev;
if (applist == wapp->app_icon->applist)
wapp->app_icon->applist = applist->next;
free(applist);
if (wapp->app_icon->applist != NULL)
wapp->app_icon->main_window = wapp->app_icon->applist->wapp->main_window;
return (--wapp->app_icon->num_apps);
}
applist = applist->next;
}
return (--wapp->app_icon->num_apps);
}
#endif
static void
hideCallback(WMenu *menu, WMenuEntry *entry)
{
WApplication *wapp = (WApplication*)entry->clientdata;
if (wapp->flags.hidden) {
wWorkspaceChange(menu->menu->screen_ptr, wapp->last_workspace);
wUnhideApplication(wapp, False, False);
} else {
wHideApplication(wapp);
}
}
static void
unhideHereCallback(WMenu *menu, WMenuEntry *entry)
{
WApplication *wapp = (WApplication*)entry->clientdata;
wUnhideApplication(wapp, False, True);
}
static void
setIconCallback(WMenu *menu, WMenuEntry *entry)
{
WAppIcon *icon = ((WApplication*)entry->clientdata)->app_icon;
char *file=NULL;
WScreen *scr;
int result;
assert(icon!=NULL);
if (icon->editing)
return;
icon->editing = 1;
scr = icon->icon->core->screen_ptr;
wretain(icon);
result = wIconChooserDialog(scr, &file);
if (result && !icon->destroyed) {
if (file[0]==0) {
free(file);
file = NULL;
}
if (!wIconChangeImageFile(icon->icon, file)) {
wMessageDialog(scr, _("Error"),
_("Could not open specified icon file"),
_("OK"), NULL, NULL);
} else {
wDefaultChangeIcon(scr, icon->wm_instance, icon->wm_class, file);
wAppIconPaint(icon);
}
if (file)
free(file);
}
icon->editing = 0;
wrelease(icon);
}
static void
killCallback(WMenu *menu, WMenuEntry *entry)
{
WApplication *wapp = (WApplication*)entry->clientdata;
assert(entry->clientdata!=NULL);
wretain(wapp->main_window_desc);
if (wPreferences.dont_confirm_kill
|| wMessageDialog(menu->frame->screen_ptr, _("Kill Application"),
_("This will kill the application.\nAny unsaved changes will be lost.\nPlease confirm."),
_("Yes"), _("No"), NULL)==WAPRDefault) {
if (!wapp->main_window_desc->flags.destroyed)
wClientKill(wapp->main_window_desc);
}
wrelease(wapp->main_window_desc);
}
static WMenu*
createApplicationMenu(WScreen *scr)
{
WMenu *menu;
menu = wMenuCreate(scr, NULL, False);
wMenuAddCallback(menu, _("Unhide Here"), unhideHereCallback, NULL);
wMenuAddCallback(menu, _("(Un)Hide"), hideCallback, NULL);
wMenuAddCallback(menu, _("Set Icon..."), setIconCallback, NULL);
wMenuAddCallback(menu, _("Kill"), killCallback, NULL);
return menu;
}
static void
openApplicationMenu(WApplication *wapp, int x, int y)
{
WMenu *menu;
WScreen *scr = wapp->main_window_desc->screen_ptr;
int i;
if (!scr->icon_menu) {
scr->icon_menu = createApplicationMenu(scr);
}
menu = scr->icon_menu;
if (!menu->flags.realized)
wMenuRealize(menu);
x -= menu->frame->core->width/2;
if (x + menu->frame->core->width > scr->scr_width)
x = scr->scr_width - menu->frame->core->width;
if (x < 0)
x = 0;
/* set client data */
for (i = 0; i < menu->entry_no; i++) {
menu->entries[i]->clientdata = wapp;
}
wMenuMapAt(menu, x, y, False);
}
/******************************************************************/
static void
iconExpose(WObjDescriptor *desc, XEvent *event)
{
wAppIconPaint(desc->parent);
}
static void
iconDblClick(WObjDescriptor *desc, XEvent *event)
{
WAppIcon *aicon = desc->parent;
WApplication *wapp;
WScreen *scr = aicon->icon->core->screen_ptr;
int unhideHere;
#ifndef REDUCE_APPICONS
assert(aicon->icon->owner!=NULL);
#else
if (aicon->icon->owner == NULL) {
fprintf(stderr, "Double-click disabled: missing main window.\n");
return;
}
#endif
wapp = wApplicationOf(aicon->icon->owner->main_window);
#ifdef DEBUG0
if (!wapp) {
wwarning("could not find application descriptor for app icon!!");
return;
}
#endif
#ifdef REDUCE_APPICONS
if (!wapp) {
fprintf(stderr, "Double-click disabled: missing wapp.\n");
return;
}
#endif /* REDUCE_APPICONS */
#if 0
/* aproveita que ta aqui pra atualizar */
wapp->main_window = aicon->icon->owner->main_window;
#endif
unhideHere = (event->xbutton.state & ShiftMask);
/* go to the last workspace that the user worked on the app */
if (!unhideHere)
wWorkspaceChange(scr, wapp->last_workspace);
wUnhideApplication(wapp, event->xbutton.button==Button2, unhideHere);
if (event->xbutton.state & MOD_MASK) {
wHideOtherApplications(aicon->icon->owner);
}
}
void
appIconMouseDown(WObjDescriptor *desc, XEvent *event)
{
WAppIcon *aicon = desc->parent;
WIcon *icon = aicon->icon;
XEvent ev;
int x=aicon->x_pos, y=aicon->y_pos;
int dx=event->xbutton.x, dy=event->xbutton.y;
int grabbed=0;
int done=0;
int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */
WScreen *scr = icon->core->screen_ptr;
WWorkspace *workspace = scr->workspaces[scr->current_workspace];
int shad_x = 0, shad_y = 0, docking=0, dockable, collapsed = 0;
int ix, iy;
int clickButton = event->xbutton.button;
Pixmap ghost = None;
if (IsDoubleClick(scr, event)) {
iconDblClick(desc, event);
return;
}
if (event->xbutton.button == Button3) {
WObjDescriptor *desc;
WApplication *wapp = wApplicationOf(aicon->icon->owner->main_window);
openApplicationMenu(wapp, event->xbutton.x_root,
event->xbutton.y_root);
/* allow drag select of menu */
desc = &scr->icon_menu->menu->descriptor;
event->xbutton.send_event = True;
(*desc->handle_mousedown)(desc, event);
return;
}
#ifdef DEBUG
puts("Moving icon");
#endif
if (event->xbutton.state & MOD_MASK)
wLowerFrame(icon->core);
else
wRaiseFrame(icon->core);
if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask
|ButtonReleaseMask|ButtonPressMask, GrabModeAsync,
GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) {
wwarning("pointer grab failed for appicon move");
}
if (wPreferences.flags.nodock && wPreferences.flags.noclip)
dockable = 0;
else
dockable = canBeDocked(icon->owner);
while (!done) {
WMMaskEvent(dpy, PointerMotionMask|ButtonReleaseMask|ButtonPressMask
|ButtonMotionMask|ExposureMask, &ev);
switch (ev.type) {
case Expose:
WMHandleEvent(&ev);
break;
case MotionNotify:
if (!grabbed) {
if (abs(dx-ev.xmotion.x)>=MOVE_THRESHOLD
|| abs(dy-ev.xmotion.y)>=MOVE_THRESHOLD) {
XChangeActivePointerGrab(dpy, ButtonMotionMask
|ButtonReleaseMask|ButtonPressMask,
wCursor[WCUR_MOVE], CurrentTime);
grabbed=1;
} else {
break;
}
}
x = ev.xmotion.x_root - dx;
y = ev.xmotion.y_root - dy;
XMoveWindow(dpy, icon->core->window, x, y);
if (dockable) {
if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y,
&ix, &iy, False)) {
shad_x = scr->dock->x_pos + ix*wPreferences.icon_size;
shad_y = scr->dock->y_pos + iy*wPreferences.icon_size;
if (scr->last_dock != scr->dock && collapsed) {
scr->last_dock->collapsed = 1;
wDockHideIcons(scr->last_dock);
collapsed = 0;
}
if (!collapsed && (collapsed = scr->dock->collapsed)) {
scr->dock->collapsed = 0;
wDockShowIcons(scr->dock);
}
scr->last_dock = scr->dock;
XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
if (!docking) {
Window wins[2];
wins[0] = icon->core->window;
wins[1] = scr->dock_shadow;
XRestackWindows(dpy, wins, 2);
if (superfluous) {
if (icon->pixmap!=None)
ghost = MakeGhostIcon(scr, icon->pixmap);
else
ghost = MakeGhostIcon(scr, icon->core->window);
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow,
ghost);
XClearWindow(dpy, scr->dock_shadow);
}
XMapWindow(dpy, scr->dock_shadow);
}
docking = 1;
} else if (workspace->clip &&
wDockSnapIcon(workspace->clip, aicon, x, y,
&ix, &iy, False)) {
shad_x = workspace->clip->x_pos + ix*wPreferences.icon_size;
shad_y = workspace->clip->y_pos + iy*wPreferences.icon_size;
if (scr->last_dock != workspace->clip && collapsed) {
scr->last_dock->collapsed = 1;
wDockHideIcons(scr->last_dock);
collapsed = 0;
}
if (!collapsed && (collapsed = workspace->clip->collapsed)) {
workspace->clip->collapsed = 0;
wDockShowIcons(workspace->clip);
}
scr->last_dock = workspace->clip;
XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y);
if (!docking) {
Window wins[2];
wins[0] = icon->core->window;
wins[1] = scr->dock_shadow;
XRestackWindows(dpy, wins, 2);
if (superfluous) {
if (icon->pixmap!=None)
ghost = MakeGhostIcon(scr, icon->pixmap);
else
ghost = MakeGhostIcon(scr, icon->core->window);
XSetWindowBackgroundPixmap(dpy, scr->dock_shadow,
ghost);
XClearWindow(dpy, scr->dock_shadow);
}
XMapWindow(dpy, scr->dock_shadow);
}
docking = 1;
} else if (docking) {
XUnmapWindow(dpy, scr->dock_shadow);
docking = 0;
}
}
break;
case ButtonPress:
break;
case ButtonRelease:
if (ev.xbutton.button != clickButton)
break;
XUngrabPointer(dpy, CurrentTime);
if (docking) {
Bool docked;
/* icon is trying to be docked */
SlideWindow(icon->core->window, x, y, shad_x, shad_y);
XUnmapWindow(dpy, scr->dock_shadow);
docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy);
if (scr->last_dock->auto_collapse) {
collapsed = 0;
}
if (!docked) {
/* If icon could not be docked, slide it back to the old
* position */
SlideWindow(icon->core->window, x, y, aicon->x_pos,
aicon->y_pos);
}
} else {
XMoveWindow(dpy, icon->core->window, x, y);
aicon->x_pos = x;
aicon->y_pos = y;
}
if (collapsed) {
scr->last_dock->collapsed = 1;
wDockHideIcons(scr->last_dock);
collapsed = 0;
}
if (superfluous) {
if (ghost!=None)
XFreePixmap(dpy, ghost);
XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel);
}
done = 1;
break;
}
}
#ifdef DEBUG
puts("End icon move");
#endif
}

114
src/appicon.h Normal file
View File

@@ -0,0 +1,114 @@
/* appicon.h- application icon
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMAPPICON_H_
#define WMAPPICON_H_
#include <wraster.h>
#include "wcore.h"
#include "window.h"
#include "icon.h"
#include "application.h"
#ifdef REDUCE_APPICONS
typedef struct WAppIconAppList {
struct WAppIconAppList *prev;
struct WAppIconAppList *next;
WApplication *wapp;
} WAppIconAppList;
#endif
typedef struct WAppIcon {
short xindex;
short yindex;
struct WAppIcon *next;
struct WAppIcon *prev;
WIcon *icon;
char *client_machine;
int x_pos, y_pos; /* absolute screen coordinate */
char *command; /* command used to launch app */
#ifdef OFFIX_DND
char *dnd_command; /* command to use when something is */
/* dropped on us */
#endif
char *wm_class;
char *wm_instance;
pid_t pid; /* for apps launched from the dock */
Window main_window;
#ifdef REDUCE_APPICONS
/* There are a number of assumptions about structures in the code,
* but nowhere do I see them explicitly stated. I'll rip this out later.
* If applist is not NULL, applist->wapp will always point to a valid
* structure. Knowing this removes the need for useless checks....
* AS LONG AS NO ONE VIOLATES THIS ASSUMPTION. -cls
*/
WAppIconAppList *applist; /* list of apps bound to appicon */
#endif
struct WDock *dock; /* In which dock is docked. */
struct _AppSettingsPanel *panel; /* Settings Panel */
unsigned int gnustep_app:1; /* if this is a GNUstep application */
unsigned int docked:1;
unsigned int attracted:1; /* If it was attracted by the clip */
unsigned int launching:1;
unsigned int running:1; /* application is already running */
unsigned int relaunching:1; /* launching 2nd instance */
unsigned int forced_dock:1;
unsigned int auto_launch:1; /* launch app on startup */
unsigned int remote_start:1;
unsigned int updated:1;
unsigned int editing:1; /* editing docked icon */
unsigned int drop_launch:1; /* launching from drop action */
unsigned int destroyed:1; /* appicon was destroyed */
unsigned int buggy_app:1; /* do not make dock rely on hints
* set by app */
#ifdef REDUCE_APPICONS
unsigned int num_apps; /* length of applist */
#endif
} WAppIcon;
WAppIcon *wAppIconCreate(WWindow *leader_win);
WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance,
char *wm_class, int tile);
void wAppIconDestroy(WAppIcon *aicon);
void wAppIconPaint(WAppIcon *aicon);
Bool wAppIconChangeImage(WAppIcon *icon, char *file);
void wAppIconMove(WAppIcon *aicon, int x, int y);
#ifdef REDUCE_APPICONS
unsigned int wAppIconReduceAppCount(WApplication *wapp);
#endif
#endif

486
src/application.c Normal file
View File

@@ -0,0 +1,486 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "WindowMaker.h"
#include "menu.h"
#include "window.h"
#include "icon.h"
#include "appicon.h"
#include "application.h"
#include "appmenu.h"
#include "properties.h"
#include "funcs.h"
#include "stacking.h"
#include "actions.h"
#include "defaults.h"
#include "workspace.h"
#include "dock.h"
#ifdef WMSOUND
#include "wmsound.h"
#endif
/******** Global variables ********/
extern XContext wAppWinContext;
extern XContext wWinContext;
extern WPreferences wPreferences;
extern WDDomain *WDWindowAttributes;
/******** Local variables ********/
static WWindow*
makeMainWindow(WScreen *scr, Window window)
{
WWindow *wwin;
XWindowAttributes attr;
if (!XGetWindowAttributes(dpy, window, &attr)) {
return NULL;
}
wwin = wWindowCreate();
wwin->screen_ptr = scr;
wwin->client_win = window;
wwin->main_window = window;
wwin->wm_hints = XGetWMHints(dpy, window);
/* if (!MyXFetchName(dpy, window, &(wwin->frame->title))) {
wwin->frame->title = NULL;
}
*/
PropGetWMClass(window, &wwin->wm_class, &wwin->wm_instance);
wDefaultFillAttributes(scr, wwin->wm_instance, wwin->wm_class,
&wwin->window_flags, True);
XSelectInput(dpy, window, attr.your_event_mask | PropertyChangeMask
| StructureNotifyMask );
return wwin;
}
WApplication*
wApplicationOf(Window window)
{
WApplication *wapp;
if (window == None)
return NULL;
if (XFindContext(dpy, window, wAppWinContext, (XPointer*)&wapp)!=XCSUCCESS)
return NULL;
return wapp;
}
static WAppIcon*
findDockIconFor(WDock *dock, Window main_window)
{
WAppIcon *aicon = NULL;
aicon = wDockFindIconFor(dock, main_window);
if (!aicon) {
wDockTrackWindowLaunch(dock, main_window);
aicon = wDockFindIconFor(dock, main_window);
}
return aicon;
}
static void
extractIcon(WWindow *wwin)
{
int argc;
char **argv;
if (!XGetCommand(dpy, wwin->client_win, &argv, &argc) || argc < 1)
return;
wApplicationExtractDirPackIcon(wwin->screen_ptr,argv[0],
wwin->wm_instance,
wwin->wm_class);
XFreeStringList(argv);
}
void
wApplicationExtractDirPackIcon(WScreen *scr, char *path,
char *wm_instance, char *wm_class)
{
char *iconPath=NULL;
/* Maybe the app is a .app and it has an icon in it, like
* /usr/local/GNUstep/Apps/WPrefs.app/WPrefs.tiff
*/
if (strstr(path, ".app")) {
char *tmp;
tmp = wmalloc(strlen(path)+16);
if (scr->flags.supports_tiff) {
strcpy(tmp, path);
strcat(tmp, ".tiff");
if (access(tmp, R_OK)==0)
iconPath = tmp;
}
if (!path) {
strcpy(tmp, path);
strcat(tmp, ".xpm");
if (access(tmp, R_OK)==0)
iconPath = tmp;
}
if (!iconPath)
free(tmp);
}
if (iconPath) {
proplist_t dict = WDWindowAttributes->dictionary;
proplist_t adict, key, iconk;
proplist_t val;
char *tmp;
int i;
i = 0;
if (wm_instance)
i += strlen(wm_instance);
if (wm_class)
i += strlen(wm_class);
tmp = wmalloc(i+8);
*tmp = 0;
if (wm_class && wm_instance) {
sprintf(tmp, "%s.%s", wm_instance, wm_class);
} else {
if (wm_instance)
strcat(tmp, wm_instance);
if (wm_class)
strcat(tmp, wm_class);
}
key = PLMakeString(tmp);
free(tmp);
adict = PLGetDictionaryEntry(dict, key);
iconk = PLMakeString("Icon");
if (adict) {
val = PLGetDictionaryEntry(adict, iconk);
} else {
/* no dictionary for app, so create one */
adict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
PLInsertDictionaryEntry(dict, key, adict);
PLRelease(adict);
val = NULL;
}
if (!val) {
val = PLMakeString(iconPath);
PLInsertDictionaryEntry(adict, iconk, val);
PLRelease(val);
}
PLRelease(key);
if (val)
PLSave(dict, YES);
free(iconPath);
}
}
WApplication*
wApplicationCreate(WScreen *scr, Window main_window)
{
WApplication *wapp;
WWindow *leader;
if (main_window==None || main_window==scr->root_win) {
#ifdef DEBUG0
wwarning("trying to create application for %x",(unsigned)main_window);
#endif
return NULL;
}
{
Window root;
int foo;
unsigned int bar;
/* check if the window is valid */
if (!XGetGeometry(dpy, main_window, &root, &foo, &foo, &bar, &bar,
&bar, &bar)) {
return NULL;
}
}
wapp = wApplicationOf(main_window);
if (wapp) {
wapp->refcount++;
return wapp;
}
wapp = wmalloc(sizeof(WApplication));
memset(wapp, 0, sizeof(WApplication));
wapp->refcount = 1;
wapp->last_focused = NULL;
wapp->last_workspace = 0;
wapp->main_window = main_window;
wapp->main_window_desc = makeMainWindow(scr, main_window);
if (!wapp->main_window_desc) {
free(wapp);
return NULL;
}
extractIcon(wapp->main_window_desc);
leader = wWindowFor(main_window);
if (leader) {
leader->main_window = main_window;
}
wapp->menu = wAppMenuGet(scr, main_window);
/*
* Set application wide attributes from the leader.
*/
wapp->flags.hidden = wapp->main_window_desc->window_flags.start_hidden;
wapp->flags.emulated = wapp->main_window_desc->window_flags.emulate_appicon;
/* application descriptor */
XSaveContext(dpy, main_window, wAppWinContext, (XPointer)wapp);
if (!wapp->main_window_desc->window_flags.no_appicon) {
wapp->app_icon = NULL;
if (scr->last_dock)
wapp->app_icon = findDockIconFor(scr->last_dock, main_window);
/* check main dock if we did not find it in last dock */
if (!wapp->app_icon && scr->dock)
wapp->app_icon = findDockIconFor(scr->dock, main_window);
/* finally check clips */
if (!wapp->app_icon) {
int i;
for (i=0; i<scr->workspace_count; i++) {
WDock *dock = scr->workspaces[i]->clip;
if (dock)
wapp->app_icon = findDockIconFor(dock, main_window);
if (wapp->app_icon)
break;
}
}
if (wapp->app_icon) {
WWindow *mainw = wapp->main_window_desc;
wapp->app_icon->running = 1;
wapp->app_icon->icon->force_paint = 1;
wapp->app_icon->icon->owner = mainw;
if (mainw->wm_hints && (mainw->wm_hints->flags&IconWindowHint))
wapp->app_icon->icon->icon_win = mainw->wm_hints->icon_window;
wAppIconPaint(wapp->app_icon);
} else {
wapp->app_icon = wAppIconCreate(wapp->main_window_desc);
#ifdef REDUCE_APPICONS
/* This is so we get the appearance of invoking the app sitting
* on the dock. -cls */
if (wapp->app_icon) {
if (wapp->app_icon->docked && wapp->app_icon->num_apps == 1) {
wapp->app_icon->launching = 0;
wapp->app_icon->running = 1;
wapp->app_icon->icon->force_paint = 1;
wAppIconPaint(wapp->app_icon);
}
}
#endif
}
} else {
wapp->app_icon = NULL;
}
if (wapp->app_icon) {
wapp->app_icon->main_window = main_window;
#ifdef WMSOUND
wSoundServerGrab(wapp->app_icon->wm_class, main_window);
#endif
}
#ifndef REDUCE_APPICONS
if (wapp->app_icon && !wapp->app_icon->docked) {
#else
if (wapp->app_icon && !wapp->app_icon->docked && wapp->app_icon->num_apps == 1) {
#endif
WIcon *icon = wapp->app_icon->icon;
WDock *clip = scr->workspaces[scr->current_workspace]->clip;
int x=0, y=0;
if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) {
wapp->app_icon->attracted = 1;
if (!clip->keep_attracted && !wapp->app_icon->icon->shadowed) {
wapp->app_icon->icon->shadowed = 1;
wapp->app_icon->icon->force_paint = 1;
/* We don't do an wAppIconPaint() here because it's in
* wDockAttachIcon(). -Dan
*/
}
wDockAttachIcon(clip, wapp->app_icon, x, y);
} else {
PlaceIcon(scr, &x, &y);
wAppIconMove(wapp->app_icon, x, y);
#ifndef STRICTNS
wLowerFrame(icon->core);
#endif
}
if (!clip || !wapp->app_icon->attracted || !clip->collapsed)
XMapWindow(dpy, icon->core->window);
}
if (wPreferences.auto_arrange_icons && wapp->app_icon && !wapp->app_icon->attracted) {
wArrangeIcons(scr, True);
}
wapp->prev = NULL;
wapp->next = scr->wapp_list;
if (scr->wapp_list)
scr->wapp_list->prev = wapp;
scr->wapp_list = wapp;
#ifdef WMSOUND
wSoundPlay(WMSOUND_APPSTART);
#endif
#ifdef DEBUG
printf("Created application for %x\n", (unsigned)main_window);
#endif
return wapp;
}
void
wApplicationDestroy(WApplication *wapp)
{
Window main_window;
WWindow *wwin;
WScreen *scr;
#ifdef REDUCE_APPICONS
unsigned int napps;
#endif
if (!wapp)
return;
wapp->refcount--;
if (wapp->refcount>0)
return;
scr = wapp->main_window_desc->screen_ptr;
main_window = wapp->main_window;
#ifdef REDUCE_APPICONS
napps = wAppIconReduceAppCount(wapp);
#endif
if (wapp == scr->wapp_list) {
if (wapp->next)
wapp->next->prev = NULL;
scr->wapp_list = wapp->next;
} else {
if (wapp->next)
wapp->next->prev = wapp->prev;
if (wapp->prev)
wapp->prev->next = wapp->next;
}
XDeleteContext(dpy, wapp->main_window, wAppWinContext);
wAppMenuDestroy(wapp->menu);
if (wapp->app_icon) {
if (wapp->app_icon->docked
&& (!wapp->app_icon->attracted ||
wapp->app_icon->dock->keep_attracted)) {
#ifdef REDUCE_APPICONS
if (napps == 0) {
#endif
wapp->app_icon->running = 0;
/* since we keep it, we don't care if it was attracted or not */
wapp->app_icon->attracted = 0;
wapp->app_icon->icon->shadowed = 0;
wapp->app_icon->main_window = None;
wapp->app_icon->pid = 0;
wapp->app_icon->icon->owner = NULL;
wapp->app_icon->icon->icon_win = None;
wapp->app_icon->icon->force_paint = 1;
wAppIconPaint(wapp->app_icon);
#ifdef REDUCE_APPICONS
}
#endif
} else if (wapp->app_icon->docked) {
#ifdef REDUCE_APPICONS
if (napps == 0) {
#endif
wapp->app_icon->running = 0;
wDockDetach(wapp->app_icon->dock, wapp->app_icon);
#ifdef REDUCE_APPICONS
}
#endif
} else {
#ifdef REDUCE_APPICONS
if (napps == 0) {
#endif
wAppIconDestroy(wapp->app_icon);
#ifdef REDUCE_APPICONS
}
#endif
}
}
wwin = wWindowFor(wapp->main_window_desc->client_win);
wWindowDestroy(wapp->main_window_desc);
if (wwin) {
/* undelete client window context that was deleted in
* wWindowDestroy */
XSaveContext(dpy, wwin->client_win, wWinContext,
(XPointer)&wwin->client_descriptor);
}
free(wapp);
#ifdef DEBUG
printf("Destroyed application for %x\n", (unsigned)main_window);
#endif
if (wPreferences.auto_arrange_icons) {
wArrangeIcons(scr, True);
}
#ifdef WMSOUND
wSoundPlay(WMSOUND_APPEXIT);
#endif
}

74
src/application.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMAPPLICATION_H_
#define WMAPPLICATION_H_
/* for tracking single application instances */
typedef struct WApplication {
struct WApplication *next;
struct WApplication *prev;
Window main_window; /* ID of the group leader */
struct WWindow *main_window_desc; /* main (leader) window descriptor */
WMenu *menu; /* application menu */
struct WAppIcon *app_icon;
int refcount;
struct WWindow *last_focused; /* focused window before hide */
int last_workspace; /* last workspace used to work on the
* app */
struct {
unsigned int skip_next_animation:1;
unsigned int hidden:1;
unsigned int emulated:1;
} flags;
} WApplication;
WApplication *wApplicationCreate(WScreen *scr, Window main_window);
void wApplicationDestroy(WApplication *wapp);
WApplication *wApplicationOf(Window window);
void wApplicationExtractDirPackIcon(WScreen *scr,char *path, char *wm_instance,
char *wm_class);
#ifdef NEWAPPICON
# define wApplicationActivate(wapp) {\
wapp->main_window_desc->flags.focused=1; \
wAppIconPaint(wapp->app_icon);\
}
#define wApplicationDeactivate(wapp) {\
wapp->main_window_desc->flags.focused=0;\
wAppIconPaint(wapp->app_icon);\
}
#endif
#endif

337
src/appmenu.c Normal file
View File

@@ -0,0 +1,337 @@
/* appmenu.c- application defined menu
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "menu.h"
#include "actions.h"
#include "funcs.h"
#include "framewin.h"
/******** Global Variables **********/
extern Atom _XA_WINDOWMAKER_MENU;
extern Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
extern Time LastTimestamp;
extern WPreferences wPreferences;
typedef struct {
short code;
short tag;
Window window;
} WAppMenuData;
enum {
wmBeginMenu = 1,
wmEndMenu = 2,
wmNormalItem = 10,
wmDoubleItem = 11,
wmSubmenuItem = 12
};
enum {
wmSelectItem = 1
};
static void
sendMessage(Window window, int what, int tag)
{
XEvent event;
event.xclient.type = ClientMessage;
event.xclient.message_type = _XA_WINDOWMAKER_MENU;
event.xclient.format = 32;
event.xclient.display = dpy;
event.xclient.window = window;
event.xclient.data.l[0] = LastTimestamp;
event.xclient.data.l[1] = what;
event.xclient.data.l[2] = tag;
event.xclient.data.l[3] = 0;
XSendEvent(dpy, window, False, NoEventMask, &event);
XFlush(dpy);
}
static void
notifyClient(WMenu *menu, WMenuEntry *entry)
{
WAppMenuData *data = entry->clientdata;
sendMessage(data->window, wmSelectItem, data->tag);
}
static WMenu*
parseMenuCommand(WScreen *scr, Window win, char **slist, int count, int *index)
{
WMenu *menu;
int command;
int code, pos;
char title[300];
char rtext[300];
if (strlen(slist[*index])>300) {
wwarning("appmenu: menu command size exceeded in window %x", win);
return NULL;
}
if (sscanf(slist[*index], "%i %i %n", &command, &code, &pos)<2
|| command!=wmBeginMenu) {
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
strcpy(title, &slist[*index][pos]);
menu = wMenuCreateForApp(scr, title, *index==1);
if (!menu)
return NULL;
*index += 1;
while (*index<count) {
int ecode, etag, enab;
if (sscanf(slist[*index], "%i", &command)!=1) {
wMenuDestroy(menu, True);
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
if (command==wmEndMenu) {
*index += 1;
break;
} else if (command==wmNormalItem
|| command==wmDoubleItem) {
WAppMenuData *data;
WMenuEntry *entry;
if (command == wmNormalItem) {
if (sscanf(slist[*index], "%i %i %i %i %n",
&command, &ecode, &etag, &enab, &pos)!=4
|| ecode!=code) {
wMenuDestroy(menu, True);
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
strcpy(title, &slist[*index][pos]);
rtext[0] = 0;
} else {
if (sscanf(slist[*index], "%i %i %i %i %s %n",
&command, &ecode, &etag, &enab, rtext, &pos)!=5
|| ecode!=code) {
wMenuDestroy(menu, True);
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
strcpy(title, &slist[*index][pos]);
}
if (!(data = malloc(sizeof(WAppMenuData)))) {
wwarning("appmenu: out of memory making menu for window %x",
win);
wMenuDestroy(menu, True);
return NULL;
}
data->code = code;
data->tag = etag;
data->window = win;
entry = wMenuAddCallback(menu, title, notifyClient, data);
if (!entry) {
wMenuDestroy(menu, True);
wwarning("appmenu: out of memory creating menu for window %x",
slist[*index], win);
free(data);
return NULL;
}
if (rtext[0]!=0)
entry->rtext = wstrdup(rtext);
else
entry->rtext = NULL;
entry->free_cdata = free;
*index += 1;
} else if (command==wmSubmenuItem) {
int ncode;
WMenuEntry *entry;
WMenu *submenu;
if (sscanf(slist[*index], "%i %i %i %i %i %n",
&command, &ecode, &etag, &enab, &ncode, &pos)!=5
|| ecode!=code) {
wMenuDestroy(menu, True);
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
strcpy(title, &slist[*index][pos]);
*index += 1;
submenu = parseMenuCommand(scr, win, slist, count, index);
entry = wMenuAddCallback(menu, title, NULL, NULL);
if (!entry) {
wMenuDestroy(menu, True);
wMenuDestroy(submenu, True);
wwarning("appmenu: out of memory creating menu for window %x",
slist[*index], win);
return NULL;
}
wMenuEntrySetCascade(menu, entry, submenu);
} else {
wMenuDestroy(menu, True);
wwarning("appmenu: bad menu entry \"%s\" in window %x",
slist[*index], win);
return NULL;
}
}
return menu;
}
WMenu*
wAppMenuGet(WScreen *scr, Window window)
{
XTextProperty text_prop;
int count, i;
char **slist;
WMenu *menu;
if (!XGetTextProperty(dpy, window, &text_prop, _XA_WINDOWMAKER_MENU)) {
return NULL;
}
if (!XTextPropertyToStringList(&text_prop, &slist, &count) || count<1) {
XFree(text_prop.value);
return NULL;
}
XFree(text_prop.value);
if (strcmp(slist[0], "WMMenu 0")!=0) {
wwarning("appmenu: unknown version of WMMenu in window %x: %s",
window, slist[0]);
XFreeStringList(slist);
return NULL;
}
i = 1;
menu = parseMenuCommand(scr, window, slist, count, &i);
if (menu)
menu->parent = NULL;
XFreeStringList(slist);
return menu;
}
void
wAppMenuDestroy(WMenu *menu)
{
if (menu)
wMenuDestroy(menu, True);
}
static void
mapmenus(WMenu *menu)
{
int i;
if (menu->flags.mapped)
XMapWindow(dpy, menu->frame->core->window);
if (menu->brother->flags.mapped)
XMapWindow(dpy, menu->brother->frame->core->window);
for (i=0; i<menu->cascade_no; i++) {
if (menu->cascades[i])
mapmenus(menu->cascades[i]);
}
}
void
wAppMenuMap(WMenu *menu, WWindow *wwin)
{
if (!menu)
return;
if (!menu->flags.mapped) {
wMenuMap(menu);
}
if(wwin && (wPreferences.focus_mode!=WKF_CLICK)) {
int x, min;
min = 20; /* Keep at least 20 pixels visible */
if( wwin->frame_x > min ) {
x = wwin->frame_x - menu->frame->core->width;
}
else {
x = min - menu->frame->core->width;
}
wMenuMove(menu, x, wwin->frame_y, True);
}
mapmenus(menu);
}
static void
unmapmenus(WMenu *menu)
{
int i;
if (menu->flags.mapped)
XUnmapWindow(dpy, menu->frame->core->window);
if (menu->brother->flags.mapped)
XUnmapWindow(dpy, menu->brother->frame->core->window);
for (i=0; i<menu->cascade_no; i++) {
if (menu->cascades[i])
unmapmenus(menu->cascades[i]);
}
}
void
wAppMenuUnmap(WMenu *menu)
{
if (menu)
unmapmenus(menu);
}

33
src/appmenu.h Normal file
View File

@@ -0,0 +1,33 @@
/* appmenu.h- application defined menu
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef _WAPPMENU_H_
#define _WAPPMENU_H_
WMenu *wAppMenuGet(WScreen *scr, Window window);
void wAppMenuDestroy(WMenu *menu);
void wAppMenuMap(WMenu *menu, WWindow *wwin);
void wAppMenuUnmap(WMenu *menu);
#endif

482
src/balloon.c Normal file
View File

@@ -0,0 +1,482 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#ifdef BALLOON_TEXT
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef SHAPED_BALLOON
#include <X11/extensions/shape.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "screen.h"
#include "texture.h"
#include "wcore.h"
#include "framewin.h"
#include "icon.h"
#include "appicon.h"
#include "funcs.h"
#include "workspace.h"
#include "balloon.h"
extern WPreferences wPreferences;
typedef struct _WBalloon {
Window window;
#ifdef SHAPED_BALLOON
GC monoGC;
#endif
int prevType;
Window objectWindow;
char *text;
int h;
WMHandlerID timer;
Pixmap contents;
char mapped;
char ignoreTimer;
} WBalloon;
#define TOP 0
#define BOTTOM 1
#define LEFT 0
#define RIGHT 2
#define TLEFT (TOP|LEFT)
#define TRIGHT (TOP|RIGHT)
#define BLEFT (BOTTOM|LEFT)
#define BRIGHT (BOTTOM|RIGHT)
#ifdef SHAPED_BALLOON
#define SPACE 12
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
static void
drawBalloon(Pixmap pix, GC gc, int x, int y, int w, int h, int side)
{
int rad = h*3/10;
XPoint pt[3];
XFillArc(dpy, pix, gc, x, y, rad, rad, 90*64, 90*64);
XFillArc(dpy, pix, gc, x, y+h-1-rad, rad, rad, 180*64, 90*64);
XFillArc(dpy, pix, gc, x+w-1-rad, y, rad, rad, 0*64, 90*64);
XFillArc(dpy, pix, gc, x+w-1-rad, y+h-1-rad, rad, rad, 270*64, 90*64);
XFillRectangle(dpy, pix, gc, x, y+rad/2, w, h-rad);
XFillRectangle(dpy, pix, gc, x+rad/2, y, w-rad, h);
if (side & BOTTOM) {
pt[0].y = y+h-1;
pt[1].y = y+h-1+SPACE;
pt[2].y = y+h-1;
} else {
pt[0].y = y;
pt[1].y = y-SPACE;
pt[2].y = y;
}
if (side & RIGHT) {
pt[0].x = x+w-h+2*h/16;
pt[1].x = x+w-h+11*h/16;
pt[2].x = x+w-h+7*h/16;
} else {
pt[0].x = x+h-2*h/16;
pt[1].x = x+h-11*h/16;
pt[2].x = x+h-7*h/16;
}
XFillPolygon(dpy, pix, gc, pt, 3, Convex, CoordModeOrigin);
}
static Pixmap
makePixmap(WScreen *scr, int width, int height, int side, Pixmap *mask)
{
WBalloon *bal = scr->balloon;
Pixmap bitmap;
Pixmap pixmap;
int x, y;
bitmap = XCreatePixmap(dpy, scr->root_win, width+SPACE, height+SPACE, 1);
if (!bal->monoGC) {
bal->monoGC = XCreateGC(dpy, bitmap, 0, NULL);
}
XSetForeground(dpy, bal->monoGC, scr->black_pixel);
XFillRectangle(dpy, bitmap, bal->monoGC, 0, 0, width+SPACE, height+SPACE);
pixmap = XCreatePixmap(dpy, scr->root_win, width+SPACE, height+SPACE,
scr->w_depth);
XSetForeground(dpy, scr->draw_gc, scr->black_pixel);
XFillRectangle(dpy, pixmap, scr->draw_gc, 0, 0, width+SPACE, height+SPACE);
if (side & BOTTOM) {
y = 0;
} else {
y = SPACE;
}
x = 0;
XSetForeground(dpy, bal->monoGC, scr->white_pixel);
drawBalloon(bitmap, bal->monoGC, x, y, width, height, side);
XSetForeground(dpy, scr->draw_gc, scr->white_pixel);
drawBalloon(pixmap, scr->draw_gc, x+1, y+1, width-2, height-2, side);
*mask = bitmap;
return pixmap;
}
static void
showText(WScreen *scr, int x, int y, int h, int w, char *text)
{
int width;
int height;
Pixmap pixmap;
Pixmap mask;
WFont *font = scr->info_text_font;
int side = 0;
int ty;
int bx, by;
if (scr->balloon->contents)
XFreePixmap(dpy, scr->balloon->contents);
width = wTextWidth(font->font, text, strlen(text))+16;
height = font->height + 4;
if (height < 16)
height = 16;
if (width < height)
width = height;
if (x + width > scr->scr_width) {
side = RIGHT;
bx = x - width + w/2;
if (bx < 0)
bx = 0;
} else {
side = LEFT;
bx = x + w/2;
}
if (bx + width > scr->scr_width)
bx = scr->scr_width - width;
if (y - (height + SPACE) < 0) {
side |= TOP;
by = y+h-1;
ty = SPACE;
} else {
side |= BOTTOM;
by = y - (height + SPACE);
ty = 0;
}
pixmap = makePixmap(scr, width, height, side, &mask);
XSetForeground(dpy, scr->info_text_gc, scr->black_pixel);
wDrawString(pixmap, font, scr->info_text_gc, 8,
ty + font->y + (height - font->height)/2,
text, strlen(text));
XSetWindowBackgroundPixmap(dpy, scr->balloon->window, pixmap);
scr->balloon->contents = pixmap;
XResizeWindow(dpy, scr->balloon->window, width, height+SPACE);
XShapeCombineMask(dpy, scr->balloon->window, ShapeBounding, 0, 0, mask,
ShapeSet);
XFreePixmap(dpy, mask);
XMoveWindow(dpy, scr->balloon->window, bx, by);
XMapRaised(dpy, scr->balloon->window);
scr->balloon->mapped = 1;
}
#else /* !SHAPED_BALLOON */
static void
showText(WScreen *scr, int x, int y, int h, int w, char *text)
{
int width;
int height;
Pixmap pixmap;
WFont *font = scr->info_text_font;
if (scr->balloon->contents)
XFreePixmap(dpy, scr->balloon->contents);
width = wTextWidth(font->font, text, strlen(text))+8;
height = font->height + 4;
if (x < 0)
x = 0;
else if (x + width > scr->scr_width-1)
x = scr->scr_width - width;
if (y - height - 2 < 0) {
y += h;
if (y < 0)
y = 0;
} else {
y -= height + 2;
}
if (scr->window_title_texture[0])
XSetForeground(dpy, scr->draw_gc,
scr->window_title_texture[0]->any.color.pixel);
else
XSetForeground(dpy, scr->draw_gc, scr->light_pixel);
pixmap = XCreatePixmap(dpy, scr->root_win, width, height, scr->w_depth);
XFillRectangle(dpy, pixmap, scr->draw_gc, 0, 0, width, height);
XSetForeground(dpy, scr->info_text_gc, scr->window_title_pixel[0]);
wDrawString(pixmap, font->font, scr->info_text_gc, 4, font->y+2, text,
strlen(text));
XResizeWindow(dpy, scr->balloon->window, width, height);
XMoveWindow(dpy, scr->balloon->window, x, y);
XSetWindowBackgroundPixmap(dpy, scr->balloon->window, pixmap);
XClearWindow(dpy, scr->balloon->window);
XMapRaised(dpy, scr->balloon->window);
scr->balloon->contents = pixmap;
scr->balloon->mapped = 1;
}
#endif /* !SHAPED_BALLOON */
static void
showBalloon(WScreen *scr)
{
int x, y;
Window foow;
unsigned foo, w;
if (scr->balloon) {
scr->balloon->timer = NULL;
scr->balloon->ignoreTimer = 1;
}
if (!XGetGeometry(dpy, scr->balloon->objectWindow, &foow, &x, &y,
&w, &foo, &foo, &foo)) {
scr->balloon->prevType = 0;
return;
}
showText(scr, x, y, scr->balloon->h, w, scr->balloon->text);
}
static void
frameBalloon(WObjDescriptor *object)
{
WFrameWindow *fwin = (WFrameWindow*)object->parent;
WScreen *scr = fwin->core->screen_ptr;
if (fwin->titlebar != object->self
|| !fwin->flags.is_client_window_frame) {
wBalloonHide(scr);
return;
}
if (fwin->title && fwin->flags.incomplete_title) {
scr->balloon->h = (fwin->titlebar ? fwin->titlebar->height : 0);
scr->balloon->text = wstrdup(fwin->title);
scr->balloon->objectWindow = fwin->core->window;
scr->balloon->timer = WMAddTimerHandler(BALLOON_DELAY,
(WMCallback*)showBalloon, scr);
}
}
static void
miniwindowBalloon(WObjDescriptor *object)
{
WIcon *icon = (WIcon*)object->parent;
WScreen *scr = icon->core->screen_ptr;
if (!icon->icon_name) {
wBalloonHide(scr);
return;
}
scr->balloon->h = icon->core->height;
scr->balloon->text = wstrdup(icon->icon_name);
scr->balloon->objectWindow = icon->core->window;
if (scr->balloon->prevType == object->parent_type
&& scr->balloon->ignoreTimer) {
XUnmapWindow(dpy, scr->balloon->window);
showBalloon(scr);
} else {
scr->balloon->timer = WMAddTimerHandler(BALLOON_DELAY,
(WMCallback*)showBalloon, scr);
}
}
static void
appiconBalloon(WObjDescriptor *object)
{
WAppIcon *aicon = (WAppIcon*)object->parent;
WScreen *scr = aicon->icon->core->screen_ptr;
char *tmp;
if (aicon->command && aicon->wm_class) {
tmp = wmalloc(strlen(aicon->command)+strlen(aicon->wm_class)+8);
sprintf(tmp, "%s (%s)", aicon->wm_class, aicon->command);
scr->balloon->text = tmp;
} else if (aicon->command) {
scr->balloon->text = wstrdup(aicon->command);
} else if (aicon->wm_class) {
scr->balloon->text = wstrdup(aicon->wm_class);
} else {
wBalloonHide(scr);
return;
}
scr->balloon->h = aicon->icon->core->height-2;
scr->balloon->objectWindow = aicon->icon->core->window;
if (scr->balloon->prevType == object->parent_type
&& scr->balloon->ignoreTimer) {
XUnmapWindow(dpy, scr->balloon->window);
showBalloon(scr);
} else {
scr->balloon->timer = WMAddTimerHandler(BALLOON_DELAY,
(WMCallback*)showBalloon, scr);
}
}
void
wBalloonInitialize(WScreen *scr)
{
WBalloon *bal;
XSetWindowAttributes attribs;
unsigned long vmask;
bal = wmalloc(sizeof(WBalloon));
memset(bal, 0, sizeof(WBalloon));
scr->balloon = bal;
vmask = CWSaveUnder|CWOverrideRedirect|CWColormap;
attribs.save_under = True;
attribs.override_redirect = True;
attribs.colormap = scr->w_colormap;
bal->window = XCreateWindow(dpy, scr->root_win, 1, 1, 10, 10, 1,
scr->w_depth, CopyFromParent,
scr->w_visual, vmask, &attribs);
#if 0
/* select EnterNotify to so that the balloon will be unmapped
* when the pointer is moved over it */
XSelectInput(dpy, bal->window, EnterWindowMask);
#endif
}
void
wBalloonEnteredObject(WScreen *scr, WObjDescriptor *object)
{
WBalloon *balloon = scr->balloon;
if (balloon->timer) {
WMDeleteTimerHandler(balloon->timer);
balloon->timer = NULL;
balloon->ignoreTimer = 0;
}
if (scr->balloon->text)
free(scr->balloon->text);
scr->balloon->text = NULL;
if (!object) {
wBalloonHide(scr);
balloon->ignoreTimer = 0;
return;
}
switch (object->parent_type) {
case WCLASS_FRAME:
if (wPreferences.window_balloon) {
frameBalloon(object);
}
break;
case WCLASS_DOCK_ICON:
if (object->parent != scr->clip_icon && wPreferences.appicon_balloon)
appiconBalloon(object);
break;
case WCLASS_MINIWINDOW:
if (wPreferences.miniwin_balloon) {
miniwindowBalloon(object);
}
break;
case WCLASS_APPICON:
if (wPreferences.appicon_balloon)
appiconBalloon(object);
break;
default:
wBalloonHide(scr);
break;
}
scr->balloon->prevType = object->parent_type;
}
void
wBalloonHide(WScreen *scr)
{
if (scr) {
if (scr->balloon->mapped) {
XUnmapWindow(dpy, scr->balloon->window);
scr->balloon->mapped = 0;
} else if (scr->balloon->timer) {
WMDeleteTimerHandler(scr->balloon->timer);
scr->balloon->timer = NULL;
}
scr->balloon->prevType = 0;
}
}
#endif

31
src/balloon.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef _BALLOON_H_
#define _BALLOON_H_
void wBalloonInitialize(WScreen *scr);
void wBalloonEnteredObject(WScreen *scr, WObjDescriptor *object);
void wBalloonHide(WScreen *scr);
#endif

702
src/client.c Normal file
View File

@@ -0,0 +1,702 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
#include "properties.h"
#include "actions.h"
#include "icon.h"
#include "client.h"
#include "funcs.h"
#include "stacking.h"
#include "appicon.h"
#include "appmenu.h"
/****** Global Variables ******/
/* contexts */
extern XContext wWinContext;
extern Atom _XA_WM_STATE;
extern Atom _XA_WM_PROTOCOLS;
extern Atom _XA_WM_COLORMAP_WINDOWS;
extern Atom _XA_WINDOWMAKER_MENU;
extern Atom _XA_GNUSTEP_WM_ATTR;
extern Atom _XA_GNUSTEP_WM_RESIZEBAR;
/*
*--------------------------------------------------------------------
* wClientRestore--
* Reparent the window back to the root window.
*
*--------------------------------------------------------------------
*/
void
wClientRestore(WWindow *wwin)
{
int gx, gy;
wClientGetGravityOffsets(wwin, &gx, &gy);
/* set the positio of the frame on screen */
wwin->frame_x -= gx * (wwin->old_border_width - FRAME_BORDER_WIDTH);
wwin->frame_y -= gy * (wwin->old_border_width - FRAME_BORDER_WIDTH);
/* if gravity is to the south, account for the border sizes */
if (gy > 0)
wwin->frame_y += (wwin->frame->top_width + wwin->frame->bottom_width);
XUnmapWindow(dpy, wwin->client_win);
XSetWindowBorderWidth(dpy, wwin->client_win, wwin->old_border_width);
XReparentWindow(dpy, wwin->client_win, wwin->screen_ptr->root_win,
wwin->frame_x, wwin->frame_y);
if (wwin->flags.mapped)
XMapWindow(dpy, wwin->client_win);
/* don't let the window get iconified after restart */
if (wwin->flags.shaded)
wClientSetState(wwin, NormalState, None);
}
/*
*----------------------------------------------------------------------
* wClientSetState--
* Set the state of the client window to one of the window
* states defined in ICCCM (Iconic, Withdrawn, Normal)
*
* Side effects:
* The WM_STATE property of the window is updated as well as the
* WWindow.state variable.
*----------------------------------------------------------------------
*/
void
wClientSetState(WWindow *wwin, int state, Window icon_win)
{
unsigned long data[2];
wwin->state = state;
data[0] = (unsigned long) state;
data[1] = (unsigned long) icon_win;
XChangeProperty(dpy, wwin->client_win, _XA_WM_STATE, _XA_WM_STATE, 32,
PropModeReplace, (unsigned char *) data, 2);
}
void
wClientGetGravityOffsets(WWindow *wwin, int *ofs_x, int *ofs_y)
{
switch (wwin->normal_hints->win_gravity) {
case ForgetGravity:
case CenterGravity:
case StaticGravity:
*ofs_x = 0;
*ofs_y = 0;
break;
case NorthWestGravity:
*ofs_x = -1;
*ofs_y = -1;
break;
case NorthGravity:
*ofs_x = 0;
*ofs_y = -1;
break;
case NorthEastGravity:
*ofs_x = 1;
*ofs_y = -1;
break;
case WestGravity:
*ofs_x = -1;
*ofs_y = 0;
break;
case EastGravity:
*ofs_x = 1;
*ofs_y = 0;
break;
case SouthWestGravity:
*ofs_x = -1;
*ofs_y = 1;
break;
case SouthGravity:
*ofs_x = 0;
*ofs_y = 1;
break;
case SouthEastGravity:
*ofs_x = 1;
*ofs_y = 1;
break;
}
}
void
wClientConfigure(WWindow *wwin, XConfigureRequestEvent *xcre)
{
XWindowChanges xwc;
int nx, ny, nwidth, nheight;
int ofs_x, ofs_y;
if (wwin==NULL) {
/*
* configure a window that was not mapped by us
*/
xwc.x = xcre->x;
xwc.y = xcre->y;
xwc.width = xcre->width;
xwc.height = xcre->height;
xwc.border_width = xcre->border_width;
xwc.stack_mode = xcre->detail;
xwc.sibling = xcre->above;
XConfigureWindow(dpy, xcre->window, xcre->value_mask, &xwc);
return;
}
#ifdef SHAPE
{
int junk;
unsigned int ujunk;
int b_shaped;
XShapeSelectInput(dpy, wwin->client_win, ShapeNotifyMask);
XShapeQueryExtents(dpy, wwin->client_win, &b_shaped, &junk, &junk,
&ujunk, &ujunk, &junk, &junk, &junk, &ujunk,
&ujunk);
wwin->flags.shaped = b_shaped;
}
#endif
if (xcre->value_mask & CWStackMode) {
WObjDescriptor *desc;
WWindow *sibling;
if ((xcre->value_mask & CWSibling) &&
(XFindContext(dpy, xcre->above, wWinContext,
(XPointer *)&desc) == XCSUCCESS)
&& (desc->parent_type==WCLASS_WINDOW)) {
sibling=desc->parent;
xwc.sibling = sibling->frame->core->window;
} else {
xwc.sibling = xcre->above;
}
xwc.stack_mode = xcre->detail;
XConfigureWindow(dpy, wwin->frame->core->window,
xcre->value_mask & (CWSibling | CWStackMode), &xwc);
/* fix stacking order */
RemakeStackList(wwin->screen_ptr);
}
wClientGetGravityOffsets(wwin, &ofs_x, &ofs_y);
if (xcre->value_mask & CWBorderWidth) {
wwin->old_border_width = xcre->border_width;
}
if (!wwin->flags.shaded) {
/* If the window is shaded, wrong height will be set for the window */
if (xcre->value_mask & CWX)
nx = xcre->x - FRAME_BORDER_WIDTH;
else
nx = wwin->frame_x;
if (xcre->value_mask & CWY)
ny = xcre->y - FRAME_BORDER_WIDTH - ((ofs_y < 0) ? 0 : wwin->frame->top_width);
else
ny = wwin->frame_y;
if (xcre->value_mask & CWWidth)
nwidth = xcre->width;
else
nwidth = wwin->frame->core->width;
if (xcre->value_mask & CWHeight)
nheight = xcre->height;
else
nheight = wwin->frame->core->height - wwin->frame->top_width - wwin->frame->bottom_width;
wWindowConfigure(wwin, nx, ny, nwidth, nheight);
wwin->old_geometry.x = nx;
wwin->old_geometry.y = ny;
wwin->old_geometry.width = nwidth;
wwin->old_geometry.height = nheight;
}
}
void
wClientSendProtocol(WWindow *wwin, Atom protocol, Time time)
{
XEvent event;
event.xclient.type = ClientMessage;
event.xclient.message_type = _XA_WM_PROTOCOLS;
event.xclient.format = 32;
event.xclient.display = dpy;
event.xclient.window = wwin->client_win;
event.xclient.data.l[0] = protocol;
event.xclient.data.l[1] = time;
event.xclient.data.l[2] = 0;
event.xclient.data.l[3] = 0;
XSendEvent(dpy, wwin->client_win, False, NoEventMask, &event);
XSync(dpy, False);
}
void
wClientKill(WWindow *wwin)
{
XKillClient(dpy, wwin->client_win);
XFlush(dpy);
}
/*
*----------------------------------------------------------------------
* wClientCheckProperty--
* Handles PropertyNotify'es, verifying which property was
* changed and updating internal state according to that, like redrawing
* the icon title when it is changed.
*
* Side effects:
* Depends on the changed property.
*
* TODO: CLIENT_LEADER, _GNUSTEP_WM_ATTR
*----------------------------------------------------------------------
*/
void
wClientCheckProperty(WWindow *wwin, XPropertyEvent *event)
{
XWindowAttributes attribs;
XWMHints *new_hints;
int i, g1, g2;
char *tmp;
switch (event->atom) {
case XA_WM_NAME:
/* window title was changed */
if (wwin->frame) {
if (!wFetchName(dpy, wwin->client_win, &tmp)) {
/* the hint was removed */
tmp = wstrdup(DEF_WINDOW_TITLE);
}
if (wFrameWindowChangeTitle(wwin->frame, tmp)) {
/* only update the menu if the title has actually changed */
UpdateSwitchMenu(wwin->screen_ptr, wwin, ACTION_CHANGE);
}
if (tmp)
free(tmp);
}
break;
case XA_WM_ICON_NAME:
if (!wwin->icon)
break;
else {
char *new_title;
/* icon title was changed */
wGetIconName(dpy, wwin->client_win, &new_title);
wIconChangeTitle(wwin->icon, new_title);
}
break;
case XA_WM_COMMAND:
if (wwin->main_window!=None) {
WApplication *wapp = wApplicationOf(wwin->main_window);
char **argv;
int argc;
if (wapp && wapp->app_icon) {
if (wapp->app_icon->command!=NULL)
free(wapp->app_icon->command);
if (XGetCommand(dpy, wwin->main_window, &argv, &argc)) {
if (argc > 0 && argv != NULL)
wapp->app_icon->command = FlattenStringList(argv,argc);
if (argv) {
XFreeStringList(argv);
}
}
}
}
break;
case XA_WM_HINTS:
/* WM_HINTS */
new_hints = XGetWMHints(dpy, wwin->client_win);
/* group leader update
*
* This means that the window is setting the leader after
* it was mapped, changing leaders or removing the leader.
*
* Valid state transitions are:
*
* _1 __2
* / \ / \
* v | v |
* (GC) (GC')
* / ^ / ^
* 3| |4 5| |6
* | | | |
* v / v /
* (G'C) (G'C')
*
* Where G is the window_group hint, C is CLIENT_LEADER property
* and ' indicates the hint is unset.
*
* 1,2 - change group leader to new value of window_group
* 3 - change leader to value of CLIENT_LEADER
* 4 - change leader to value of window_group
* 5 - destroy application
* 6 - create application
*/
if (new_hints && (new_hints->flags & WindowGroupHint)
&& new_hints->window_group!=None) {
g2 = 1;
} else {
g2 = 0;
}
if (wwin->wm_hints && (wwin->wm_hints->flags & WindowGroupHint)
&& wwin->wm_hints->window_group!=None) {
g1 = 1;
} else {
g1 = 0;
}
if (wwin->client_leader) {
if (g1 && g2
&& wwin->wm_hints->window_group!=new_hints->window_group) {
i = 1;
} else if (g1 && !g2) {
i = 3;
} else if (!g1 && g2) {
i = 4;
} else {
i = 0;
}
} else {
if (g1 && g2
&& wwin->wm_hints->window_group!=new_hints->window_group) {
i = 2;
} else if (g1 && !g2) {
i = 5;
} else if (!g1 && g2) {
i = 6;
} else {
i = 0;
}
}
if (wwin->wm_hints)
XFree(wwin->wm_hints);
wwin->wm_hints = new_hints;
/* do action according to state transition */
switch (i) {
/* 3 - change leader to value of CLIENT_LEADER */
case 3:
wApplicationDestroy(wApplicationOf(wwin->main_window));
wwin->main_window = wwin->client_leader;
wwin->group_id = None;
wApplicationCreate(wwin->screen_ptr, wwin->main_window);
break;
/* 1,2,4 - change leader to new value of window_group */
case 1:
case 2:
case 4:
wApplicationDestroy(wApplicationOf(wwin->main_window));
wwin->main_window = new_hints->window_group;
wwin->group_id = wwin->main_window;
wApplicationCreate(wwin->screen_ptr, wwin->main_window);
break;
/* 5 - destroy application */
case 5:
wApplicationDestroy(wApplicationOf(wwin->main_window));
wwin->main_window = None;
wwin->group_id = None;
break;
/* 6 - create application */
case 6:
wwin->main_window = new_hints->window_group;
wwin->group_id = wwin->main_window;
wApplicationCreate(wwin->screen_ptr, wwin->main_window);
break;
}
#ifdef DEBUG
if (i) {
printf("window leader update caused state transition %i\n",i);
}
#endif
if (wwin->wm_hints) {
/* update icon */
if ((wwin->wm_hints->flags & IconPixmapHint)
|| (wwin->wm_hints->flags & IconWindowHint)) {
WApplication *wapp;
if (wwin->flags.miniaturized) {
wIconUpdate(wwin->icon);
}
wapp = wApplicationOf(wwin->main_window);
if (wapp && wapp->app_icon) {
wIconUpdate(wapp->app_icon->icon);
}
}
if (wwin->wm_hints->flags & UrgencyHint)
wwin->flags.urgent = 1;
else
wwin->flags.urgent = 0;
} else {
wwin->group_id = None;
}
break;
case XA_WM_NORMAL_HINTS:
/* normal (geometry) hints */
XGetWindowAttributes(dpy, wwin->client_win, &attribs);
GetNormalHints(wwin, &attribs, False);
break;
case XA_WM_TRANSIENT_FOR:
{
Window new_owner;
WWindow *owner;
if (!XGetTransientForHint(dpy, wwin->client_win, &new_owner)) {
new_owner = None;
} else {
if (new_owner==0 || new_owner == wwin->client_win) {
new_owner = wwin->screen_ptr->root_win;
}
}
if (new_owner!=wwin->transient_for) {
owner = wWindowFor(wwin->transient_for);
if (owner) {
if (owner->flags.semi_focused) {
owner->flags.semi_focused = 0;
if ((owner->flags.mapped || owner->flags.shaded)
&& owner->frame)
wFrameWindowPaint(owner->frame);
}
}
owner = wWindowFor(new_owner);
if (owner) {
if (!owner->flags.semi_focused) {
owner->flags.semi_focused = 1;
if ((owner->flags.mapped || owner->flags.shaded)
&& owner->frame)
wFrameWindowPaint(owner->frame);
}
}
wwin->transient_for = new_owner;
if (new_owner==None) {
if (wwin->window_flags.no_miniaturizable) {
wwin->window_flags.no_miniaturizable = 0;
wwin->window_flags.no_miniaturize_button = 0;
if (wwin->frame)
wWindowConfigureBorders(wwin);
}
} else if (!wwin->window_flags.no_miniaturizable) {
wwin->window_flags.no_miniaturizable = 1;
wwin->window_flags.no_miniaturize_button = 1;
if (wwin->frame)
wWindowConfigureBorders(wwin);
}
}
}
break;
default:
if (event->atom==_XA_WM_PROTOCOLS) {
PropGetProtocols(wwin->client_win, &wwin->protocols);
if (wwin->protocols.DELETE_WINDOW) {
wwin->window_flags.kill_close = 0;
} else {
wwin->window_flags.kill_close = 1;
}
if (wwin->frame)
wWindowUpdateButtonImages(wwin);
} else if (event->atom==_XA_WM_COLORMAP_WINDOWS) {
GetColormapWindows(wwin);
wColormapInstallForWindow(wwin->screen_ptr, wwin);
} else if (event->atom==_XA_WINDOWMAKER_MENU) {
WApplication *wapp;
wapp = wApplicationOf(wwin->main_window);
if (wapp) {
if (wapp->menu) {
/* update menu */
/* TODO: remake appmenu update */
wAppMenuDestroy(wapp->menu);
}
wapp->menu = wAppMenuGet(wwin->screen_ptr, wwin->main_window);
/* make the appmenu be mapped */
wSetFocusTo(wwin->screen_ptr, NULL);
wSetFocusTo(wwin->screen_ptr,
wwin->screen_ptr->focused_window);
}
} else if (event->atom==_XA_GNUSTEP_WM_ATTR) {
GNUstepWMAttributes *attr;
PropGetGNUstepWMAttr(wwin->client_win, &attr);
wWindowUpdateGNUstepAttr(wwin, attr);
XFree(attr);
}
}
}
/*
*----------------------------------------------------------------------
* GetNormalHints--
* Get size (normal) hints and a default geometry for the client
* window. The hints are also checked for inconsistency.
*
* Side effects:
* normal_hints is filled with valid data and geometry information
* about the client is also changed.
*----------------------------------------------------------------------
*/
void
GetNormalHints(WWindow *wwin, XWindowAttributes *wattribs, int geometry)
{
int pre_icccm=0;
/* find a position for the window */
if (!wwin->normal_hints)
wwin->normal_hints = XAllocSizeHints();
if (!PropGetNormalHints(wwin->client_win, wwin->normal_hints, &pre_icccm)) {
wwin->normal_hints->flags = 0;
}
wwin->client.x = wattribs->x;
wwin->client.y = wattribs->y;
wwin->client.width = wattribs->width;
wwin->client.height = wattribs->height;
if (!(wwin->normal_hints->flags & PWinGravity)) {
wwin->normal_hints->win_gravity = NorthWestGravity;
}
if (!(wwin->normal_hints->flags & PMinSize)) {
wwin->normal_hints->min_width = MIN_WINDOW_SIZE;
wwin->normal_hints->min_height = MIN_WINDOW_SIZE;
}
if (!(wwin->normal_hints->flags & PBaseSize)) {
wwin->normal_hints->base_width = 0;
wwin->normal_hints->base_height = 0;
}
if (!(wwin->normal_hints->flags & PMaxSize)) {
wwin->normal_hints->max_width = wwin->screen_ptr->scr_width*2;
wwin->normal_hints->max_height = wwin->screen_ptr->scr_height*2;
}
if (!(wwin->normal_hints->flags & PResizeInc)) {
wwin->normal_hints->width_inc = 1;
wwin->normal_hints->height_inc = 1;
} else {
if (wwin->normal_hints->width_inc <= 0)
wwin->normal_hints->width_inc = 1;
if (wwin->normal_hints->height_inc <= 0)
wwin->normal_hints->height_inc = 1;
}
if (wwin->normal_hints->flags & PAspect) {
if (wwin->normal_hints->min_aspect.x < 1)
wwin->normal_hints->min_aspect.x = 1;
if (wwin->normal_hints->min_aspect.y < 1)
wwin->normal_hints->min_aspect.y = 1;
if (wwin->normal_hints->max_aspect.x < 1)
wwin->normal_hints->max_aspect.x = 1;
if (wwin->normal_hints->max_aspect.y < 1)
wwin->normal_hints->max_aspect.y = 1;
}
if (wwin->normal_hints->min_width <= 0)
wwin->normal_hints->min_width = MIN_WINDOW_SIZE;
if (wwin->normal_hints->min_height <= 0)
wwin->normal_hints->min_height = MIN_WINDOW_SIZE;
if (wwin->normal_hints->min_height > wwin->normal_hints->max_height) {
wwin->normal_hints->min_height = wwin->normal_hints->max_height;
}
if (wwin->normal_hints->min_width > wwin->normal_hints->max_width) {
wwin->normal_hints->min_width = wwin->normal_hints->max_width;
}
/* pre ICCCM (old) client */
if (pre_icccm && !wwin->screen_ptr->flags.startup && geometry) {
#ifdef DEBUG
printf("PRE ICCCM\n");
#endif
if (wwin->normal_hints->flags & (USPosition|PPosition)) {
wwin->client.x = wwin->normal_hints->x;
wwin->client.y = wwin->normal_hints->y;
}
if (wwin->normal_hints->flags & (USSize|PSize)) {
wwin->client.width = wwin->normal_hints->width;
wwin->client.height = wwin->normal_hints->height;
}
}
}
void
GetColormapWindows(WWindow *wwin)
{
if (wwin->cmap_windows) {
XFree(wwin->cmap_windows);
}
if (!XGetWMColormapWindows(dpy, wwin->client_win, &(wwin->cmap_windows),
&(wwin->cmap_window_no))) {
wwin->cmap_window_no = 0;
wwin->cmap_windows = NULL;
}
}

38
src/client.h Normal file
View File

@@ -0,0 +1,38 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMCLIENT_H_
#define WMCLIENT_H_
void wClientSetState(WWindow *wwin, int state, Window icon_win);
void wClientRestore(WWindow *wwin);
void wClientConfigure(WWindow *wwin, XConfigureRequestEvent *xcre);
void wClientGetGravityOffsets(WWindow *wwin, int *ofs_x, int *ofs_y);
void wClientSendProtocol(WWindow *wwin, Atom protocol, Time time);
void wClientKill(WWindow *wwin);
void wClientCheckProperty(WWindow *wwin, XPropertyEvent *event);
void GetNormalHints(WWindow *wwin, XWindowAttributes *wattribs, int geometry);
void GetColormapWindows(WWindow *wwin);
#endif

111
src/colormap.c Normal file
View File

@@ -0,0 +1,111 @@
/* colormap.c - colormap handling code
*
* WindowMaker window manager
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* This code slightly based on fvwm code,
* Copyright (c) Rob Nation and others
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include "WindowMaker.h"
#include <X11/Xatom.h>
#include "window.h"
void
wColormapInstallForWindow(WScreen *scr, WWindow *wwin)
{
int i;
XWindowAttributes attributes;
int done = 0;
Window xwin = None;
if(wwin) {
xwin = wwin->client_win;
} else {
xwin = scr->root_win;
}
scr->cmap_window = wwin;
if (scr->root_colormap_install_count > 0) {
scr->original_cmap_window = wwin;
return;
}
/* install colormap for all windows of the client */
if (wwin && wwin->cmap_window_no > 0) {
for (i = wwin->cmap_window_no - 1; i >= 0; i--) {
Window w;
w = wwin->cmap_windows[i];
if (w == wwin->client_win)
done = 1;
XGetWindowAttributes(dpy, w, &attributes);
if (attributes.colormap == None)
attributes.colormap = scr->colormap;
if (scr->current_colormap != attributes.colormap) {
scr->current_colormap = attributes.colormap;
XInstallColormap(dpy, attributes.colormap);
}
}
}
if (!done) {
XGetWindowAttributes(dpy, xwin, &attributes);
if (attributes.colormap == None)
attributes.colormap = scr->colormap;
if (scr->current_colormap != attributes.colormap) {
scr->current_colormap = attributes.colormap;
XInstallColormap(dpy, attributes.colormap);
}
}
}
void
wColormapInstallRoot(WScreen *scr)
{
if (scr->root_colormap_install_count == 0) {
wColormapInstallForWindow(scr, NULL);
scr->original_cmap_window = scr->cmap_window;
}
scr->root_colormap_install_count++;
}
void
wColormapUninstallRoot(WScreen *scr)
{
if (scr->root_colormap_install_count > 0)
scr->root_colormap_install_count--;
if (scr->root_colormap_install_count == 0) {
wColormapInstallForWindow(scr, scr->original_cmap_window);
scr->original_cmap_window = NULL;
}
}

111
src/config.h Normal file
View File

@@ -0,0 +1,111 @@
/* src/config.h. Generated automatically by configure. */
/* src/config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
/* #undef C_ALLOCA */
/* Define to empty if the keyword does not work. */
/* #undef const */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#define HAVE_ALLOCA_H 1
/* Define if you don't have vprintf but do have _doprnt. */
/* #undef HAVE_DOPRNT */
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1
/* Define if you have the vprintf function. */
#define HAVE_VPRINTF 1
/* Define to `int' if <sys/types.h> doesn't define. */
/* #undef pid_t */
/* Define if you need to in order for stat and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define as the return type of signal handlers (int or void). */
#define RETSIGTYPE void
/* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define if `sys_siglist' is declared by <signal.h>. */
#define SYS_SIGLIST_DECLARED 1
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define if the X Window System is missing or not being used. */
/* #undef X_DISPLAY_MISSING */
/* define to the path to cpp */
#define CPP_PATH "/lib/cpp"
/* package name */
#define PACKAGE "WindowMaker"
/* package version */
#define VERSION "0.20.1"
/* Define if you have the gethostname function. */
#define HAVE_GETHOSTNAME 1
/* Define if you have the gettimeofday function. */
#define HAVE_GETTIMEOFDAY 1
/* Define if you have the poll function. */
#define HAVE_POLL 1
/* Define if you have the select function. */
#define HAVE_SELECT 1
/* Define if you have the setpgid function. */
#define HAVE_SETPGID 1
/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
/* Define if you have the strncasecmp function. */
#define HAVE_STRNCASECMP 1
/* Define if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define if you have the <libintl.h> header file. */
#define HAVE_LIBINTL_H 1
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
/* Define if you have the <sys/select.h> header file. */
/* #undef HAVE_SYS_SELECT_H */
/* Define if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1

110
src/config.h.in Normal file
View File

@@ -0,0 +1,110 @@
/* src/config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to empty if the keyword does not work. */
#undef const
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define if you have the vprintf function. */
#undef HAVE_VPRINTF
/* Define to `int' if <sys/types.h> doesn't define. */
#undef pid_t
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if `sys_siglist' is declared by <signal.h>. */
#undef SYS_SIGLIST_DECLARED
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if the X Window System is missing or not being used. */
#undef X_DISPLAY_MISSING
/* define to the path to cpp */
#undef CPP_PATH
/* package name */
#undef PACKAGE
/* package version */
#undef VERSION
/* Define if you have the gethostname function. */
#undef HAVE_GETHOSTNAME
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the poll function. */
#undef HAVE_POLL
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the setpgid function. */
#undef HAVE_SETPGID
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strncasecmp function. */
#undef HAVE_STRNCASECMP
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <libintl.h> header file. */
#undef HAVE_LIBINTL_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H

100
src/def_pixmaps.h Normal file
View File

@@ -0,0 +1,100 @@
/* diamond mark */
#define MENU_RADIO_INDICATOR_XBM_SIZE 9
static unsigned char MENU_RADIO_INDICATOR_XBM_DATA[] = {
0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xee, 0x00, 0xc7, 0x01, 0xee, 0x00,
0x7c, 0x00, 0x38, 0x00, 0x10, 0x00};
/* check mark */
#define MENU_CHECK_INDICATOR_XBM_SIZE 9
static unsigned char MENU_CHECK_INDICATOR_XBM_DATA[] = {
0x00, 0x01, 0x83, 0x01, 0xc3, 0x00, 0x63, 0x00, 0x33, 0x00, 0x1b, 0x00,
0x0f, 0x00, 0x07, 0x00, 0x03, 0x00};
#define MENU_MINI_INDICATOR_XBM_SIZE 9
static unsigned char MENU_MINI_INDICATOR_XBM_DATA[] = {
0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0xff, 0x01};
#define MENU_HIDE_INDICATOR_XBM_SIZE 9
static unsigned char MENU_HIDE_INDICATOR_XBM_DATA[] = {
0x99, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x01, 0x33, 0x01};
#define MENU_SHADE_INDICATOR_XBM_SIZE 9
static unsigned char MENU_SHADE_INDICATOR_XBM_DATA[] = {
0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* button pixmaps */
/* the first one is for normal state, the second is for when
* the button is pushed */
static char *PRED_CLOSE_XPM[] = {
"10 10 3 1",
" c #000000",
". c #616561",
"X c None",
" .XXXXXX. ",
". .XXXX. .",
"X. .XX. .X",
"XX. .. .XX",
"XXX. .XXX",
"XXX. .XXX",
"XX. .. .XX",
"X. .XX. .X",
". .XXXX. .",
" .XXXXXX. "};
static char *PRED_BROKEN_CLOSE_XPM[] = {
"10 10 3 1",
" c #000000",
". c #616561",
"X c None",
" .XXXXXX. ",
". .XXXX. .",
"X. XXXX .X",
"XXXXXXXXXX",
"XXXXXXXXXX",
"XXXXXXXXXX",
"XXXXXXXXXX",
"X. XXXX .X",
". .XXXX. .",
" .XXXXXX. "};
static char *PRED_KILL_XPM[] = {
"10 10 3 1",
" c #000000",
". c #616561",
"X c None",
" .XXXXXX. ",
". XXXXXX .",
"XXXXXXXXXX",
"XXX .. XXX",
"XXX. .XXX",
"XXX. .XXX",
"XXX .. XXX",
"XXXXXXXXXX",
". XXXXXX .",
" .XXXXXX. "};
static char *PRED_ICONIFY_XPM[] = {
" 10 10 2 1",
". c #000000",
"# c None",
"..........",
"..........",
"..........",
".########.",
".########.",
".########.",
".########.",
".########.",
".########.",
".........."
};

3250
src/defaults.c Normal file

File diff suppressed because it is too large Load Diff

63
src/defaults.h Normal file
View File

@@ -0,0 +1,63 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMDEFAULTS_H_
#define WMDEFAULTS_H_
typedef struct WDDomain {
char *domain_name;
proplist_t dictionary;
char *path;
time_t timestamp;
} WDDomain;
#if 0
proplist_t wDefaultsInit(int screen_number);
#endif
WDDomain*wDefaultsInitDomain(char *domain, Bool requireDictionary);
void wDefaultsDestroyDomain(WDDomain *domain);
void wReadDefaults(WScreen *scr, proplist_t new_dict);
void wDefaultUpdateIcons(WScreen *scr);
void wReadStaticDefaults(proplist_t dict);
void wDefaultsCheckDomains(void *screen);
void wSaveDefaults(WScreen *scr);
char *wDefaultGetIconFile(WScreen *scr, char *instance, char *class,
Bool noDefault);
RImage*wDefaultGetImage(WScreen *scr, char *winstance, char *wclass);
void wDefaultFillAttributes(WScreen *scr, char *instance, char *class,
WWindowAttributes *attr, Bool useGlobalDefault);
int wDefaultGetStartWorkspace(WScreen *scr, char *instance, char *class);
void wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file);
#endif /* WMDEFAULTS_H_ */

888
src/dialog.c Normal file
View File

@@ -0,0 +1,888 @@
/* dialog.c - dialog windows for internal use
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX DEFAULT_PATH_MAX
#endif
#include "WindowMaker.h"
#include "GNUstep.h"
#include "screen.h"
#include "dialog.h"
#include "funcs.h"
#include "stacking.h"
#include "framewin.h"
#include "window.h"
#include "actions.h"
extern WPreferences wPreferences;
int
wMessageDialog(WScreen *scr, char *title, char *message,
char *defBtn, char *altBtn, char *othBtn)
{
WMAlertPanel *panel;
Window parent;
WWindow *wwin;
int result;
panel = WMCreateAlertPanel(scr->wmscreen, NULL, title, message,
defBtn, altBtn, othBtn);
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 400, 180, 0, 0, 0);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
wwin = wManageInternalWindow(scr, parent, None, NULL,
(scr->scr_width - 400)/2,
(scr->scr_height - 180)/2, 400, 180);
wwin->client_leader = WMWidgetXID(panel->win);
WMMapWidget(panel->win);
wWindowMap(wwin);
while (!panel->done) {
XEvent event;
WMNextEvent(dpy, &event);
WMHandleEvent(&event);
}
result = panel->result;
WMUnmapWidget(panel->win);
wUnmanageWindow(wwin, False);
WMDestroyAlertPanel(panel);
XDestroyWindow(dpy, parent);
return result;
}
int
wInputDialog(WScreen *scr, char *title, char *message, char **text)
{
WWindow *wwin;
Window parent;
WMInputPanel *panel;
char *result;
panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text,
_("OK"), _("Cancel"));
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
wwin = wManageInternalWindow(scr, parent, None, NULL,
(scr->scr_width - 320)/2,
(scr->scr_height - 160)/2, 320, 160);
wwin->client_leader = WMWidgetXID(panel->win);
WMMapWidget(panel->win);
wWindowMap(wwin);
while (!panel->done) {
XEvent event;
WMNextEvent(dpy, &event);
WMHandleEvent(&event);
}
if (panel->result == WAPRDefault)
result = WMGetTextFieldText(panel->text);
else
result = NULL;
wUnmanageWindow(wwin, False);
WMDestroyInputPanel(panel);
XDestroyWindow(dpy, parent);
if (result==NULL)
return WDB_CANCEL;
else {
if (*text)
free(*text);
*text = result;
return WDB_OK;
}
}
/*
*****************************************************************
* Icon Selection Panel
*****************************************************************
*/
typedef struct IconPanel {
WScreen *scr;
WMWindow *win;
WMLabel *dirLabel;
WMLabel *iconLabel;
WMList *dirList;
WMList *iconList;
WMLabel *iconView;
WMLabel *fileLabel;
WMTextField *fileField;
WMButton *okButton;
WMButton *cancelButton;
#if 0
WMButton *chooseButton;
#endif
short done;
short result;
} IconPanel;
static void
listPixmaps(WScreen *scr, WMList *lPtr, char *path)
{
struct dirent *dentry;
DIR *dir;
char pbuf[PATH_MAX+16];
char *apath;
apath = wexpandpath(path);
dir = opendir(apath);
if (!dir) {
char *msg;
char *tmp;
tmp = _("Could not open directory ");
msg = wmalloc(strlen(tmp)+strlen(path)+6);
strcpy(msg, tmp);
strcat(msg, path);
wMessageDialog(scr, _("Error"), msg, _("OK"), NULL, NULL);
free(msg);
free(apath);
return;
}
/* list contents in the column */
while ((dentry = readdir(dir))) {
struct stat statb;
if (strcmp(dentry->d_name, ".")==0 ||
strcmp(dentry->d_name, "..")==0)
continue;
strcpy(pbuf, apath);
strcat(pbuf, "/");
strcat(pbuf, dentry->d_name);
if (stat(pbuf, &statb)<0)
continue;
if (statb.st_mode & (S_IRUSR|S_IRGRP|S_IROTH)
&& statb.st_mode & (S_IFREG|S_IFLNK)) {
WMAddSortedListItem(lPtr, dentry->d_name);
}
}
closedir(dir);
free(apath);
}
static void
setViewedImage(IconPanel *panel, char *file)
{
WMPixmap *pixmap;
RColor color;
color.red = 0xae;
color.green = 0xaa;
color.blue = 0xae;
color.alpha = 0;
pixmap = WMCreateBlendedPixmapFromFile(WMWidgetScreen(panel->win),
file, &color);
if (!pixmap) {
char *msg;
char *tmp;
WMSetButtonEnabled(panel->okButton, False);
tmp = _("Could not load image file ");
msg = wmalloc(strlen(tmp)+strlen(file)+6);
strcpy(msg, tmp);
strcat(msg, file);
wMessageDialog(panel->scr, _("Error"), msg, _("OK"), NULL, NULL);
free(msg);
WMSetLabelImage(panel->iconView, NULL);
} else {
WMSetButtonEnabled(panel->okButton, True);
WMSetLabelImage(panel->iconView, pixmap);
WMReleasePixmap(pixmap);
}
}
static void
listCallback(void *self, void *data)
{
WMList *lPtr = (WMList*)self;
IconPanel *panel = (IconPanel*)data;
char *path;
if (lPtr==panel->dirList) {
path = WMGetListSelectedItem(lPtr)->text;
WMSetTextFieldText(panel->fileField, path);
WMSetLabelImage(panel->iconView, NULL);
WMSetButtonEnabled(panel->okButton, False);
WMClearList(panel->iconList);
listPixmaps(panel->scr, panel->iconList, path);
} else {
char *tmp, *iconFile;
path = WMGetListSelectedItem(panel->dirList)->text;
tmp = wexpandpath(path);
iconFile = WMGetListSelectedItem(panel->iconList)->text;
path = wmalloc(strlen(tmp)+strlen(iconFile)+4);
strcpy(path, tmp);
strcat(path, "/");
strcat(path, iconFile);
free(tmp);
WMSetTextFieldText(panel->fileField, path);
setViewedImage(panel, path);
free(path);
}
}
static void
listIconPaths(WMList *lPtr)
{
int i;
for (i=0; wPreferences.icon_path[i]!=NULL; i++) {
char *tmp;
tmp = wexpandpath(wPreferences.icon_path[i]);
/* do not sort, because the order implies the order of
* directories searched */
if (access(tmp, X_OK)==0)
WMAddListItem(lPtr, wPreferences.icon_path[i]);
free(tmp);
}
}
static void
buttonCallback(void *self, void *clientData)
{
WMButton *bPtr = (WMButton*)self;
IconPanel *panel = (IconPanel*)clientData;
if (bPtr==panel->okButton) {
panel->done = True;
panel->result = True;
} else if (bPtr==panel->cancelButton) {
panel->done = True;
panel->result = False;
}
#if 0
else if (bPtr==panel->chooseButton) {
WMOpenPanel *op;
op = WMCreateOpenPanel(WMWidgetScreen(bPtr));
if (WMRunModalOpenPanelForDirectory(op, NULL, "/usr/local", NULL, NULL)) {
char *path;
path = WMGetFilePanelFile(op);
WMSetTextFieldText(panel->fileField, path);
setViewedImage(panel, path);
free(path);
}
WMDestroyFilePanel(op);
}
#endif
}
Bool
wIconChooserDialog(WScreen *scr, char **file)
{
WWindow *wwin;
Window parent;
IconPanel *panel;
WMColor *color;
WMFont *boldFont;
panel = wmalloc(sizeof(IconPanel));
memset(panel, 0, sizeof(IconPanel));
panel->scr = scr;
panel->win = WMCreateWindow(scr->wmscreen, "iconChooser");
WMResizeWidget(panel->win, 450, 280);
boldFont = WMBoldSystemFontOfSize(scr->wmscreen, 12);
panel->dirLabel = WMCreateLabel(panel->win);
WMResizeWidget(panel->dirLabel, 200, 20);
WMMoveWidget(panel->dirLabel, 10, 7);
WMSetLabelText(panel->dirLabel, _("Directories"));
WMSetLabelFont(panel->dirLabel, boldFont);
WMSetLabelTextAlignment(panel->dirLabel, WACenter);
WMSetLabelRelief(panel->dirLabel, WRSunken);
panel->iconLabel = WMCreateLabel(panel->win);
WMResizeWidget(panel->iconLabel, 140, 20);
WMMoveWidget(panel->iconLabel, 215, 7);
WMSetLabelText(panel->iconLabel, _("Icons"));
WMSetLabelFont(panel->iconLabel, boldFont);
WMSetLabelTextAlignment(panel->iconLabel, WACenter);
WMReleaseFont(boldFont);
color = WMWhiteColor(scr->wmscreen);
WMSetLabelTextColor(panel->dirLabel, color);
WMSetLabelTextColor(panel->iconLabel, color);
WMReleaseColor(color);
color = WMDarkGrayColor(scr->wmscreen);
WMSetWidgetBackgroundColor(panel->iconLabel, color);
WMSetWidgetBackgroundColor(panel->dirLabel, color);
WMReleaseColor(color);
WMSetLabelRelief(panel->iconLabel, WRSunken);
panel->dirList = WMCreateList(panel->win);
WMResizeWidget(panel->dirList, 200, 170);
WMMoveWidget(panel->dirList, 10, 30);
WMSetListAction(panel->dirList, listCallback, panel);
panel->iconList = WMCreateList(panel->win);
WMResizeWidget(panel->iconList, 140, 170);
WMMoveWidget(panel->iconList, 215, 30);
WMSetListAction(panel->iconList, listCallback, panel);
panel->iconView = WMCreateLabel(panel->win);
WMResizeWidget(panel->iconView, 75, 75);
WMMoveWidget(panel->iconView, 365, 60);
WMSetLabelImagePosition(panel->iconView, WIPImageOnly);
WMSetLabelRelief(panel->iconView, WRSunken);
panel->fileLabel = WMCreateLabel(panel->win);
WMResizeWidget(panel->fileLabel, 80, 20);
WMMoveWidget(panel->fileLabel, 10, 210);
WMSetLabelText(panel->fileLabel, _("File Name:"));
panel->fileField = WMCreateTextField(panel->win);
WMResizeWidget(panel->fileField, 345, 20);
WMMoveWidget(panel->fileField, 95, 210);
WMSetTextFieldEnabled(panel->fileField, False);
panel->okButton = WMCreateCommandButton(panel->win);
WMResizeWidget(panel->okButton, 80, 26);
WMMoveWidget(panel->okButton, 360, 240);
WMSetButtonText(panel->okButton, _("OK"));
WMSetButtonEnabled(panel->okButton, False);
WMSetButtonAction(panel->okButton, buttonCallback, panel);
panel->cancelButton = WMCreateCommandButton(panel->win);
WMResizeWidget(panel->cancelButton, 80, 26);
WMMoveWidget(panel->cancelButton, 270, 240);
WMSetButtonText(panel->cancelButton, _("Cancel"));
WMSetButtonAction(panel->cancelButton, buttonCallback, panel);
#if 0
panel->chooseButton = WMCreateCommandButton(panel->win);
WMResizeWidget(panel->chooseButton, 110, 26);
WMMoveWidget(panel->chooseButton, 150, 240);
WMSetButtonText(panel->chooseButton, _("Choose File"));
WMSetButtonAction(panel->chooseButton, buttonCallback, panel);
#endif
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 450, 280, 0, 0, 0);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
wwin = wManageInternalWindow(scr, parent, None, _("Icon Chooser"),
(scr->scr_width - 450)/2,
(scr->scr_height - 280)/2, 450, 280);
/* put icon paths in the list */
listIconPaths(panel->dirList);
WMMapWidget(panel->win);
wWindowMap(wwin);
while (!panel->done) {
XEvent event;
WMNextEvent(dpy, &event);
WMHandleEvent(&event);
}
if (panel->result) {
char *defaultPath, *wantedPath;
/* check if the file the user selected is not the one that
* would be loaded by default with the current search path */
*file = WMGetListSelectedItem(panel->iconList)->text;
if ((*file)[0]==0) {
free(*file);
*file = NULL;
} else {
defaultPath = FindImage(wPreferences.icon_path, *file);
wantedPath = WMGetTextFieldText(panel->fileField);
/* if the file is not the default, use full path */
if (strcmp(wantedPath, defaultPath)!=0) {
*file = wantedPath;
} else {
*file = wstrdup(*file);
free(wantedPath);
}
free(defaultPath);
}
} else {
*file = NULL;
}
WMUnmapWidget(panel->win);
WMDestroyWidget(panel->win);
wUnmanageWindow(wwin, False);
free(panel);
XDestroyWindow(dpy, parent);
return panel->result;
}
/*
***********************************************************************
* Info Panel
***********************************************************************
*/
typedef struct {
WScreen *scr;
WWindow *wwin;
WMWindow *win;
WMLabel *logoL;
WMLabel *name1L;
WMLabel *name2L;
WMLabel *versionL;
WMLabel *infoL;
WMLabel *copyrL;
} InfoPanel;
#define COPYRIGHT_TEXT \
"Copyright \xa9 1997, 1998 Alfredo K. Kojima <kojima@windowmaker.org>\n"\
"Copyright \xa9 1998 Dan Pascu <dan@windowmaker.org>"
static InfoPanel *thePanel = NULL;
static void
destroyInfoPanel(WCoreWindow *foo, void *data, XEvent *event)
{
WMUnmapWidget(thePanel);
WMDestroyWidget(thePanel->win);
wUnmanageWindow(thePanel->wwin, False);
free(thePanel);
thePanel = NULL;
}
WMPixmap*
renderText(WMScreen *scr, char *text, char *font, RColor *from, RColor *to)
{
WMPixmap *wpix = NULL;
RImage *gradient = NULL;
Pixmap grad = None;
Pixmap mask = None;
RContext *rc = WMScreenRContext(scr);
XFontStruct *f = NULL;
int w, h;
GC gc = None;
f = XLoadQueryFont(dpy, font);
if (!f)
return NULL;
w = XTextWidth(f, text, strlen(text));
h = f->ascent+f->descent;
gradient = RRenderGradient(w, h, from, to, RVerticalGradient);
if (!gradient) {
wwarning("error doing image processing:%s", RErrorString);
goto bye;
}
if (!RConvertImage(rc, gradient, &grad)) {
wwarning("error doing image processing:%s", RErrorString);
goto bye;
}
mask = XCreatePixmap(dpy, rc->drawable, w, h, 1);
gc = XCreateGC(dpy, mask, 0, NULL);
XSetForeground(dpy, gc, rc->black);
XSetFont(dpy, gc, f->fid);
XFillRectangle(dpy, mask, gc, 0, 0, w, h);
XSetForeground(dpy, gc, rc->white);
XDrawString(dpy, mask, gc, 0, f->ascent, text, strlen(text));
XSetLineAttributes(dpy, gc, 3, LineSolid, CapRound, JoinMiter);
XDrawLine(dpy, mask, gc, 0, h-2, w, h-2);
wpix = WMCreatePixmapFromXPixmaps(scr, grad, mask, w, h, rc->depth);
bye:
if (gc)
XFreeGC(dpy, gc);
XFreeFont(dpy, f);
if (gradient)
RDestroyImage(gradient);
return wpix;
}
void
wShowInfoPanel(WScreen *scr)
{
InfoPanel *panel;
WMPixmap *logo;
WMSize size;
WMFont *font;
char version[32];
char buffer[256];
Window parent;
WWindow *wwin;
RColor color1, color2;
char **strl;
int i;
char *visuals[] = {
"StaticGray",
"GrayScale",
"StaticColor",
"PseudoColor",
"TrueColor",
"DirectColor"
};
if (thePanel) {
wRaiseFrame(thePanel->wwin->frame->core);
wSetFocusTo(scr, thePanel->wwin);
return;
}
panel = wmalloc(sizeof(InfoPanel));
panel->scr = scr;
panel->win = WMCreateWindow(scr->wmscreen, "info");
WMResizeWidget(panel->win, 382, 230);
logo = WMGetApplicationIconImage(scr->wmscreen);
if (logo) {
size = WMGetPixmapSize(logo);
panel->logoL = WMCreateLabel(panel->win);
WMResizeWidget(panel->logoL, 64, 64);
WMMoveWidget(panel->logoL, 30, 20);
WMSetLabelImagePosition(panel->logoL, WIPImageOnly);
WMSetLabelImage(panel->logoL, logo);
}
panel->name1L = WMCreateLabel(panel->win);
WMResizeWidget(panel->name1L, 200, 30);
WMMoveWidget(panel->name1L, 120, 30);
color1.red = 0;
color1.green = 0;
color1.blue = 0;
color2.red = 0x80;
color2.green = 0x80;
color2.blue = 0x80;
logo = renderText(scr->wmscreen, " WindowMaker ",
"-*-times-bold-r-*-*-24-*", &color1, &color2);
if (logo) {
WMSetLabelImagePosition(panel->name1L, WIPImageOnly);
WMSetLabelImage(panel->name1L, logo);
WMReleasePixmap(logo);
} else {
font = WMBoldSystemFontOfSize(scr->wmscreen, 24);
if (font) {
WMSetLabelFont(panel->name1L, font);
WMReleaseFont(font);
}
WMSetLabelText(panel->name1L, "WindowMaker");
}
panel->name2L = WMCreateLabel(panel->win);
WMResizeWidget(panel->name2L, 200, 24);
WMMoveWidget(panel->name2L, 120, 60);
font = WMBoldSystemFontOfSize(scr->wmscreen, 18);
if (font) {
WMSetLabelFont(panel->name2L, font);
WMReleaseFont(font);
font = NULL;
}
WMSetLabelText(panel->name2L, "X11 Window Manager");
sprintf(version, "Version %s", VERSION);
panel->versionL = WMCreateLabel(panel->win);
WMResizeWidget(panel->versionL, 150, 16);
WMMoveWidget(panel->versionL, 190, 95);
WMSetLabelTextAlignment(panel->versionL, WARight);
WMSetLabelText(panel->versionL, version);
panel->copyrL = WMCreateLabel(panel->win);
WMResizeWidget(panel->copyrL, 340, 40);
WMMoveWidget(panel->copyrL, 15, 185);
WMSetLabelTextAlignment(panel->copyrL, WALeft);
WMSetLabelText(panel->copyrL, COPYRIGHT_TEXT);
/* we want the (c) character in the helvetica font */
font = WMCreateFontInDefaultEncoding(scr->wmscreen, HELVETICA10_FONT);
if (font) {
WMSetLabelFont(panel->copyrL, font);
}
sprintf(buffer, "Using visual %s %ibpp (0x%x)\n",
visuals[scr->w_visual->class], scr->w_depth,
(unsigned)scr->w_visual->visualid);
strcat(buffer, "Supported image formats: ");
strl = RSupportedFileFormats();
for (i=0; strl[i]!=NULL; i++) {
strcat(buffer, strl[i]);
strcat(buffer, " ");
}
panel->infoL = WMCreateLabel(panel->win);
WMResizeWidget(panel->infoL, 350, 75);
WMMoveWidget(panel->infoL, 15, 115);
WMSetLabelText(panel->infoL, buffer);
if (font) {
WMSetLabelFont(panel->infoL, font);
WMReleaseFont(font);
}
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 382, 230, 0, 0, 0);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
WMMapWidget(panel->win);
wwin = wManageInternalWindow(scr, parent, None, "Info",
(scr->scr_width - 382)/2,
(scr->scr_height - 230)/2, 382, 230);
wwin->window_flags.no_closable = 0;
wwin->window_flags.no_close_button = 0;
wWindowUpdateButtonImages(wwin);
wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
wwin->frame->on_click_right = destroyInfoPanel;
wWindowMap(wwin);
panel->wwin = wwin;
thePanel = panel;
}
/*
***********************************************************************
* Legal Panel
***********************************************************************
*/
typedef struct {
WScreen *scr;
WWindow *wwin;
WMWindow *win;
WMLabel *licenseL;
} LegalPanel;
#define LICENSE_TEXT \
" WindowMaker is free software; you can redistribute it and/or modify "\
"it under the terms of the GNU General Public License as published "\
"by the Free Software Foundation; either version 2 of the License, "\
"or (at your option) any later version.\n\n\n"\
" WindowMaker is distributed in the hope that it will be useful, but "\
"WITHOUT ANY WARRANTY; without even the implied warranty of "\
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU "\
"General Public License for more details.\n\n\n"\
" You should have received a copy of the GNU General Public License "\
"along with this program; if not, write to the Free Software "\
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA "\
"02111-1307, USA."
static LegalPanel *legalPanel = NULL;
static void
destroyLegalPanel(WCoreWindow *foo, void *data, XEvent *event)
{
WMUnmapWidget(legalPanel->win);
WMDestroyWidget(legalPanel->win);
wUnmanageWindow(legalPanel->wwin, False);
free(legalPanel);
legalPanel = NULL;
}
void
wShowLegalPanel(WScreen *scr)
{
LegalPanel *panel;
Window parent;
WWindow *wwin;
if (legalPanel) {
wRaiseFrame(legalPanel->wwin->frame->core);
wSetFocusTo(scr, legalPanel->wwin);
return;
}
panel = wmalloc(sizeof(LegalPanel));
panel->scr = scr;
panel->win = WMCreateWindow(scr->wmscreen, "legal");
WMResizeWidget(panel->win, 420, 250);
panel->licenseL = WMCreateLabel(panel->win);
WMResizeWidget(panel->licenseL, 400, 230);
WMMoveWidget(panel->licenseL, 10, 10);
WMSetLabelTextAlignment(panel->licenseL, WALeft);
WMSetLabelText(panel->licenseL, LICENSE_TEXT);
WMSetLabelRelief(panel->licenseL, WRGroove);
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 420, 250, 0, 0, 0);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
wwin = wManageInternalWindow(scr, parent, None, "Legal",
(scr->scr_width - 420)/2,
(scr->scr_height - 250)/2, 420, 250);
wwin->window_flags.no_closable = 0;
wwin->window_flags.no_close_button = 0;
wWindowUpdateButtonImages(wwin);
wFrameWindowShowButton(wwin->frame, WFF_RIGHT_BUTTON);
wwin->frame->on_click_right = destroyLegalPanel;
panel->wwin = wwin;
WMMapWidget(panel->win);
wWindowMap(wwin);
legalPanel = panel;
}

43
src/dialog.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMDIALOG_H_
#define WMDIALOG_H_
#define WDB_OK (0)
#define WDB_CANCEL (1)
#define WDB_YES (2)
#define WDB_NO (3)
#define WDB_EXIT (4)
int wMessageDialog(WScreen *scr, char *title, char *message,
char *defBtn, char *altBtn, char *othBtn);
int wInputDialog(WScreen *scr, char *title, char *message, char **text);
Bool wIconChooserDialog(WScreen *scr, char **file);
void wShowInfoPanel(WScreen *scr);
void wShowLegalPanel(WScreen *scr);
#endif

3869
src/dock.c Normal file

File diff suppressed because it is too large Load Diff

106
src/dock.h Normal file
View File

@@ -0,0 +1,106 @@
/* dock.h- built-in Dock module for WindowMaker
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMDOCK_H_
#define WMDOCK_H_
#include "appicon.h"
#include "funcs.h"
typedef struct WDock {
WScreen *screen_ptr;
int x_pos, y_pos; /* position of the first icon */
WAppIcon **icon_array; /* array of docked icons */
int max_icons;
int icon_count;
#define WM_DOCK 0
#define WM_CLIP 1
#define NORMAL_DOCK WM_DOCK
#define EXTENDED_DOCK WM_CLIP
int type;
WMagicNumber auto_collapse_magic;
unsigned int auto_collapse:1; /* if clip auto-collapse itself */
unsigned int on_right_side:1;
unsigned int collapsed:1;
unsigned int mapped:1;
unsigned int lowered:1;
unsigned int attract_icons:1; /* If clip should attract app-icons */
unsigned int keep_attracted:1; /* if keep them when application exits*/
unsigned int lclip_button_pushed:1;
unsigned int rclip_button_pushed:1;
struct WMenu *menu;
struct WDDomain *defaults;
} WDock;
WDock *wDockCreate(WScreen *scr, int type);
WDock *wDockRestoreState(WScreen *scr, proplist_t dock_state, int type);
void wDockDestroy(WDock *dock);
void wDockHideIcons(WDock *dock);
void wDockShowIcons(WDock *dock);
void wDockLower(WDock *dock);
void wDockRaise(WDock *dock);
void wDockRaiseLower(WDock *dock);
void wDockSaveState(WScreen *scr);
Bool wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y);
int wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y,
int *ret_x, int *ret_y, int redocking);
int wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y);
void wDockDetach(WDock *dock, WAppIcon *icon);
void wDockTrackWindowLaunch(WDock *dock, Window window);
WAppIcon *wDockFindIconFor(WDock *dock, Window window);
void wDockDoAutoLaunch(WDock *dock, int workspace);
void wDockLaunchWithState(WDock *dock, WAppIcon *btn, WSavedState *state);
#ifdef REDUCE_APPICONS
void wDockSimulateLaunch(WDock *dock, WAppIcon *btn);
#endif
#ifdef OFFIX_DND
int wDockReceiveDNDDrop(WScreen *scr, XEvent *event);
#endif
void wClipIconPaint(WAppIcon *aicon);
void wClipSaveState(WScreen *scr);
proplist_t wClipSaveWorkspaceState(WScreen *scr, int workspace);
WAppIcon* wClipRestoreState(WScreen *scr, proplist_t clip_state);
void wClipUpdateForWorkspaceChange(WScreen *scr, int workspace);
RImage *wClipMakeTile(WScreen *scr, RImage *normalTile);
#endif

429
src/dockedapp.c Normal file
View File

@@ -0,0 +1,429 @@
/* dockedapp.c- docked application settings panel
*
* WindowMaker window manager
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "window.h"
#include "icon.h"
#include "appicon.h"
#include "dock.h"
#include "dialog.h"
#include "funcs.h"
#include "defaults.h"
#include "framewin.h"
/**** Global variables ****/
extern WPreferences wPreferences;
typedef struct _AppSettingsPanel {
WMWindow *win;
WAppIcon *editedIcon;
WWindow *wwin;
WMLabel *iconLabel;
WMLabel *nameLabel;
WMFrame *commandFrame;
WMTextField *commandField;
WMFrame *dndCommandFrame;
WMTextField *dndCommandField;
WMLabel *dndCommandLabel;
WMFrame *iconFrame;
WMTextField *iconField;
WMButton *browseBtn;
WMButton *autoLaunchBtn;
WMButton *okBtn;
WMButton *cancelBtn;
/* kluge */
unsigned int destroyed:1;
unsigned int choosingIcon:1;
} AppSettingsPanel;
void DestroyDockAppSettingsPanel(AppSettingsPanel *panel);
static void
updateCommand(WAppIcon *icon, char *command)
{
if (icon->command)
free(icon->command);
if (command && (command[0]==0 || (command[0]=='-' && command[1]==0))) {
free(command);
command = NULL;
}
icon->command = command;
if (!icon->wm_class && !icon->wm_instance &&
icon->command && strlen(icon->command)>0) {
icon->forced_dock = 1;
}
}
#ifdef OFFIX_DND
static void
updateDNDCommand(WAppIcon *icon, char *command)
{
if (icon->dnd_command)
free(icon->dnd_command);
if (command && (command[0]==0 || (command[0]=='-' && command[1]==0))) {
free(command);
command = NULL;
}
icon->dnd_command = command;
}
#endif /* OFFIX_DND */
static void
updateSettingsPanelIcon(AppSettingsPanel *panel)
{
char *file;
file = WMGetTextFieldText(panel->iconField);
if (!file)
WMSetLabelImage(panel->iconLabel, NULL);
else {
char *path;
path = FindImage(wPreferences.icon_path, file);
if (!path) {
wwarning(_("could not find icon %s, used in a docked application"),
file);
free(file);
WMSetLabelImage(panel->iconLabel, NULL);
return;
} else {
WMPixmap *pixmap;
RColor color;
color.red = 0xae;
color.green = 0xaa;
color.blue = 0xae;
color.alpha = 0;
pixmap = WMCreateBlendedPixmapFromFile(WMWidgetScreen(panel->win),
path, &color);
if (!pixmap) {
WMSetLabelImage(panel->iconLabel, NULL);
} else {
WMSetLabelImage(panel->iconLabel, pixmap);
WMReleasePixmap(pixmap);
}
}
free(file);
free(path);
}
}
static void
chooseIconCallback(WMWidget *self, void *clientData)
{
char *file;
AppSettingsPanel *panel = (AppSettingsPanel*)clientData;
int result;
panel->choosingIcon = 1;
WMSetButtonEnabled(panel->browseBtn, False);
result = wIconChooserDialog(panel->wwin->screen_ptr, &file);
panel->choosingIcon = 0;
if (!panel->destroyed) {
if (result) {
WMSetTextFieldText(panel->iconField, file);
free(file);
updateSettingsPanelIcon(panel);
}
WMSetButtonEnabled(panel->browseBtn, True);
} else {
/* kluge for the case, the user asked to close the panel before
* the icon chooser */
DestroyDockAppSettingsPanel(panel);
}
}
static void
panelBtnCallback(WMWidget *self, void *data)
{
WMButton *btn = self;
AppSettingsPanel *panel = (AppSettingsPanel*)data;
char *text;
int done;
done = 1;
if (panel->okBtn == btn) {
text = WMGetTextFieldText(panel->iconField);
if (text[0]==0) {
free(text);
text = NULL;
}
if (!wIconChangeImageFile(panel->editedIcon->icon, text)) {
char *buf;
buf = wmalloc(strlen(text) + 64);
sprintf(buf, _("Could not open specified icon file:%s"), text);
wMessageDialog(panel->wwin->screen_ptr, _("Error"), buf, _("OK"),
NULL, NULL);
free(buf);
done = 0;
return;
} else {
WAppIcon *aicon = panel->editedIcon;
if (aicon == aicon->icon->core->screen_ptr->clip_icon)
wClipIconPaint(aicon);
else
wAppIconPaint(aicon);
wDefaultChangeIcon(panel->wwin->screen_ptr, aicon->wm_instance,
aicon->wm_class, text);
}
if (text)
free(text);
/* cannot free text from this, because it will be not be duplicated
* in updateCommand */
text = WMGetTextFieldText(panel->commandField);
if (text[0]==0) {
free(text);
text = NULL;
}
updateCommand(panel->editedIcon, text);
#ifdef OFFIX_DND
/* cannot free text from this, because it will be not be duplicated
* in updateDNDCommand */
text = WMGetTextFieldText(panel->dndCommandField);
updateDNDCommand(panel->editedIcon, text);
#endif
panel->editedIcon->auto_launch =
WMGetButtonSelected(panel->autoLaunchBtn);
}
if (done)
DestroyDockAppSettingsPanel(panel);
}
#define PWIDTH 295
#define PHEIGHT 345
void
ShowDockAppSettingsPanel(WAppIcon *aicon)
{
AppSettingsPanel *panel;
WScreen *scr = aicon->icon->core->screen_ptr;
Window parent;
WMFont *font;
int x, y;
panel = wmalloc(sizeof(AppSettingsPanel));
memset(panel, 0, sizeof(AppSettingsPanel));
panel->editedIcon = aicon;
aicon->panel = panel;
aicon->editing = 1;
panel->win = WMCreateWindow(scr->wmscreen, "applicationSettings");
WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
panel->iconLabel = WMCreateLabel(panel->win);
WMResizeWidget(panel->iconLabel, 64, 64);
WMMoveWidget(panel->iconLabel, 10, 10);
WMSetLabelImagePosition(panel->iconLabel, WIPImageOnly);
panel->nameLabel = WMCreateLabel(panel->win);
WMResizeWidget(panel->nameLabel, 190, 18);
WMMoveWidget(panel->nameLabel, 80, 35);
WMSetLabelTextAlignment(panel->nameLabel, WALeft);
font = WMBoldSystemFontOfSize(scr->wmscreen, 14);
WMSetLabelFont(panel->nameLabel, font);
WMReleaseFont(font);
WMSetLabelText(panel->nameLabel, aicon->wm_class);
panel->autoLaunchBtn = WMCreateSwitchButton(panel->win);
WMResizeWidget(panel->autoLaunchBtn, PWIDTH-30, 20);
WMMoveWidget(panel->autoLaunchBtn, 15, 80);
WMSetButtonText(panel->autoLaunchBtn,
_("Start when WindowMaker is started"));
WMSetButtonSelected(panel->autoLaunchBtn, aicon->auto_launch);
panel->commandFrame = WMCreateFrame(panel->win);
WMResizeWidget(panel->commandFrame, 275, 50);
WMMoveWidget(panel->commandFrame, 10, 105);
WMSetFrameTitle(panel->commandFrame, _("Application path and arguments"));
panel->commandField = WMCreateTextField(panel->commandFrame);
WMResizeWidget(panel->commandField, 256, 20);
WMMoveWidget(panel->commandField, 10, 20);
WMSetTextFieldText(panel->commandField, aicon->command);
panel->dndCommandFrame = WMCreateFrame(panel->win);
WMResizeWidget(panel->dndCommandFrame, 275, 70);
WMMoveWidget(panel->dndCommandFrame, 10, 165);
WMSetFrameTitle(panel->dndCommandFrame,
_("Command for files dropped with DND"));
panel->dndCommandField = WMCreateTextField(panel->dndCommandFrame);
WMResizeWidget(panel->dndCommandField, 256, 20);
WMMoveWidget(panel->dndCommandField, 10, 20);
panel->dndCommandLabel = WMCreateLabel(panel->dndCommandFrame);
WMResizeWidget(panel->dndCommandLabel, 256, 18);
WMMoveWidget(panel->dndCommandLabel, 10, 45);
#ifdef OFFIX_DND
WMSetTextFieldText(panel->dndCommandField, aicon->dnd_command);
WMSetLabelText(panel->dndCommandLabel,
_("%d will be replaced with the file name"));
#else
WMSetTextFieldEnabled(panel->dndCommandField, False);
WMSetLabelText(panel->dndCommandLabel,
_("DND support was not compiled in"));
#endif
panel->iconFrame = WMCreateFrame(panel->win);
WMResizeWidget(panel->iconFrame, 275, 50);
WMMoveWidget(panel->iconFrame, 10, 245);
WMSetFrameTitle(panel->iconFrame, _("Icon Image"));
panel->iconField = WMCreateTextField(panel->iconFrame);
WMResizeWidget(panel->iconField, 176, 20);
WMMoveWidget(panel->iconField, 10, 20);
WMSetTextFieldText(panel->iconField,
wDefaultGetIconFile(scr, aicon->wm_instance,
aicon->wm_class, False));
panel->browseBtn = WMCreateCommandButton(panel->iconFrame);
WMResizeWidget(panel->browseBtn, 70, 24);
WMMoveWidget(panel->browseBtn, 195, 18);
WMSetButtonText(panel->browseBtn, _("Browse..."));
WMSetButtonAction(panel->browseBtn, chooseIconCallback, panel);
panel->okBtn = WMCreateCommandButton(panel->win);
WMResizeWidget(panel->okBtn, 80, 26);
WMMoveWidget(panel->okBtn, 200, 308);
WMSetButtonText(panel->okBtn, _("OK"));
WMSetButtonAction(panel->okBtn, panelBtnCallback, panel);
panel->cancelBtn = WMCreateCommandButton(panel->win);
WMResizeWidget(panel->cancelBtn, 80, 26);
WMMoveWidget(panel->cancelBtn, 110, 308);
WMSetButtonText(panel->cancelBtn, _("Cancel"));
WMSetButtonAction(panel->cancelBtn, panelBtnCallback, panel);
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
WMMapSubwidgets(panel->commandFrame);
WMMapSubwidgets(panel->dndCommandFrame);
WMMapSubwidgets(panel->iconFrame);
updateSettingsPanelIcon(panel);
parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT,
0, 0, 0);
XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
XReparentWindow(dpy, WMWidgetXID(panel->win), parent, 0, 0);
y = aicon->y_pos;
if (y < 0)
y = 0;
else if (y + PWIDTH > scr->scr_height)
y = scr->scr_height - PHEIGHT - 30;
if (aicon->dock && aicon->dock->type == WM_DOCK) {
if (aicon->dock->on_right_side)
x = scr->scr_width/2;
else
x = scr->scr_width/2 - PWIDTH;
} else {
x = (scr->scr_width - PWIDTH)/2;
}
panel->wwin = wManageInternalWindow(scr, parent, None,
_("Docked Application Settings"),
x, y, PWIDTH, PHEIGHT);
panel->wwin->client_leader = WMWidgetXID(panel->win);
WMMapWidget(panel->win);
wWindowMap(panel->wwin);
}
void
DestroyDockAppSettingsPanel(AppSettingsPanel *panel)
{
if (!panel->destroyed) {
XUnmapWindow(dpy, panel->wwin->client_win);
XReparentWindow(dpy, panel->wwin->client_win,
panel->wwin->screen_ptr->root_win, 0, 0);
wUnmanageWindow(panel->wwin, False);
}
panel->destroyed = 1;
/*
* kluge. If we destroy the panel before the icon chooser is closed,
* we will crash when it does close, trying to access something in the
* destroyed panel. Could use wretain()/wrelease() in the panel,
* but it is not working for some reason.
*/
if (panel->choosingIcon)
return;
WMDestroyWidget(panel->win);
XDestroyWindow(dpy, panel->wwin->client_win);
panel->editedIcon->panel = NULL;
panel->editedIcon->editing = 0;
free(panel);
}

1574
src/event.c Normal file

File diff suppressed because it is too large Load Diff

1167
src/framewin.c Normal file

File diff suppressed because it is too large Load Diff

141
src/framewin.h Normal file
View File

@@ -0,0 +1,141 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMFRAMEWINDOW_H_
#define WMFRAMEWINDOW_H_
#define BORDER_TOP 1
#define BORDER_BOTTOM 2
#define BORDER_LEFT 4
#define BORDER_RIGHT 8
#define BORDER_ALL (1|2|4|8)
#define WFF_TITLEBAR (1<<0)
#define WFF_LEFT_BUTTON (1<<1)
#define WFF_RIGHT_BUTTON (1<<2)
#define WFF_RESIZEBAR (1<<3)
#define WFF_BORDER (1<<4)
#define WFF_SINGLE_STATE (1<<5)
typedef struct WFrameWindow {
WScreen *screen_ptr; /* pointer to the screen structure */
short window_level;
short workspace; /* workspace that the window occupies */
WCoreWindow *core;
WCoreWindow *titlebar; /* the titlebar */
WCoreWindow *left_button; /* miniaturize button */
WCoreWindow *right_button; /* close button */
short top_width;
short bottom_width;
WCoreWindow *resizebar; /* bottom resizebar */
Pixmap title_back[3]; /* focused, unfocused, pfocused */
Pixmap lbutton_back[3];
Pixmap rbutton_back[3];
WPixmap *lbutton_image;
WPixmap *rbutton_image;
union WTexture **title_texture;
union WTexture **resizebar_texture;
unsigned long *title_pixel;
GC *title_gc;
WFont **font;
short resizebar_corner_width;
char *title; /* window name (title) */
/* thing that uses this frame. passed as data to callbacks */
void *child;
/* callbacks */
void (*on_click_left)(WCoreWindow *sender, void *data, XEvent *event);
void (*on_click_right)(WCoreWindow *sender, void *data, XEvent *event);
void (*on_dblclick_right)(WCoreWindow *sender, void *data, XEvent *event);
void (*on_mousedown_titlebar)(WCoreWindow *sender, void *data, XEvent *event);
void (*on_dblclick_titlebar)(WCoreWindow *sender, void *data, XEvent *event);
void (*on_mousedown_resizebar)(WCoreWindow *sender, void *data, XEvent *event);
struct {
unsigned int state:2; /* 3 possible states */
unsigned int justification:2;
unsigned int titlebar:1;
unsigned int resizebar:1;
unsigned int left_button:1;
unsigned int right_button:1;
unsigned int need_texture_remake:1;
unsigned int single_texture:1;
unsigned int hide_left_button:1;
unsigned int hide_right_button:1;
unsigned int need_texture_change:1;
unsigned int lbutton_dont_fit:1;
unsigned int rbutton_dont_fit:1;
unsigned int repaint_only_titlebar:1;
unsigned int repaint_only_resizebar:1;
unsigned int is_client_window_frame:1;
unsigned int incomplete_title:1;
} flags;
} WFrameWindow;
WFrameWindow*
wFrameWindowCreate(WScreen *scr, int wlevel, int x, int y,
int width, int height, int flags,
union WTexture **title_texture,
union WTexture **resize_texture,
unsigned long *color, GC *gc, WFont **font);
void wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags);
void wFrameWindowDestroy(WFrameWindow *fwin);
void wFrameWindowChangeState(WFrameWindow *fwin, int state);
void wFrameWindowPaint(WFrameWindow *fwin);
void wFrameWindowResize(WFrameWindow *fwin, int width, int height);
void wFrameWindowResizeInternal(WFrameWindow *fwin, int iwidth, int iheight);
void wFrameWindowShowButton(WFrameWindow *fwin, int flags);
void wFrameWindowHideButton(WFrameWindow *fwin, int flags);
int wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title);
#endif

162
src/funcs.h Normal file
View File

@@ -0,0 +1,162 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMFUNCS_H_
#define WMFUNCS_H_
#include <sys/types.h>
#include <stdio.h>
#include "window.h"
typedef void (WCallBack)(void *cdata);
typedef void (WDeathHandler)(pid_t pid, unsigned int status, void *cdata);
typedef void* WMagicNumber;
void RestoreDesktop(WScreen *scr);
void Restart(char *manager);
void SetupEnvironment(WScreen *scr);
void DispatchEvent(XEvent *event);
void WipeDesktop(WScreen *scr);
Bool wRootMenuPerformShortcut(XEvent *event);
void wRootMenuBindShortcuts(Window window);
void OpenRootMenu(WScreen *scr, int x, int y, int keyboard);
void OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard);
void OpenWindowMenu(WWindow *wwin, int x, int y, int keyboard);
void OpenWorkspaceMenu(WScreen *scr, int x, int y);
void CloseWindowMenu(WScreen *scr);
void UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action);
void UpdateSwitchMenuWorkspace(WScreen *scr, int workspace);
WMagicNumber wAddDeathHandler(pid_t pid, WDeathHandler *callback, void *cdata);
WMagicNumber wAddWindowSavedState(char *instance, char *class, char *command,
pid_t pid, WSavedState *state);
WMagicNumber wGetWindowSavedState(Window win);
void wDeleteWindowSavedState(WMagicNumber id);
void wColormapInstallForWindow(WScreen *scr, WWindow *wwin);
void wColormapInstallRoot(WScreen *scr);
void wColormapUninstallRoot(WScreen *scr);
Pixmap LoadIcon(WScreen *scr, char *path, char *mask, int title_height);
void PlaceIcon(WScreen *scr, int *x_ret, int *y_ret);
void PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret);
#ifdef USECPP
char *MakeCPPArgs(char *path);
#endif
char *ExpandOptions(WScreen *scr, char *cmdline);
Bool IsDoubleClick(WScreen *scr, XEvent *event);
WWindow *NextFocusWindow(WScreen *scr);
WWindow *PrevFocusWindow(WScreen *scr);
void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y);
char *ShrinkString(WFont *font, char *string, int width);
char *FindImage(char **paths, char *file);
RImage*wGetImageForWindowName(WScreen *scr, char *winstance, char *wclass);
BOOL StringCompareHook(proplist_t pl1, proplist_t pl2);
int IsEof(FILE * stream); /* feof that stats pipes */
char *FlattenStringList(char **list, int count);
void ParseWindowName(proplist_t value, char **winstance, char **wclass,
char *where);
char *GetShortcutString(char *text);
#ifdef NUMLOCK_HACK
void wHackedGrabKey(int keycode, unsigned int modifiers,
Window grab_window, Bool owner_events, int pointer_mode,
int keyboard_mode);
void wHackedGrabButton(unsigned int button, unsigned int modifiers,
Window grab_window, Bool owner_events,
unsigned int event_mask, int pointer_mode,
int keyboard_mode, Window confine_to, Cursor cursor);
void wHackedUngrabButton(unsigned int button, unsigned int modifiers,
Window grab_window);
#endif
/* this function is in dock.c */
void ParseCommand(char *command, char ***argv, int *argc);
/* This function is in moveres.c. */
void wGetGeometryWindowSize(WScreen *scr, unsigned int *width,
unsigned int *height);
void ExecExitScript();
/****** I18N Wrapper for XFetchName,XGetIconName ******/
Bool wFetchName(Display *dpy, Window win, char **winname);
Bool wGetIconName(Display *dpy, Window win, char **iconname);
#ifdef I18N_MB
/*void wTextWidth(XFontSet *font, char *text, int length);*/
#define wDrawString(d,f,gc,x,y,text,textlen) \
XmbDrawString(dpy, d, (f)->font, gc, (x), (y), text, textlen)
#define wTextWidth(font,text,textlen) XmbTextEscapement(font,text,textlen)
#else /* !I18N_MB */
#define wTextWidth(font,text,textlen) XTextWidth(font,text,textlen)
/*void wTextWidth(XFontStruct *font, char *text, int length);*/
#define wDrawString(d,font,gc,x,y,text,textlen) \
XDrawString(dpy, d, gc, (x), (y), text, textlen)
#endif /* !I18N_MB */
#endif

801
src/icon.c Normal file
View File

@@ -0,0 +1,801 @@
/* icon.c - window icon and dock and appicon parent
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "texture.h"
#include "window.h"
#include "icon.h"
#include "actions.h"
#include "funcs.h"
#include "stacking.h"
#include "application.h"
#include "defaults.h"
#include "appicon.h"
/**** Global variables ****/
extern WPreferences wPreferences;
#define MOD_MASK wPreferences.modifier_mask
extern Cursor wCursor[WCUR_LAST];
static void miniwindowExpose(WObjDescriptor *desc, XEvent *event);
static void miniwindowMouseDown(WObjDescriptor *desc, XEvent *event);
static void miniwindowDblClick(WObjDescriptor *desc, XEvent *event);
INLINE static void
getSize(Drawable d, unsigned int *w, unsigned int *h, unsigned int *dep)
{
Window rjunk;
int xjunk, yjunk;
unsigned int bjunk;
XGetGeometry(dpy, d, &rjunk, &xjunk, &yjunk, w, h, &bjunk, dep);
}
WIcon*
wIconCreate(WWindow *wwin)
{
WScreen *scr=wwin->screen_ptr;
WIcon *icon;
char *file;
unsigned long vmask = 0;
XSetWindowAttributes attribs;
icon = wmalloc(sizeof(WIcon));
memset(icon, 0, sizeof(WIcon));
icon->core = wCoreCreateTopLevel(scr, wwin->icon_x, wwin->icon_y,
wPreferences.icon_size,
wPreferences.icon_size, 0);
if (wPreferences.use_saveunders) {
vmask |= CWSaveUnder;
attribs.save_under = True;
}
/* a white border for selecting it */
vmask |= CWBorderPixel;
attribs.border_pixel = scr->white_pixel;
XChangeWindowAttributes(dpy, icon->core->window, vmask, &attribs);
/* will be overriden if this is an application icon */
icon->core->descriptor.handle_mousedown = miniwindowMouseDown;
icon->core->descriptor.handle_expose = miniwindowExpose;
icon->core->descriptor.parent_type = WCLASS_MINIWINDOW;
icon->core->descriptor.parent = icon;
icon->core->stacking = wmalloc(sizeof(WStacking));
icon->core->stacking->above = NULL;
icon->core->stacking->under = NULL;
icon->core->stacking->window_level = WMNormalWindowLevel;
icon->core->stacking->child_of = NULL;
icon->owner = wwin;
if (wwin->wm_hints && (wwin->wm_hints->flags & IconWindowHint)) {
if (wwin->client_win == wwin->main_window) {
WApplication *wapp;
/* do not let miniwindow steal app-icon's icon window */
wapp = wApplicationOf(wwin->client_win);
if (!wapp || wapp->app_icon==NULL)
icon->icon_win = wwin->wm_hints->icon_window;
} else {
icon->icon_win = wwin->wm_hints->icon_window;
}
}
#ifdef NO_MINIWINDOW_TITLES
icon->show_title = 0;
#else
icon->show_title = 1;
#endif
icon->image = wDefaultGetImage(scr, wwin->wm_instance, wwin->wm_class);
file = wDefaultGetIconFile(scr, wwin->wm_instance, wwin->wm_class,
False);
if (file) {
icon->file = wstrdup(file);
}
wGetIconName(dpy, wwin->client_win, &icon->icon_name);
icon->tile_type = TILE_NORMAL;
wIconUpdate(icon);
XFlush(dpy);
return icon;
}
WIcon*
wIconCreateWithIconFile(WScreen *scr, char *iconfile, int tile)
{
WIcon *icon;
unsigned long vmask = 0;
XSetWindowAttributes attribs;
icon = wmalloc(sizeof(WIcon));
memset(icon, 0, sizeof(WIcon));
icon->core = wCoreCreateTopLevel(scr, 0, 0, wPreferences.icon_size,
wPreferences.icon_size, 0);
if (wPreferences.use_saveunders) {
vmask = CWSaveUnder;
attribs.save_under = True;
}
/* a white border for selecting it */
vmask |= CWBorderPixel;
attribs.border_pixel = scr->white_pixel;
XChangeWindowAttributes(dpy, icon->core->window, vmask, &attribs);
/* will be overriden if this is a application icon */
icon->core->descriptor.handle_mousedown = miniwindowMouseDown;
icon->core->descriptor.handle_expose = miniwindowExpose;
icon->core->descriptor.parent_type = WCLASS_MINIWINDOW;
icon->core->descriptor.parent = icon;
icon->core->stacking = wmalloc(sizeof(WStacking));
icon->core->stacking->above = NULL;
icon->core->stacking->under = NULL;
icon->core->stacking->window_level = WMNormalWindowLevel;
icon->core->stacking->child_of = NULL;
if (iconfile) {
icon->image = RLoadImage(scr->rcontext, iconfile, 0);
if (!icon->image) {
wwarning(_("error loading image file \"%s\""), iconfile, RErrorString);
}
icon->image = wIconValidateIconSize(scr, icon->image);
icon->file = wstrdup(iconfile);
}
icon->tile_type = tile;
wIconUpdate(icon);
return icon;
}
void
wIconDestroy(WIcon *icon)
{
WCoreWindow *core = icon->core;
WScreen *scr = core->screen_ptr;
if (icon->handlerID)
WMDeleteTimerHandler(icon->handlerID);
if (icon->icon_win) {
int x=0, y=0;
if (icon->owner) {
x = icon->owner->icon_x;
y = icon->owner->icon_y;
}
XUnmapWindow(dpy, icon->icon_win);
XReparentWindow(dpy, icon->icon_win, scr->root_win, x, y);
}
if (icon->icon_name)
XFree(icon->icon_name);
if (icon->pixmap)
XFreePixmap(dpy, icon->pixmap);
if (icon->file)
free(icon->file);
if (icon->image!=NULL)
RDestroyImage(icon->image);
wCoreDestroy(icon->core);
free(icon);
}
static void
drawIconTitle(WScreen *scr, Pixmap pixmap, int height)
{
XFillRectangle(dpy, pixmap, scr->icon_title_texture->normal_gc,
0, 0, wPreferences.icon_size, height+1);
XDrawLine(dpy, pixmap, scr->icon_title_texture->light_gc, 0, 0,
wPreferences.icon_size, 0);
XDrawLine(dpy, pixmap, scr->icon_title_texture->light_gc, 0, 0,
0, height+1);
XDrawLine(dpy, pixmap, scr->icon_title_texture->dim_gc,
wPreferences.icon_size-1, 0, wPreferences.icon_size-1, height+1);
}
static Pixmap
makeIcon(WScreen *scr, RImage *icon, int titled, int shadowed, int tileType)
{
RImage *tile;
Pixmap pixmap;
int x, y, sx, sy;
unsigned w, h;
int theight = scr->icon_title_font->height;
if (tileType == TILE_NORMAL)
tile = RCloneImage(scr->icon_tile);
else {
assert(scr->clip_tile);
tile = RCloneImage(scr->clip_tile);
}
if (icon) {
w = (icon->width > wPreferences.icon_size)
? wPreferences.icon_size : icon->width;
x = (wPreferences.icon_size - w) / 2;
sx = (icon->width - w)/2;
if (!titled) {
h = (icon->height > wPreferences.icon_size)
? wPreferences.icon_size : icon->height;
y = (wPreferences.icon_size - h) / 2;
sy = (icon->height - h)/2;
} else {
h = (icon->height+theight > wPreferences.icon_size
? wPreferences.icon_size-theight : icon->height);
y = theight+((int)wPreferences.icon_size-theight-h)/2;
sy = (icon->height - h)/2;
}
RCombineArea(tile, icon, sx, sy, w, h, x, y);
}
if (shadowed) {
RColor color;
color.red = scr->icon_back_texture->light.red >> 8;
color.green = scr->icon_back_texture->light.green >> 8;
color.blue = scr->icon_back_texture->light.blue >> 8;
color.alpha = 150; /* about 60% */
RClearImage(tile, &color);
}
if (!RConvertImage(scr->rcontext, tile, &pixmap)) {
wwarning(_("error rendering image:%s"), RErrorString);
}
RDestroyImage(tile);
if (titled)
drawIconTitle(scr, pixmap, theight);
return pixmap;
}
void
wIconChangeTitle(WIcon *icon, char *new_title)
{
int changed;
changed = (new_title==NULL && icon->icon_name!=NULL)
|| (new_title!=NULL && icon->icon_name==NULL);
if (icon->icon_name!=NULL)
XFree(icon->icon_name);
icon->icon_name = new_title;
if (changed)
icon->force_paint = 1;
wIconPaint(icon);
}
void
wIconChangeImage(WIcon *icon, RImage *new_image)
{
assert(icon != NULL);
if (icon->image)
RDestroyImage(icon->image);
icon->image = wIconValidateIconSize(icon->core->screen_ptr, new_image);
wIconUpdate(icon);
}
RImage*
wIconValidateIconSize(WScreen *scr, RImage *icon)
{
RImage *tmp;
int w, h;
if (!icon)
return NULL;
if (icon->width > wPreferences.icon_size
|| icon->height > wPreferences.icon_size) {
if (icon->width > icon->height) {
w = wPreferences.icon_size - 4;
h = w*icon->height/icon->width;
} else {
h = wPreferences.icon_size - 4;
w = h*icon->width/icon->height;
}
tmp = RScaleImage(icon, w, h);
RDestroyImage(icon);
icon = tmp;
}
return icon;
}
Bool
wIconChangeImageFile(WIcon *icon, char *file)
{
WScreen *scr = icon->core->screen_ptr;
RImage *image;
char *path;
int error = 0;
if (!file) {
wIconChangeImage(icon, NULL);
return True;
}
path = FindImage(wPreferences.icon_path, file);
if (path && (image = RLoadImage(scr->rcontext, path, 0))) {
wIconChangeImage(icon, image);
} else {
error = 1;
}
if (path)
free(path);
return !error;
}
/*
void
wIconChangeIconWindow(WIcon *icon, Window new_window);
*/
static void
cycleColor(void *data)
{
WIcon *icon = (WIcon*)data;
WScreen *scr = icon->core->screen_ptr;
icon->step = !icon->step;
if (icon->step) {
XSetForeground(dpy, scr->icon_select_gc, scr->white_pixel);
XSetBackground(dpy, scr->icon_select_gc, scr->black_pixel);
} else {
XSetForeground(dpy, scr->icon_select_gc, scr->black_pixel);
XSetBackground(dpy, scr->icon_select_gc, scr->white_pixel);
}
XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
icon->core->width-1, icon->core->height-1);
icon->handlerID = WMAddTimerHandler(COLOR_CYCLE_DELAY, cycleColor, icon);
}
void
wIconSetHighlited(WIcon *icon, Bool flag)
{
if (icon->highlighted == flag) {
return;
}
icon->highlighted = flag;
wIconPaint(icon);
}
void
wIconSelect(WIcon *icon)
{
WScreen *scr = icon->core->screen_ptr;
icon->selected = !icon->selected;
if (icon->selected) {
icon->step = 0;
if (!wPreferences.dont_blink)
icon->handlerID = WMAddTimerHandler(10, cycleColor, icon);
else
XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
icon->core->width-1, icon->core->height-1);
} else {
if (icon->handlerID) {
WMDeleteTimerHandler(icon->handlerID);
icon->handlerID = NULL;
}
XClearArea(dpy, icon->core->window, 0, 0, icon->core->width,
icon->core->height, True);
}
}
void
wIconUpdate(WIcon *icon)
{
WScreen *scr = icon->core->screen_ptr;
int title_height = scr->icon_title_font->height;
WWindow *wwin = icon->owner;
assert(scr->icon_tile!=NULL);
if (icon->pixmap!=None)
XFreePixmap(dpy, icon->pixmap);
icon->pixmap = None;
if (wwin && wwin->window_flags.always_user_icon)
goto user_icon;
/* use client specified icon window */
if (icon->icon_win!=None) {
XWindowAttributes attr;
int resize=0;
int width, height, depth;
int theight;
Pixmap pixmap;
getSize(icon->icon_win, &width, &height, &depth);
if (width > wPreferences.icon_size) {
resize = 1;
width = wPreferences.icon_size;
}
if (height > wPreferences.icon_size) {
resize = 1;
height = wPreferences.icon_size;
}
if (icon->show_title
&& (height+title_height < wPreferences.icon_size)) {
pixmap = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size,
wPreferences.icon_size, scr->w_depth);
XSetClipMask(dpy, scr->copy_gc, None);
XCopyArea(dpy, scr->icon_tile_pixmap, pixmap, scr->copy_gc, 0, 0,
wPreferences.icon_size, wPreferences.icon_size, 0, 0);
drawIconTitle(scr, pixmap, title_height);
theight = title_height;
} else {
pixmap = None;
theight = 0;
XSetWindowBackgroundPixmap(dpy, icon->core->window,
scr->icon_tile_pixmap);
}
XSetWindowBorderWidth(dpy, icon->icon_win, 0);
XReparentWindow(dpy, icon->icon_win, icon->core->window,
(wPreferences.icon_size-width)/2,
theight+(wPreferences.icon_size-height-theight)/2);
if (resize)
XResizeWindow(dpy, icon->icon_win, width, height);
XMapWindow(dpy, icon->icon_win);
XAddToSaveSet(dpy, icon->icon_win);
icon->pixmap = pixmap;
if (XGetWindowAttributes(dpy, icon->icon_win, &attr)) {
if (attr.all_event_masks & ButtonPressMask) {
XGrabButton(dpy, Button1, MOD_MASK, icon->core->window, True,
ButtonPressMask, GrabModeSync, GrabModeAsync, None,
wCursor[WCUR_ARROW]);
XGrabButton(dpy, Button1, MOD_MASK|LockMask, icon->core->window,
True, ButtonPressMask, GrabModeSync, GrabModeAsync,
None, wCursor[WCUR_ARROW]);
#ifdef NUMLOCK_HACK
wHackedGrabButton(Button1, MOD_MASK, icon->core->window, True,
ButtonPressMask, GrabModeSync, GrabModeAsync,
None, wCursor[WCUR_ARROW]);
#endif
}
}
} else if (wwin && wwin->wm_hints
&& (wwin->wm_hints->flags & IconPixmapHint)) {
int x, y;
unsigned int w, h;
Window jw;
int ji, dotitle;
unsigned int ju, d;
Pixmap pixmap;
if (!XGetGeometry(dpy, wwin->wm_hints->icon_pixmap, &jw,
&ji, &ji, &w, &h, &ju, &d)) {
icon->owner->wm_hints->flags &= ~IconPixmapHint;
goto user_icon;
}
pixmap = XCreatePixmap(dpy, icon->core->window, wPreferences.icon_size,
wPreferences.icon_size, scr->w_depth);
XSetClipMask(dpy, scr->copy_gc, None);
XCopyArea(dpy, scr->icon_tile_pixmap, pixmap, scr->copy_gc, 0, 0,
wPreferences.icon_size, wPreferences.icon_size, 0, 0);
if (w > wPreferences.icon_size)
w = wPreferences.icon_size;
x = (wPreferences.icon_size-w)/2;
if (icon->show_title && (title_height < wPreferences.icon_size)) {
drawIconTitle(scr, pixmap, title_height);
dotitle = 1;
if (h > wPreferences.icon_size - title_height - 2) {
h = wPreferences.icon_size - title_height - 2;
y = title_height + 1;
} else {
y = (wPreferences.icon_size-h-title_height)/2+title_height + 1;
}
} else {
dotitle = 0;
if (w > wPreferences.icon_size)
w = wPreferences.icon_size;
y = (wPreferences.icon_size-h)/2;
}
if (wwin->wm_hints->flags & IconMaskHint)
XSetClipMask(dpy, scr->copy_gc, wwin->wm_hints->icon_mask);
XSetClipOrigin(dpy, scr->copy_gc, x, y);
if (d != scr->w_depth) {
XSetForeground(dpy, scr->copy_gc, scr->black_pixel);
XSetBackground(dpy, scr->copy_gc, scr->white_pixel);
XCopyPlane(dpy, wwin->wm_hints->icon_pixmap, pixmap, scr->copy_gc,
0, 0, w, h, x, y, 1);
} else {
XCopyArea(dpy, wwin->wm_hints->icon_pixmap, pixmap, scr->copy_gc,
0, 0, w, h, x, y);
}
XSetClipOrigin(dpy, scr->copy_gc, 0, 0);
icon->pixmap = pixmap;
} else {
user_icon:
if (icon->image) {
icon->pixmap = makeIcon(scr, icon->image, icon->show_title,
icon->shadowed, icon->tile_type);
} else {
/* make default icons */
if (!scr->def_icon_pixmap) {
RImage *image = NULL;
char *path;
char *file;
file = wDefaultGetIconFile(scr, NULL, NULL, False);
if (file) {
path = FindImage(wPreferences.icon_path, file);
if (!path) {
wwarning(_("could not find default icon \"%s\""),file);
goto make_icons;
}
image = RLoadImage(scr->rcontext, path, 0);
if (!image) {
wwarning(_("could not load default icon \"%s\":%s"),
file, RErrorString);
}
free(path);
}
make_icons:
image = wIconValidateIconSize(scr, image);
scr->def_icon_pixmap = makeIcon(scr, image, False, False,
icon->tile_type);
scr->def_ticon_pixmap = makeIcon(scr, image, True, False,
icon->tile_type);
if (image)
RDestroyImage(image);
}
if (icon->show_title) {
XSetWindowBackgroundPixmap(dpy, icon->core->window,
scr->def_ticon_pixmap);
} else {
XSetWindowBackgroundPixmap(dpy, icon->core->window,
scr->def_icon_pixmap);
}
icon->pixmap = None;
}
}
if (icon->pixmap != None) {
XSetWindowBackgroundPixmap(dpy, icon->core->window, icon->pixmap);
}
XClearWindow(dpy, icon->core->window);
wIconPaint(icon);
}
void
wIconPaint(WIcon *icon)
{
WScreen *scr=icon->core->screen_ptr;
GC gc = scr->icon_title_gc;
int x;
char *tmp;
if (icon->force_paint) {
icon->force_paint = 0;
wIconUpdate(icon);
return;
}
XClearWindow(dpy, icon->core->window);
/* draw the icon title */
if (icon->show_title && icon->icon_name!=NULL) {
int l;
int w;
tmp = ShrinkString(scr->icon_title_font, icon->icon_name,
wPreferences.icon_size-4);
w = wTextWidth(scr->icon_title_font->font, tmp, l=strlen(tmp));
if (w > icon->core->width - 4)
x = (icon->core->width - 4) - w;
else
x = (icon->core->width - w)/2;
wDrawString(icon->core->window, scr->icon_title_font, gc,
x, 1 + scr->icon_title_font->y, tmp, l);
free(tmp);
}
if (icon->selected)
XDrawRectangle(dpy, icon->core->window, scr->icon_select_gc, 0, 0,
icon->core->width-1, icon->core->height-1);
}
/******************************************************************/
static void
miniwindowExpose(WObjDescriptor *desc, XEvent *event)
{
wIconPaint(desc->parent);
}
static void
miniwindowDblClick(WObjDescriptor *desc, XEvent *event)
{
WIcon *icon = desc->parent;
assert(icon->owner!=NULL);
wDeiconifyWindow(icon->owner);
}
static void
miniwindowMouseDown(WObjDescriptor *desc, XEvent *event)
{
WIcon *icon = desc->parent;
WWindow *wwin = icon->owner;
XEvent ev;
int x=wwin->icon_x, y=wwin->icon_y;
int dx=event->xbutton.x, dy=event->xbutton.y;
int grabbed=0;
int clickButton=event->xbutton.button;
if (IsDoubleClick(icon->core->screen_ptr, event)) {
miniwindowDblClick(desc, event);
return;
}
#ifdef DEBUG
puts("Moving miniwindow");
#endif
if (event->xbutton.button==Button1) {
if (event->xbutton.state & MOD_MASK)
wLowerFrame(icon->core);
else
wRaiseFrame(icon->core);
if (event->xbutton.state & ShiftMask) {
wIconSelect(icon);
wSelectWindow(icon->owner);
}
}
if (XGrabPointer(dpy, icon->core->window, False, ButtonMotionMask
|ButtonReleaseMask|ButtonPressMask, GrabModeAsync,
GrabModeAsync, None, None, CurrentTime) !=GrabSuccess) {
#ifdef DEBUG0
wwarning("pointer grab failed for icon move");
#endif
}
while(1) {
WMMaskEvent(dpy, PointerMotionMask|ButtonReleaseMask|ButtonPressMask
|ButtonMotionMask|ExposureMask, &ev);
switch (ev.type) {
case Expose:
WMHandleEvent(&ev);
break;
case MotionNotify:
if (!grabbed) {
if (abs(dx-ev.xmotion.x)>=MOVE_THRESHOLD
|| abs(dy-ev.xmotion.y)>=MOVE_THRESHOLD) {
XChangeActivePointerGrab(dpy, ButtonMotionMask
|ButtonReleaseMask|ButtonPressMask,
wCursor[WCUR_MOVE], CurrentTime);
grabbed=1;
} else {
break;
}
}
x = ev.xmotion.x_root - dx;
y = ev.xmotion.y_root - dy;
XMoveWindow(dpy, icon->core->window, x, y);
break;
case ButtonPress:
break;
case ButtonRelease:
if (ev.xbutton.button != clickButton)
break;
if (wwin->icon_x!=x || wwin->icon_y!=y)
wwin->flags.icon_moved = 1;
XMoveWindow(dpy, icon->core->window, x, y);
wwin->icon_x = x;
wwin->icon_y = y;
#ifdef DEBUG
puts("End miniwindow move");
#endif
XUngrabPointer(dpy, CurrentTime);
return;
}
}
}

74
src/icon.h Normal file
View File

@@ -0,0 +1,74 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMICON_H_
#define WMICON_H_
#include "wcore.h"
#include "window.h"
#include "funcs.h"
#define TILE_NORMAL 0
#define TILE_CLIP 1
typedef struct WIcon {
WCoreWindow *core;
WWindow *owner; /* owner window */
char *icon_name; /* the icon name hint */
Window icon_win; /* client suplied icon window */
char *file; /* the file with the icon image */
RImage *image;
short tile_type;
unsigned int show_title:1;
unsigned int has_titlebar:1;
unsigned int force_paint:1; /* True for icon update and repaint */
unsigned int selected:1;
unsigned int step:1;
unsigned int shadowed:1; /* If the icon is to be blured */
unsigned int mapped:1;
unsigned int highlighted:1;
Pixmap pixmap;
WMHandlerID handlerID; /* timer handler ID for cycling select
* color */
} WIcon;
WIcon *wIconCreateWithIconFile(WScreen *scr, char *iconfile, int tile);
WIcon *wIconCreate(WWindow *wwin);
void wIconDestroy(WIcon *icon);
void wIconPaint(WIcon *icon);
void wIconUpdate(WIcon *icon);
void wIconChangeTitle(WIcon *icon, char *new_title);
void wIconChangeImage(WIcon *icon, RImage *new_image);
Bool wIconChangeImageFile(WIcon *icon, char *file);
void wIconSelect(WIcon *icon);
RImage *wIconValidateIconSize(WScreen *scr, RImage *icon);
#endif /* WMICON_H_ */

71
src/keybind.h Normal file
View File

@@ -0,0 +1,71 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/* anywhere */
#define WKBD_ROOTMENU 0
#define WKBD_WINDOWMENU 1
#define WKBD_WINDOWLIST 2
/* window */
#define WKBD_MINIATURIZE 3
#define WKBD_HIDE 4
#define WKBD_MAXIMIZE 5
#define WKBD_VMAXIMIZE 6
#define WKBD_SELECT 7
/* Clip */
#define WKBD_CLIPLOWER 8
#define WKBD_CLIPRAISE 9
#define WKBD_CLIPRAISELOWER 10
/* window, menu */
#define WKBD_RAISE 11
#define WKBD_LOWER 12
#define WKBD_RAISELOWER 13
/* window */
#define WKBD_SHADE 14
/* window, menu */
#define WKBD_CLOSE 15
/* window */
#define WKBD_FOCUSNEXT 16
#define WKBD_FOCUSPREV 17
#define WKBD_WORKSPACE1 20
#define WKBD_WORKSPACE2 21
#define WKBD_WORKSPACE3 22
#define WKBD_WORKSPACE4 23
#define WKBD_WORKSPACE5 24
#define WKBD_WORKSPACE6 25
#define WKBD_WORKSPACE7 26
#define WKBD_WORKSPACE8 27
#define WKBD_WORKSPACE9 28
#define WKBD_WORKSPACE10 29
#define WKBD_NEXTWORKSPACE 30
#define WKBD_PREVWORKSPACE 31
#define WKBD_NEXTWSLAYER 32
#define WKBD_PREVWSLAYER 33
#define WKBD_LAST 34
typedef struct WShortKey {
unsigned int modifier;
KeyCode keycode;
} WShortKey;
void wKeyboardInitialize();

225
src/list.c Normal file
View File

@@ -0,0 +1,225 @@
/* Generic single linked list to keep various information
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
Author: Kresten Krab Thorup
Many modifications by Alfredo K. Kojima
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with files compiled with
GCC to produce an executable, this does not cause the resulting executable
to be covered by the GNU General Public License. This exception does not
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
#include <WUtil.h>
#include "list.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <stdlib.h>
#define xrealloc(ptr, size) wrealloc(ptr, size)
/* Return a cons cell produced from (head . tail) */
INLINE LinkedList*
list_cons(void* head, LinkedList* tail)
{
LinkedList* cell;
cell = (LinkedList*)wmalloc(sizeof(LinkedList));
cell->head = head;
cell->tail = tail;
return cell;
}
/* Inserts "item" in list using "compare" function to make a sorted list */
INLINE void
list_insert_sorted(void* item, LinkedList** list, int (*compare)(void*, void*))
{
LinkedList *tmp, *cell;
cell = (LinkedList*)wmalloc(sizeof(LinkedList));
cell->head = item;
if ((*list == NULL) || ((*compare)((*list)->head, item) >= 0)) {
cell->tail = *list;
*list = cell;
} else {
tmp = *list;
while (tmp->tail) {
if ((*compare)(tmp->tail->head, item) >= 0)
break;
tmp = tmp->tail;
}
cell->tail = tmp->tail;
tmp->tail = cell;
}
}
/* Return the length of a list, list_length(NULL) returns zero */
INLINE int
list_length(LinkedList* list)
{
int i = 0;
while(list)
{
i += 1;
list = list->tail;
}
return i;
}
/* Return the Nth element of LIST, where N count from zero. If N
larger than the list length, NULL is returned */
INLINE void*
list_nth(int index, LinkedList* list)
{
while(index-- != 0)
{
if(list->tail)
list = list->tail;
else
return 0;
}
return list->head;
}
/* Remove the element at the head by replacing it by its successor */
#if 0
INLINE void
list_remove_head(LinkedList** list)
{
if (!*list) return;
if ((*list)->tail)
{
LinkedList* tail = (*list)->tail; /* fetch next */
*(*list) = *tail; /* copy next to list head */
free(tail); /* free next */
}
else /* only one element in list */
{
free(*list);
(*list) = 0;
}
}
/* Alfredo, is there any reason for the function to be as above,
* instead of the more simple version below?
* The difference is that above function do a copying of the structure
* unlike the below that only changes where list points.
* This makes the above function twice slower, because it copies the
* whole structure, which contains 2 pointers. -Dan
*
* I don't know. I just copied this file from the gcc distribution
* (I liked the API). One could think that the above function would
* keep the pointer to the list unchanged, while the below would change
* it, but since the list is passed by reference that doesn't make any
* sense. -Alfredo
*/
#else
INLINE void
list_remove_head(LinkedList** list)
{
if (!*list) return;
{
LinkedList* next = (*list)->tail; /* fetch next */
free(*list); /* free head */
*list = next; /* update list pointer */
}
}
#endif
/* Remove the element with `car' set to ELEMENT */
/*
INLINE void
list_remove_elem(LinkedList** list, void* elem)
{
while (*list)
{
if ((*list)->head == elem)
list_remove_head(list);
*list = (*list ? (*list)->tail : NULL);
}
}*/
INLINE LinkedList *
list_remove_elem(LinkedList* list, void* elem)
{
LinkedList *tmp;
if (list) {
if (list->head == elem) {
tmp = list->tail;
free(list);
return tmp;
}
list->tail = list_remove_elem(list->tail, elem);
return list;
}
return NULL;
}
/* Return element that has ELEM as car */
INLINE LinkedList*
list_find(LinkedList* list, void* elem)
{
while(list)
{
if (list->head == elem)
return list;
list = list->tail;
}
return NULL;
}
/* Free list (backwards recursive) */
INLINE void
list_free(LinkedList* list)
{
if(list)
{
list_free(list->tail);
free(list);
}
}
/* Map FUNCTION over all elements in LIST */
INLINE void
list_mapcar(LinkedList* list, void(*function)(void*))
{
while(list)
{
(*function)(list->head);
list = list->tail;
}
}

60
src/list.h Normal file
View File

@@ -0,0 +1,60 @@
/* Generic single linked list to keep various information
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
Author: Kresten Krab Thorup
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you link this library with files compiled with
GCC to produce an executable, this does not cause the resulting executable
to be covered by the GNU General Public License. This exception does not
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
#ifndef __LIST_H_
#define __LIST_H_
#include "config.h"
#include "wconfig.h"
typedef struct LinkedList {
void *head;
struct LinkedList *tail;
} LinkedList;
INLINE LinkedList* list_cons(void* head, LinkedList* tail);
INLINE void list_insert_sorted(void* item, LinkedList** list,
int (*compare)(void*, void*));
INLINE int list_length(LinkedList* list);
INLINE void* list_nth(int index, LinkedList* list);
INLINE void list_remove_head(LinkedList** list);
INLINE LinkedList *list_remove_elem(LinkedList* list, void* elem);
INLINE void list_mapcar(LinkedList* list, void(*function)(void*));
INLINE LinkedList*list_find(LinkedList* list, void* elem);
INLINE void list_free(LinkedList* list);
#endif

457
src/main.c Normal file
View File

@@ -0,0 +1,457 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
/* Xlocale.h and locale.h are the same if X_LOCALE is undefind in wconfig.h,
* and if X_LOCALE is defined, X's locale emulating functions will be used.
* See Xlocale.h for more information.
*/
#include <X11/Xlocale.h>
#include "WindowMaker.h"
#include "window.h"
#include "funcs.h"
#include "menu.h"
#include "keybind.h"
#include "xmodifier.h"
#include "defaults.h"
#include <proplist.h>
/****** Global Variables ******/
/* general info */
Display *dpy;
char *ProgName;
unsigned int ValidModMask = 0xff;
/* locale to use. NULL==POSIX or C */
char *Locale=NULL;
int wScreenCount=0;
WPreferences wPreferences;
proplist_t wDomainName;
proplist_t wAttributeDomainName;
WShortKey wKeyBindings[WKBD_LAST];
/* defaults domains */
WDDomain *WDWindowMaker = NULL;
WDDomain *WDRootMenu = NULL;
WDDomain *WDWindowAttributes = NULL;
/* XContexts */
XContext wWinContext;
XContext wAppWinContext;
XContext wStackContext;
/* Atoms */
Atom _XA_WM_STATE;
Atom _XA_WM_CHANGE_STATE;
Atom _XA_WM_PROTOCOLS;
Atom _XA_WM_TAKE_FOCUS;
Atom _XA_WM_DELETE_WINDOW;
Atom _XA_WM_SAVE_YOURSELF;
Atom _XA_WM_CLIENT_LEADER;
Atom _XA_WM_COLORMAP_WINDOWS;
Atom _XA_GNUSTEP_WM_ATTR;
Atom _XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW;
Atom _XA_GNUSTEP_WM_RESIZEBAR;
#ifdef MWM_HINTS
/* MWM support */
Atom _XA_MOTIF_WM_HINTS;
#endif
Atom _XA_WINDOWMAKER_MENU;
Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
Atom _XA_WINDOWMAKER_STATE;
Atom _XA_WINDOWMAKER_WM_FUNCTION;
#ifdef OFFIX_DND
Atom _XA_DND_PROTOCOL;
Atom _XA_DND_SELECTION;
#endif
/* cursors */
Cursor wCursor[WCUR_LAST];
/* last event timestamp for XSetInputFocus */
Time LastTimestamp;
/* timestamp on the last time we did XSetInputFocus() */
Time LastFocusChange;
#ifdef SHAPE
int ShapeEventBase;
#endif
/* special flags */
char WRestartASAP = 0;
char WExitASAP = 0;
char WDelayedActionSet = 0;
/* temporary stuff */
int wVisualID = -1;
/******** End Global Variables *****/
static char *DisplayName = NULL;
static char **Arguments;
static int ArgCount;
extern void EventLoop();
extern void StartUp();
void
Restart(char *manager)
{
char *prog=NULL;
char *argv[MAX_RESTART_ARGS];
int i;
if (manager && manager[0]!=0) {
prog = argv[0] = strtok(manager, " ");
for (i=1; i<MAX_RESTART_ARGS; i++) {
argv[i]=strtok(NULL, " ");
if (argv[i]==NULL) {
break;
}
}
}
XCloseDisplay(dpy);
if (!prog)
execvp(Arguments[0], Arguments);
else {
execvp(prog, argv);
/* fallback */
execv(Arguments[0], Arguments);
}
wfatal(_("Restart failed!!!"));
exit(-1);
}
void
SetupEnvironment(WScreen *scr)
{
char *tmp, *ptr;
char buf[16];
if (wScreenCount == 1)
return;
tmp = wmalloc(strlen(DisplayName)+64);
sprintf(tmp, "DISPLAY=%s", XDisplayName(DisplayName));
ptr = strchr(strchr(DisplayName, ':'), '.');
if (ptr)
*ptr = 0;
sprintf(buf, ".%i", scr->screen);
strcat(tmp, buf);
putenv(tmp);
}
/*
*---------------------------------------------------------------------
* wAbort--
* Do a major cleanup and exit the program
*
*----------------------------------------------------------------------
*/
void
wAbort(Bool dumpCore)
{
int i;
WScreen *scr;
for (i=0; i<wScreenCount; i++) {
scr = wScreenWithNumber(i);
if (scr)
RestoreDesktop(scr);
}
printf(_("%s aborted.\n"), ProgName);
if (dumpCore)
abort();
else
exit(1);
}
void
print_help()
{
printf(_("usage: %s [-options]\n"), ProgName);
puts(_("options:"));
#ifdef USECPP
puts(_(" -nocpp disable preprocessing of configuration files"));
#endif
puts(_(" -nodock do not open the application Dock"));
puts(_(" -noclip do not open the workspace Clip"));
/*
puts(_(" -locale locale locale to use"));
*/
puts(_(" -visualid visualid visual id of visual to use"));
puts(_(" -display host:dpy display to use"));
puts(_(" -version print version and exit"));
}
void
check_defaults()
{
char *path;
path = wdefaultspathfordomain("");
if (access(path, R_OK)!=0) {
wfatal(_("could not find user GNUstep directory.\n"
"Make sure you have installed WindowMaker correctly and run wmaker.inst"));
exit(1);
}
free(path);
}
static void
execInitScript()
{
char *file;
file = wfindfile(DEF_CONFIG_PATHS, DEF_INIT_SCRIPT);
if (file) {
if (fork()==0) {
close(ConnectionNumber(dpy));
execl("/bin/sh", "/bin/sh", "-c", file, NULL);
wsyserror(_("%s:could not execute initialization script"), file);
exit(1);
}
free(file);
}
}
void
ExecExitScript()
{
char *file;
file = wfindfile(DEF_CONFIG_PATHS, DEF_EXIT_SCRIPT);
if (file) {
if (fork()==0) {
close(ConnectionNumber(dpy));
execl("/bin/sh", "/bin/sh", "-c", file, NULL);
wsyserror(_("%s:could not execute exit script"), file);
exit(1);
}
free(file);
}
}
int
main(int argc, char **argv)
{
int i, restart=0;
Bool multiHead = True;
char *str;
int d, s;
ArgCount = argc;
Arguments = argv;
WMInitializeApplication("WindowMaker", &argc, argv);
ProgName = strrchr(argv[0],'/');
if (!ProgName)
ProgName = argv[0];
else
ProgName++;
/* check existence of Defaults DB directory */
check_defaults();
restart = 0;
memset(&wPreferences, 0, sizeof(WPreferences));
if (argc>1) {
for (i=1; i<argc; i++) {
#ifdef USECPP
if (strcmp(argv[i], "-nocpp")==0) {
wPreferences.flags.nocpp=1;
} else
#endif
if (strcmp(argv[i], "-nodock")==0) {
wPreferences.flags.nodock=1;
} else if (strcmp(argv[i], "-noclip")==0) {
wPreferences.flags.noclip=1;
} else if (strcmp(argv[i], "-version")==0) {
printf("WindowMaker %s\n", VERSION);
exit(0);
} else if (strcmp(argv[i], "-global_defaults_path")==0) {
printf("%s/Defaults/WindowMaker", PKGDATADIR);
exit(0);
} else if (strcmp(argv[i], "-locale")==0) {
i++;
if (i>=argc) {
wwarning(_("too few arguments for %s"), argv[i-1]);
exit(0);
}
Locale = argv[i];
} else if (strcmp(argv[i], "-display")==0) {
i++;
if (i>=argc) {
wwarning(_("too few arguments for %s"), argv[i-1]);
exit(0);
}
DisplayName = argv[i];
} else if (strcmp(argv[i], "-visualid")==0) {
i++;
if (i>=argc) {
wwarning(_("too few arguments for %s"), argv[i-1]);
exit(0);
}
if (sscanf(argv[i], "%d", &wVisualID)!=1) {
wwarning(_("bad value for visualid: \"%s\""), argv[i]);
exit(0);
}
} else {
print_help();
exit(0);
}
}
}
#if 0
tmp = getenv("LANG");
if (tmp) {
if (setlocale(LC_ALL,"") == NULL) {
wwarning("cannot set locale %s", tmp);
wwarning("falling back to C locale");
setlocale(LC_ALL,"C");
Locale = NULL;
} else {
if (strcmp(tmp, "C")==0 || strcmp(tmp, "POSIX")==0)
Locale = NULL;
else
Locale = tmp;
}
} else {
Locale = NULL;
}
#endif
if (!Locale) {
Locale = getenv("LANG");
}
setlocale(LC_ALL, Locale);
if (!Locale || strcmp(Locale, "C")==0 || strcmp(Locale, "POSIX")==0)
Locale = NULL;
#ifdef I18N
if (getenv("NLSPATH"))
bindtextdomain("WindowMaker", getenv("NLSPATH"));
else
bindtextdomain("WindowMaker", NLSDIR);
textdomain("WindowMaker");
if (!XSupportsLocale()) {
wwarning(_("X server does not support locale"));
}
if (XSetLocaleModifiers("") == NULL) {
wwarning(_("cannot set locale modifiers"));
}
#endif
/* open display */
dpy = XOpenDisplay(DisplayName);
if (dpy == NULL) {
wfatal(_("could not open display \"%s\""), XDisplayName(DisplayName));
exit(1);
}
/* check if the user specified a complete display name (with screen).
* If so, only manage the specified screen */
if (DisplayName)
str = strchr(DisplayName, ':');
else
str = NULL;
if (!str)
str = "";
if (sscanf(str, "%i.%i", &d, &s)==2)
multiHead = False;
DisplayName = XDisplayName(DisplayName);
str = wmalloc(strlen(DisplayName)+64);
sprintf(str, "DISPLAY=%s", DisplayName);
putenv(str);
#ifdef DEBUG
XSynchronize(dpy, True);
#endif
wXModifierInitialize();
#ifdef SOUNDS
wSoundInitialize();
#endif
StartUp(!multiHead);
execInitScript();
EventLoop();
return -1;
}

2374
src/menu.c Normal file

File diff suppressed because it is too large Load Diff

136
src/menu.h Normal file
View File

@@ -0,0 +1,136 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMMENU_H_
#define WMMENU_H_
#include "wcore.h"
#define MR_RESIZED 1
#define MR_TITLE_BACK 2
#define MR_TEXT_BACK 4
#define MR_TITLE_TEXT 8
#define MI_DIAMOND 0
#define MI_CHECK 1
#define MI_MINIWINDOW 2
#define MI_HIDDEN 3
#define MI_SHADED 4
typedef struct WMenuEntry {
int order;
char *text; /* entry text */
char *rtext; /* text to show in the right part */
void (*callback)(struct WMenu *menu, struct WMenuEntry *entry);
void (*free_cdata)(void *data); /* proc to be used to free clientdata */
void *clientdata; /* data to pass to callback */
int cascade; /* cascade menu index */
struct {
unsigned int enabled:1; /* entry is selectable */
unsigned int indicator:1; /* left indicator */
unsigned int indicator_on:1;
unsigned int indicator_type:3;
unsigned int editable:1;
} flags;
} WMenuEntry;
typedef struct WMenu {
struct WMenu *parent;
struct WMenu *brother;
time_t timestamp; /* for the root menu. Last time
* menu was reloaded */
/* decorations */
struct WFrameWindow *frame;
WCoreWindow *menu; /* the window menu */
Pixmap menu_texture_data;
int frame_x, frame_y; /* position of the frame in root*/
WMenuEntry **entries; /* array of entries. This is shared
* by the menu and it's "brother" */
short alloced_entries; /* number of entries allocated in
* entry array */
struct WMenu **cascades; /* array of cascades */
short cascade_no;
short entry_no; /* number of entries */
short selected_entry;
short entry_height; /* height of each entry */
WMHandlerID timer; /* timer for the autoscroll */
/* to be called when some entry is edited */
void (*on_edit)(struct WMenu *menu, struct WMenuEntry *entry);
/* to be called when destroyed */
void (*on_destroy)(struct WMenu *menu);
struct {
unsigned int titled:1;
unsigned int realized:1; /* whether the window was configured */
unsigned int app_menu:1; /* this is a application or root menu */
unsigned int mapped:1; /* if menu is already mapped on screen*/
unsigned int buttoned:1; /* if the close button is visible
* (menu was torn off) */
unsigned int open_to_left:1; /* direction to open submenus */
unsigned int lowered:1;
unsigned int brother:1; /* if this is a copy of the menu*/
unsigned int editing:1;
} flags;
} WMenu;
void wMenuRefresh(WMenu *menu, int flags);
void wMenuPaint(WMenu *menu);
void wMenuDestroy(WMenu *menu, int recurse);
void wMenuRealize(WMenu *menu);
WMenuEntry *wMenuInsertCascade(WMenu *menu, int index, char *text,
WMenu *cascade);
WMenuEntry *wMenuInsertCallback(WMenu *menu, int index, char *text,
void (*callback)(WMenu *menu, WMenuEntry *entry),
void *clientdata);
void wMenuEntrySetCascade(WMenu *menu, WMenuEntry *entry, WMenu *cascade);
#define wMenuAddCallback(menu, text, callback, data) \
wMenuInsertCallback(menu, -1, text, callback, data)
void wMenuRemoveItem(WMenu *menu, int index);
WMenu *wMenuCreate(WScreen *screen, char *title, int main_menu);
WMenu *wMenuCreateForApp(WScreen *screen, char *title, int main_menu);
void wMenuMap(WMenu *menu);
void wMenuMapAt(WMenu *menu, int x, int y, int keyboard);
#define wMenuMapCopyAt(menu, x, y) wMenuMapAt((menu)->brother, (x), (y), False)
void wMenuUnmap(WMenu *menu);
void wMenuSetEnabled(WMenu *menu, int index, int enable);
void wMenuMove(WMenu *menu, int x, int y, int submenus);
void wMenuEntryRemoveCascade(WMenu *menu, WMenuEntry *entry);
void wMenuScroll(WMenu *menu, XEvent *event);
WMenu *wMenuUnderPointer(WScreen *screen);
void wMenuSaveState(WScreen *scr);
void wMenuRestoreState(WScreen *scr);
#endif

1171
src/misc.c Normal file

File diff suppressed because it is too large Load Diff

65
src/motif.h Normal file
View File

@@ -0,0 +1,65 @@
/* motif.h-- stuff for support for mwm hints
* ripped from E.h (enlightenment)
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMMWM_H_
#define WMMWM_H_
#include <X11/Xproto.h>
/* Motif window hints */
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
/* bit definitions for MwmHints.functions */
#define MWM_FUNC_ALL (1L << 0)
#define MWM_FUNC_RESIZE (1L << 1)
#define MWM_FUNC_MOVE (1L << 2)
#define MWM_FUNC_MINIMIZE (1L << 3)
#define MWM_FUNC_MAXIMIZE (1L << 4)
#define MWM_FUNC_CLOSE (1L << 5)
/* bit definitions for MwmHints.decorations */
#define MWM_DECOR_ALL (1L << 0)
#define MWM_DECOR_BORDER (1L << 1)
#define MWM_DECOR_RESIZEH (1L << 2)
#define MWM_DECOR_TITLE (1L << 3)
#define MWM_DECOR_MENU (1L << 4)
#define MWM_DECOR_MINIMIZE (1L << 5)
#define MWM_DECOR_MAXIMIZE (1L << 6)
#define PROP_MWM_HINTS_ELEMENTS 4
/* Motif window hints */
typedef struct _mwmhints
{
CARD32 flags;
CARD32 functions;
CARD32 decorations;
INT32 inputMode;
}
MWMHints;
extern Atom _XA_MOTIF_WM_HINTS;
#endif

1337
src/moveres.c Normal file

File diff suppressed because it is too large Load Diff

271
src/pixmap.c Normal file
View File

@@ -0,0 +1,271 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <wraster.h>
#include <stdlib.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
/*
*----------------------------------------------------------------------
* wPixmapCreateFromXPMData--
* Creates a WPixmap structure and initializes it with the supplied
* XPM structure data.
*
* Returns:
* A WPixmap structure or NULL on failure.
*
* Notes:
* DEF_XPM_CLOSENESS specifies the XpmCloseness
*----------------------------------------------------------------------
*/
WPixmap *
wPixmapCreateFromXPMData(WScreen *scr, char **data)
{
RImage *image;
WPixmap *pix;
image = RGetImageFromXPMData(scr->rcontext, data);
if (!image)
return NULL;
pix = wmalloc(sizeof(WPixmap));
memset(pix, 0, sizeof(WPixmap));
RConvertImageMask(scr->rcontext, image, &pix->image, &pix->mask, 128);
pix->width = image->width;
pix->height = image->height;
pix->depth = scr->w_depth;
RDestroyImage(image);
return pix;
}
/*
*----------------------------------------------------------------------
* wPixmapCreateFromXBMData--
* Creates a WPixmap structure and initializes it with the supplied
* XBM structure data, size and mask.
*
* Returns:
* A WPixmap structure or NULL on failure.
*
*----------------------------------------------------------------------
*/
WPixmap *
wPixmapCreateFromXBMData(WScreen *scr, char *data, char *mask,
int width, int height, unsigned long fg,
unsigned long bg)
{
WPixmap *pix;
pix = wmalloc(sizeof(WPixmap));
memset(pix, 0, sizeof(WPixmap));
pix->image = XCreatePixmapFromBitmapData(dpy, scr->w_win, data, width,
height, fg, bg, scr->w_depth);
if (pix->image==None) {
free(pix);
return NULL;
}
if (mask) {
pix->mask = XCreateBitmapFromData(dpy, scr->w_win, mask, width,
height);
} else {
pix->mask = None;
}
pix->width = width;
pix->height = height;
pix->depth = scr->w_depth;
return pix;
}
WPixmap*
wPixmapCreateFromBitmap(WScreen *scr, Pixmap bitmap, Pixmap mask,
unsigned long fg, unsigned long bg)
{
WPixmap *pix;
XImage *img, *img2;
Window foo;
int bar, x, y;
Pixmap pixmap;
unsigned int width, height, baz, d;
if (!XGetGeometry(dpy, bitmap, &foo, &bar, &bar, &width, &height, &baz,
&d) || d!=1) {
return NULL;
}
img = XGetImage(dpy, bitmap, 0, 0, width, height, AllPlanes, XYPixmap);
if (!img)
return NULL;
img2=XCreateImage(dpy, scr->w_visual, scr->w_depth, ZPixmap,
0, NULL, width, height, 8, 0);
if (!img2) {
XDestroyImage(img);
return NULL;
}
pixmap = XCreatePixmap(dpy, scr->w_win, width, height, scr->w_depth);
if (pixmap==None) {
XDestroyImage(img);
XDestroyImage(img2);
return NULL;
}
img2->data = wmalloc(height * img2->bytes_per_line);
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
if (XGetPixel(img, x, y)==0) {
XPutPixel(img2, x, y, bg);
} else {
XPutPixel(img2, x, y, fg);
}
}
}
XSetClipMask(dpy, scr->copy_gc, None);
XPutImage(dpy, pixmap, scr->copy_gc, img2, 0, 0, 0, 0, width, height);
XDestroyImage(img);
XDestroyImage(img2);
pix = wmalloc(sizeof(WPixmap));
memset(pix, 0, sizeof(WPixmap));
pix->image = pixmap;
pix->mask = mask;
pix->width = width;
pix->height = height;
pix->depth = scr->w_depth;
return pix;
}
WPixmap*
wPixmapCreate(WScreen *scr, Pixmap image, Pixmap mask)
{
WPixmap *pix;
Window foo;
int bar;
unsigned int width, height, depth, baz;
pix = wmalloc(sizeof(WPixmap));
memset(pix, 0, sizeof(WPixmap));
pix->image = image;
pix->mask = mask;
if (!XGetGeometry(dpy, image, &foo, &bar, &bar, &width, &height, &baz,
&depth)) {
wwarning("XGetGeometry() failed during wPixmapCreate()");
free(pix);
return NULL;
}
pix->width = width;
pix->height = height;
pix->depth = depth;
return pix;
}
#if 0
/*
*----------------------------------------------------------------------
* wPixmapLoadXBMFile--
* Creates a WPixmap structure and loads a XBM file into it with
* an optional mask file. If a mask is not wanted, mask_path should be
* NULL.
*
* Returns:
* A WPixmap structure or NULL on failure.
*
* Notes:
* If the mask bitmap is not successfully loaded the operation
* continues as no mask was supplied.
*----------------------------------------------------------------------
*/
WPixmap *
wPixmapLoadXBMFile(WScreen *scr, char *path, char *mask_path)
{
WPixmap *pix;
int junk;
if (!path) return NULL;
pix = wmalloc(sizeof(WPixmap));
memset(pix, 0, sizeof(WPixmap));
if (XReadBitmapFile(dpy, scr->w_win, path, (unsigned *)&(pix->width),
(unsigned *)&(pix->height),
&(pix->image), &junk, &junk)!=BitmapSuccess) {
free(pix);
return NULL;
}
if (mask_path!=NULL) {
if (XReadBitmapFile(dpy, scr->w_win, path, (unsigned *)&junk,
(unsigned *)&junk, &(pix->mask),
&junk, &junk) !=BitmapSuccess) {
wwarning(_("could not load mask bitmap file \"%s\". Won't use mask"),
mask_path);
pix->mask = None;
}
} else {
pix->mask = None;
}
pix->depth = 1;
return pix;
}
#endif
/*
*----------------------------------------------------------------------
* wPixmapDestroy--
* Destroys a WPixmap structure and the pixmap/mask it holds.
*
* Returns:
* None
*----------------------------------------------------------------------
*/
void
wPixmapDestroy(WPixmap *pix)
{
if (!pix->shared) {
if (pix->mask && !pix->client_owned_mask) {
XFreePixmap(dpy, pix->mask);
}
if (pix->image && !pix->client_owned) {
XFreePixmap(dpy, pix->image);
}
}
free(pix);
}

53
src/pixmap.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMPIXMAP_H_
#define WMPIXMAP_H_
typedef struct WPixmap {
Pixmap image; /* icon image */
Pixmap mask; /* icon mask */
int width, height; /* size of pixmap */
int depth; /* depth of pixmap */
unsigned int shared:1; /* if pixmaps should be kept
* when structure is freed */
unsigned int client_owned:1;
unsigned int client_owned_mask:1;
} WPixmap;
WPixmap *wPixmapCreate(WScreen *scr, Pixmap image, Pixmap mask);
WPixmap *wPixmapCreateFromXPMData(WScreen *scr, char **data);
WPixmap *wPixmapCreateFromXBMData(WScreen *scr, char *data, char *mask,
int width, int height, unsigned long fg,
unsigned long bg);
WPixmap *wPixmapLoadXBMFile(WScreen *scr, char *path, char *mask_path);
WPixmap *wPixmapCreateFromBitmap(WScreen *scr, Pixmap bitmap, Pixmap mask,
unsigned long fg, unsigned long bg);
void wPixmapDestroy(WPixmap *pix);
#endif

522
src/placement.c Normal file
View File

@@ -0,0 +1,522 @@
/* placement.c - window and icon placement on screen
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
#include "icon.h"
#include "actions.h"
#include "funcs.h"
#include "application.h"
#include "appicon.h"
#include "dock.h"
extern WPreferences wPreferences;
#define X_ORIGIN wPreferences.window_place_origin.x
#define Y_ORIGIN wPreferences.window_place_origin.y
/*
* interactive window placement is in moveres.c
*/
extern void
InteractivePlaceWindow(WWindow *wwin, int *x_ret, int *y_ret);
#if 0
void
PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
{
int x1, y1, x2, y2;
int icon_x, icon_y;
int left_margin, right_margin;
WCoreWindow *wcore;
left_margin = 0;
right_margin = scr->scr_width;
if (scr->dock) {
if (scr->dock->on_right_side)
right_margin -= wPreferences.icon_size + DOCK_EXTRA_SPACE;
else
left_margin += wPreferences.icon_size + DOCK_EXTRA_SPACE;
}
x1 = left_margin;
y2 = scr->scr_height;
y1 = y2-wPreferences.icon_size*2;
x2 = left_margin+wPreferences.icon_size;
while (1) {
wcore = scr->stacking_list[0];
while (wcore) {
void *parent;
if (x2>=right_margin+wPreferences.icon_size) {
x1 = left_margin;
x2 = left_margin+wPreferences.icon_size*2;
y1 -= wPreferences.icon_size;
y2 -= wPreferences.icon_size;
if (y2<wPreferences.icon_size) {
/* what's this guy doing!? */
*x_ret = 0;
*y_ret = 0;
return;
}
break;
}
parent = (void*) wcore->descriptor.parent;
/* if it is an application icon */
if (wcore->descriptor.parent_type == WCLASS_APPICON) {
icon_x = ((WAppIcon*)parent)->x_pos;
icon_y = ((WAppIcon*)parent)->y_pos;
} else if (wcore->descriptor.parent_type == WCLASS_MINIWINDOW &&
(((WIcon*)parent)->owner->frame->workspace==scr->current_workspace
|| ((WIcon*)parent)->owner->window_flags.omnipresent
|| wPreferences.sticky_icons)) {
icon_x = ((WIcon*)parent)->owner->icon_x;
icon_y = ((WIcon*)parent)->owner->icon_y;
} else {
wcore = wcore->stacking->under;
continue;
}
wcore = wcore->stacking->under;
/* test if place is taken */
if (icon_y>y1 && icon_y<y2) {
if (icon_x<x2 && icon_x>=x1) {
x2 = icon_x+wPreferences.icon_size*2;
x1 = icon_x+wPreferences.icon_size;
/* this place can't be used */
wcore = scr->stacking_list[0];
break;
}
}
}
if (!wcore) {
/* found spot */
break;
}
}
*x_ret = x1;
*y_ret = y2-wPreferences.icon_size;
}
#endif
/*
* Returns True if it is an icon and is in this workspace.
*/
static Bool
iconPosition(WCoreWindow *wcore, int sx1, int sy1, int sx2, int sy2,
int workspace, int *retX, int *retY)
{
void *parent;
int ok = 0;
parent = wcore->descriptor.parent;
/* if it is an application icon */
if (wcore->descriptor.parent_type == WCLASS_APPICON) {
*retX = ((WAppIcon*)parent)->x_pos;
*retY = ((WAppIcon*)parent)->y_pos;
ok = 1;
} else if (wcore->descriptor.parent_type == WCLASS_MINIWINDOW &&
(((WIcon*)parent)->owner->frame->workspace==workspace
|| ((WIcon*)parent)->owner->window_flags.omnipresent
|| wPreferences.sticky_icons)) {
*retX = ((WIcon*)parent)->owner->icon_x;
*retY = ((WIcon*)parent)->owner->icon_y;
ok = 1;
}
/*
* Check if it is inside the screen.
*/
if (ok) {
if (*retX < sx1-wPreferences.icon_size)
ok = 0;
else if (*retX > sx2)
ok = 0;
if (*retY < sy1-wPreferences.icon_size)
ok = 0;
else if (*retY > sy2)
ok = 0;
}
return ok;
}
void
PlaceIcon(WScreen *scr, int *x_ret, int *y_ret)
{
int pf; /* primary axis */
int sf; /* secondary axis */
int fullW;
int fullH;
char *map;
int pi, si;
WCoreWindow *obj;
int sx1, sx2, sy1, sy2; /* screen boundary */
int sw, sh;
int xo, yo;
int xs, ys;
int x, y;
int isize = wPreferences.icon_size;
int done = 0;
/*
* Find out screen boundaries.
*/
sx1 = 0;
sy1 = 0;
sx2 = scr->scr_width;
sy2 = scr->scr_height;
if (scr->dock) {
if (scr->dock->on_right_side)
sx2 -= isize + DOCK_EXTRA_SPACE;
else
sx1 += isize + DOCK_EXTRA_SPACE;
}
sw = isize * (scr->scr_width/isize);
sh = isize * (scr->scr_height/isize);
fullW = (sx2-sx1)/isize;
fullH = (sy2-sy1)/isize;
/* icon yard boundaries */
if (wPreferences.icon_yard & IY_VERT) {
pf = fullH;
sf = fullW;
} else {
pf = fullW;
sf = fullH;
}
if (wPreferences.icon_yard & IY_RIGHT) {
xo = sx2 - isize;
xs = -1;
} else {
xo = sx1;
xs = 1;
}
if (wPreferences.icon_yard & IY_TOP) {
yo = sy1;
ys = 1;
} else {
yo = sy2 - isize;
ys = -1;
}
/*
* Create a map with the occupied slots. 1 means the slot is used
* or at least partially used.
* The slot usage can be optimized by only marking fully used slots
* or slots that have most of it covered.
* Space usage is worse than the fvwm algorithm (used in the old version)
* but complexity is much better (faster) than it.
*/
map = wmalloc((sw+2) * (sh+2));
memset(map, 0, (sw+2) * (sh+2));
#define INDEX(x,y) (((y)+1)*(sw+2) + (x) + 1)
obj = scr->stacking_list[0];
while (obj) {
int x, y;
if (iconPosition(obj, sx1, sy1, sx2, sy2, scr->current_workspace,
&x, &y)) {
int xdi, ydi; /* rounded down */
int xui, yui; /* rounded up */
xdi = x/isize;
ydi = y/isize;
xui = (x+isize/2)/isize;
yui = (y+isize/2)/isize;
map[INDEX(xdi,ydi)] = 1;
map[INDEX(xdi,yui)] = 1;
map[INDEX(xui,ydi)] = 1;
map[INDEX(xui,yui)] = 1;
}
obj = obj->stacking->under;
}
/*
* Default position
*/
*x_ret = 0;
*y_ret = 0;
/*
* Look for an empty slot
*/
for (si=0; si<sf; si++) {
for (pi=0; pi<pf; pi++) {
if (wPreferences.icon_yard & IY_VERT) {
x = xo + xs*(si*isize);
y = yo + ys*(pi*isize);
} else {
x = xo + xs*(pi*isize);
y = yo + ys*(si*isize);
}
if (!map[INDEX(x/isize, y/isize)]) {
*x_ret = x;
*y_ret = y;
done = 1;
break;
}
}
if (done)
break;
}
free(map);
}
static int
smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret)
{
WScreen *scr = wwin->screen_ptr;
int height,width;
int test_x = 0, test_y = Y_ORIGIN;
int loc_ok = False, tw,tx,ty,th;
int swidth, sx;
WWindow *test_window;
int extra_height;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width;
else
extra_height = 24; /* random value */
swidth = scr->scr_width;
sx = X_ORIGIN;
if (scr->dock && wPreferences.no_window_under_dock) {
if (scr->dock->on_right_side)
swidth -= wPreferences.icon_size + DOCK_EXTRA_SPACE;
else if (X_ORIGIN < wPreferences.icon_size + DOCK_EXTRA_SPACE)
sx += wPreferences.icon_size + DOCK_EXTRA_SPACE - X_ORIGIN;
}
/* this was based on fvwm2's smart placement */
height = wwin->client.height+extra_height;
width = wwin->client.width;
while (((test_y + height) < (scr->scr_height)) && (!loc_ok)) {
test_x = sx;
while (((test_x + width) < swidth) && (!loc_ok)) {
loc_ok = True;
test_window = scr->focused_window;
while ((test_window != (WWindow *) 0) && (loc_ok == True)) {
tw = test_window->client.width;
if (test_window->flags.shaded)
th = test_window->frame->top_width;
else
th = test_window->client.height+extra_height;
tx = test_window->frame_x;
ty = test_window->frame_y;
if((tx<(test_x+width))&&((tx + tw) > test_x)&&
(ty<(test_y+height))&&((ty + th)>test_y)&&
(test_window->flags.mapped ||
(test_window->flags.shaded &&
!(test_window->flags.miniaturized ||
test_window->flags.hidden)))) {
loc_ok = False;
}
test_window = test_window->next;
}
test_window = scr->focused_window;
while ((test_window != (WWindow *) 0) && (loc_ok == True)) {
tw = test_window->client.width;
if (test_window->flags.shaded)
th = test_window->frame->top_width;
else
th = test_window->client.height+extra_height;
tx = test_window->frame_x;
ty = test_window->frame_y;
if((tx<(test_x+width))&&((tx + tw) > test_x)&&
(ty<(test_y+height))&&((ty + th)>test_y)&&
(test_window->flags.mapped ||
(test_window->flags.shaded &&
!(test_window->flags.miniaturized ||
test_window->flags.hidden)))) {
loc_ok = False;
}
test_window = test_window->prev;
}
if (loc_ok == True) {
*x_ret = test_x;
*y_ret = test_y;
break;
}
test_x += PLACETEST_HSTEP;
}
test_y += PLACETEST_VSTEP;
}
return loc_ok;
}
static void
cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret, int h)
{
unsigned int extra_height, height, width;
if (wwin->frame)
extra_height = wwin->frame->top_width + wwin->frame->bottom_width;
else
extra_height = 24; /* random value */
*x_ret = h * scr->cascade_index + X_ORIGIN;
*y_ret = h * scr->cascade_index + Y_ORIGIN;
height = wwin->client.height + extra_height;
width = wwin->client.width;
if (width + *x_ret > scr->scr_width || height + *y_ret > scr->scr_height) {
scr->cascade_index = 0;
*x_ret = h*scr->cascade_index + X_ORIGIN;
*y_ret = h*scr->cascade_index + Y_ORIGIN;
}
}
void
PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret)
{
WScreen *scr = wwin->screen_ptr;
int h = scr->title_font->height+TITLEBAR_EXTRA_HEIGHT;
switch (wPreferences.window_placement) {
case WPM_MANUAL:
InteractivePlaceWindow(wwin, x_ret, y_ret);
break;
case WPM_SMART:
if (smartPlaceWindow(wwin, x_ret, y_ret))
break;
/* there isn't a break here, because if we fail, it should fall
through to cascade placement, as people who want tiling want
automagicness aren't going to want to place their window */
case WPM_CASCADE:
if (wPreferences.window_placement == WPM_SMART)
scr->cascade_index++;
cascadeWindow(scr, wwin, x_ret, y_ret, h);
if (wPreferences.window_placement == WPM_CASCADE)
scr->cascade_index++;
if (scr->dock && wPreferences.no_window_under_dock) {
int x2;
x2 = *x_ret + wwin->client.width;
if (scr->dock->on_right_side
&& x2 > scr->scr_width - wPreferences.icon_size -
DOCK_EXTRA_SPACE)
*x_ret = scr->scr_width - wwin->client.width
- wPreferences.icon_size - DOCK_EXTRA_SPACE;
else if (!scr->dock->on_right_side &&
X_ORIGIN < wPreferences.icon_size + DOCK_EXTRA_SPACE)
*x_ret += wPreferences.icon_size + DOCK_EXTRA_SPACE - X_ORIGIN;
}
break;
case WPM_RANDOM:
{
int w, h;
w = (scr->scr_width-wwin->client.width);
h = (scr->scr_height-wwin->client.height);
if (w<1) w = 1;
if (h<1) h = 1;
*x_ret = rand()%w;
*y_ret = rand()%h;
if (scr->dock && wPreferences.no_window_under_dock) {
int x2;
x2 = *x_ret + wwin->client.width;
if (scr->dock->on_right_side
&& x2 > scr->scr_width - wPreferences.icon_size -
DOCK_EXTRA_SPACE)
*x_ret = scr->scr_width - wwin->client.width
- wPreferences.icon_size - DOCK_EXTRA_SPACE;
else if (!scr->dock->on_right_side
&& *x_ret < wPreferences.icon_size)
*x_ret = wPreferences.icon_size + DOCK_EXTRA_SPACE;
}
}
break;
#ifdef DEBUG
default:
puts("Invalid window placement!!!");
*x_ret = 0;
*y_ret = 0;
#endif
}
if (*x_ret < 0)
*x_ret = 0;
else if (*x_ret + wwin->client.width > scr->scr_width)
*x_ret = scr->scr_width - wwin->client.width;
if (*y_ret < 0)
*y_ret = 0;
else if (*y_ret + wwin->client.height > scr->scr_height)
*y_ret = scr->scr_height - wwin->client.height;
}

243
src/properties.c Normal file
View File

@@ -0,0 +1,243 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <string.h>
#include <stdlib.h>
#include "WindowMaker.h"
#include "window.h"
#include "GNUstep.h"
#ifdef MWM_HINTS
# include "motif.h"
#endif
/* atoms */
extern Atom _XA_WM_STATE;
extern Atom _XA_WM_CHANGE_STATE;
extern Atom _XA_WM_PROTOCOLS;
extern Atom _XA_WM_CLIENT_LEADER;
extern Atom _XA_WM_TAKE_FOCUS;
extern Atom _XA_WM_DELETE_WINDOW;
extern Atom _XA_WM_SAVE_YOURSELF;
extern Atom _XA_GNUSTEP_WM_ATTR;
extern Atom _XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW;
extern Atom _XA_WINDOWMAKER_WM_FUNCTION;
extern Atom _XA_WINDOWMAKER_MENU;
extern Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
int
PropGetNormalHints(Window window, XSizeHints *size_hints, int *pre_iccm)
{
long supplied_hints;
if (!XGetWMNormalHints(dpy, window, size_hints, &supplied_hints)) {
return False;
}
if (supplied_hints==(USPosition|USSize|PPosition|PSize|PMinSize|PMaxSize
|PResizeInc|PAspect)) {
*pre_iccm = 1;
} else {
*pre_iccm = 0;
}
return True;
}
int
PropGetWMClass(Window window, char **wm_class, char **wm_instance)
{
XClassHint *class_hint;
class_hint = XAllocClassHint();
if (XGetClassHint(dpy,window,class_hint) == 0) {
*wm_class = NULL;
*wm_instance = NULL;
XFree(class_hint);
return False;
}
*wm_instance = class_hint->res_name;
*wm_class = class_hint->res_class;
XFree(class_hint);
return True;
}
void
PropGetProtocols(Window window, WProtocols *prots)
{
Atom *protocols;
int count, i;
memset(prots, 0, sizeof(WProtocols));
if (!XGetWMProtocols(dpy, window, &protocols, &count)) {
return;
}
for (i=0; i<count; i++) {
if (protocols[i]==_XA_WM_TAKE_FOCUS)
prots->TAKE_FOCUS=1;
else if (protocols[i]==_XA_WM_DELETE_WINDOW)
prots->DELETE_WINDOW=1;
else if (protocols[i]==_XA_WM_SAVE_YOURSELF)
prots->SAVE_YOURSELF=1;
else if (protocols[i]==_XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW)
prots->MINIATURIZE_WINDOW=1;
}
XFree(protocols);
}
int
PropGetGNUstepWMAttr(Window window, GNUstepWMAttributes **attr)
{
Atom type_ret;
int fmt_ret;
unsigned long nitems_ret;
unsigned long bytes_after_ret;
CARD32 *data;
if (XGetWindowProperty(dpy, window, _XA_GNUSTEP_WM_ATTR, 0,
sizeof(GNUstepWMAttributes),
False, _XA_GNUSTEP_WM_ATTR,
&type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
(unsigned char **)&data)!=Success)
return False;
if (type_ret!=_XA_GNUSTEP_WM_ATTR || !data || fmt_ret!=32)
return False;
*attr = malloc(sizeof(GNUstepWMAttributes));
if (!*attr) {
XFree(data);
return False;
}
(*attr)->flags = data[0];
(*attr)->window_style = data[1];
(*attr)->window_level = data[2];
(*attr)->reserved = data[3];
(*attr)->miniaturize_pixmap = data[4];
(*attr)->close_pixmap = data[5];
(*attr)->miniaturize_mask = data[6];
(*attr)->close_mask = data[7];
(*attr)->extra_flags = data[8];
XFree(data);
return True;
}
#ifdef MWM_HINTS
int
PropGetMotifWMHints(Window window, MWMHints **mwmhints)
{
Atom type_ret;
int fmt_ret;
unsigned long nitems_ret;
unsigned long bytes_after_ret;
if (XGetWindowProperty(dpy, window, _XA_MOTIF_WM_HINTS, 0, 20,
False, _XA_MOTIF_WM_HINTS,
&type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
(unsigned char **)mwmhints)!=Success)
return 0;
if (type_ret==_XA_MOTIF_WM_HINTS)
return 1;
else
return 0;
}
#endif /* MWM_HINTS */
void
PropSetWMakerProtocols(Window root)
{
Atom protocols[2];
int count=0;
protocols[count++] = _XA_WINDOWMAKER_MENU;
protocols[count++] = _XA_WINDOWMAKER_WM_FUNCTION;
XChangeProperty(dpy, root, _XA_WINDOWMAKER_WM_PROTOCOLS, XA_ATOM,
32, PropModeReplace, (unsigned char *)protocols, count);
}
int
PropGetClientLeader(Window window, Window *leader)
{
Atom type_ret;
int fmt_ret;
unsigned long nitems_ret;
unsigned long bytes_after_ret;
Window *win;
if (XGetWindowProperty(dpy, window, _XA_WM_CLIENT_LEADER, 0,
sizeof(Window), False, AnyPropertyType,
&type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
(unsigned char**)&win)!=Success)
return 0;
if (!win) return 0;
*leader = (Window)*win;
XFree(win);
return 1;
}
void
PropWriteGNUstepWMAttr(Window window, GNUstepWMAttributes *attr)
{
CARD32 data[9];
/* handle idiot compilers where array of CARD32 != struct of CARD32 */
data[0] = attr->flags;
data[1] = attr->window_style;
data[2] = attr->window_level;
data[3] = 0; /* reserved */
/* The X protocol says XIDs are 32bit */
data[4] = attr->miniaturize_pixmap;
data[5] = attr->close_pixmap;
data[6] = attr->miniaturize_mask;
data[7] = attr->close_mask;
data[8] = attr->extra_flags;
XChangeProperty(dpy, window, _XA_GNUSTEP_WM_ATTR, _XA_GNUSTEP_WM_ATTR,
32, PropModeReplace, (unsigned char *)data, 9);
}
void
PropCleanUp(Window root)
{
XDeleteProperty(dpy, root, _XA_WINDOWMAKER_WM_PROTOCOLS);
XDeleteProperty(dpy, root, XA_WM_ICON_SIZE);
}

47
src/properties.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMPROPERTIES_H_
#define WMPROPERTIES_H_
#include "GNUstep.h"
#ifdef MWM_HINTS
# include "motif.h"
#endif
int PropGetNormalHints(Window window, XSizeHints *size_hints, int *pre_iccm);
void PropGetProtocols(Window window, WProtocols *prots);
int PropGetWMClass(Window window, char **wm_class, char **wm_instance);
int PropGetGNUstepWMAttr(Window window, GNUstepWMAttributes **attr);
void PropWriteGNUstepWMAttr(Window window, GNUstepWMAttributes *attr);
int PropGetClientLeader(Window window, Window *leader);
void PropSetWMakerProtocols(Window root);
void PropCleanUp(Window root);
#ifdef MWM_HINTS
int PropGetMotifWMHints(Window window, MWMHints **mwmhints);
#endif
#endif

491
src/proplist.c Normal file
View File

@@ -0,0 +1,491 @@
/* proplist.c- Hand made proplist parser.
* The one in libPropList causes wmaker to crash if an error is found in
* the parsed file. This parser is also more rigid: it will not accept any
* property lists with errors, but will print more descriptive error messages
* and will hopefully not crash.
*
* WindowMaker window manager
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include "WindowMaker.h"
#include <proplist.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#if 0
#define DPUT(s) puts(s)
#else
#define DPUT(s)
#endif
#define INITIAL_BUFFER_SIZE (16*1024)
#define BUFFER_SIZE_INCREMENT 1024
static int line_number = 1;
static int buffer_size = 0;
static char *buffer = NULL;
static char *file_name;
static proplist_t get_object(FILE *f);
static proplist_t get_array(FILE *f);
static proplist_t get_string(FILE *f);
static proplist_t get_qstring(FILE *f);
static proplist_t get_dictionary(FILE *f);
static INLINE int
get_char(FILE *f)
{
int c;
c = fgetc(f);
if (c=='\n')
line_number++;
return c;
}
static INLINE int
get_non_space_char(FILE *f)
{
int c;
while (1) {
c = fgetc(f);
if (c=='\n')
line_number++;
else if (!isspace(c))
break;
}
if (c!=EOF) {
return c;
} else {
return EOF;
}
}
static char *
unescapestr(char *src)
{
char *dest = wmalloc(strlen(src)+1);
char *src_ptr, *dest_ptr;
char ch;
for (src_ptr=src, dest_ptr=dest; *src_ptr; src_ptr++, dest_ptr++)
{
if(*src_ptr != '\\')
*dest_ptr = *src_ptr;
else
{
ch = *(++src_ptr);
if((ch>='0') && (ch<='3')) /* assume next 2 chars are octal too */
{
*dest_ptr = ((ch & 07) << 3);
*dest_ptr |= ((*(++src_ptr)&07)<<3);
*dest_ptr |= *(++src_ptr)&07;
}
else
{
switch(ch)
{
case 'a' : *dest_ptr = '\a'; break;
case 'b' : *dest_ptr = '\b'; break;
case 't' : *dest_ptr = '\t'; break;
case 'r' : *dest_ptr = '\r'; break;
case 'n' : *dest_ptr = '\n'; break;
case 'v' : *dest_ptr = '\v'; break;
case 'f' : *dest_ptr = '\f'; break;
default : *dest_ptr = *src_ptr;
}
}
}
}
*dest_ptr = 0;
return dest;
}
#define CHECK_BUFFER_SIZE(ptr) \
if ((ptr) >= buffer_size-1) {\
buffer_size += BUFFER_SIZE_INCREMENT;\
buffer = wrealloc(buffer, buffer_size);\
}
#define ISSTRINGABLE(c) (isalnum(c) || (c)=='.' || (c)=='_' || (c)=='/' \
|| (c)=='+')
#define COMPLAIN(msg) wwarning(_("syntax error in %s, line %i:%s"), \
file_name, line_number, msg)
static proplist_t
get_qstring(FILE *f)
{
int c;
int ptr = 0;
int escaping = 0;
int ok = 1;
while (1) {
c = get_char(f);
if (!escaping) {
if (c=='\\') {
escaping = 1;
continue;
}
if (c=='"')
break;
} else {
CHECK_BUFFER_SIZE(ptr);
buffer[ptr++] = '\\';
escaping = 0;
}
if (c==EOF) {
ptr--;
ok = 0;
COMPLAIN(_("unterminated string"));
break;
} else {
CHECK_BUFFER_SIZE(ptr);
buffer[ptr++] = c;
}
}
buffer[ptr] = 0;
if (!ok)
return NULL;
else {
char *tmp = unescapestr(buffer);
proplist_t pl = PLMakeString(tmp);
free(tmp);
return pl;
}
}
static proplist_t
get_string(FILE *f)
{
int c;
int ptr = 0;
while (1) {
c = get_char(f);
if (ISSTRINGABLE(c)) {
CHECK_BUFFER_SIZE(ptr);
buffer[ptr++] = c;
} else {
if (c!=EOF) {
ungetc(c, f);
}
break;
}
}
buffer[ptr] = 0;
if (ptr==0)
return NULL;
else {
char *tmp = unescapestr(buffer);
proplist_t pl = PLMakeString(tmp);
free(tmp);
return pl;
}
}
static proplist_t
get_array(FILE *f)
{
int c;
int ok=1, first=1;
proplist_t list, obj;
list = PLMakeArrayFromElements(NULL);
while (1) {
c = get_non_space_char(f);
if (c==EOF) {
COMPLAIN(_("unterminated array"));
ok = 0;
break;
} else if (c==')') {
break;
} else if (c==',') {
/* continue normally */
} else {
if (!first) {
COMPLAIN(_("missing , in array or unterminated array"));
ok = 0;
break;
} else {
ungetc(c, f);
}
}
first = 0;
/* get the data */
obj = get_object(f);
if (!obj) {
COMPLAIN(_("could not get array element"));
ok = 0;
break;
}
list = PLAppendArrayElement(list, obj);
PLRelease(obj);
}
if (ok)
return list;
else {
PLRelease(list);
return NULL;
}
}
static proplist_t
get_dictionary(FILE *f)
{
int c;
int ok = 1;
proplist_t dict, key, value;
dict = PLMakeDictionaryFromEntries(NULL, NULL);
while (1) {
c = get_non_space_char(f);
if (c==EOF) {
COMPLAIN(_("unterminated dictionary"));
ok = 0;
break;
} else if (c=='}') {
break;
}
/* get the entry */
/* get key */
DPUT("getting dict key");
if (c=='"')
key = get_qstring(f);
else if (ISSTRINGABLE(c)) {
ungetc(c, f);
key = get_string(f);
} else {
if (c=='=')
COMPLAIN(_("missing dictionary key"));
else
COMPLAIN(_("missing dictionary entry key or unterminated dictionary"));
ok = 0;
break;
}
if (!key) {
COMPLAIN(_("error parsing dictionary key"));
ok = 0;
break;
}
DPUT("getting =");
/* get = */
c = get_non_space_char(f);
if (c!='=') {
PLRelease(key);
COMPLAIN(_("missing = in dictionary entry"));
ok = 0;
break;
}
DPUT("getting dict entry data");
/* get data */
value = get_object(f);
if (!value) {
/*
COMPLAIN(_("error parsing dictionary entry value"));
*/
ok = 0;
PLRelease(key);
break;
}
DPUT("getting ;");
/* get ; */
c = get_non_space_char(f);
if (c!=';') {
COMPLAIN(_("missing ; in dictionary entry"));
ok = 0;
PLRelease(key);
PLRelease(value);
break;
}
dict = PLInsertDictionaryEntry(dict, key, value);
PLRelease(key);
PLRelease(value);
}
if (!ok) {
PLRelease(dict);
return NULL;
} else {
return dict;
}
}
static proplist_t
get_data(FILE *f)
{
COMPLAIN("the data datatype is not still implemented");
return NULL;
}
static proplist_t
get_object(FILE *f)
{
int c;
proplist_t pl;
c = get_non_space_char(f);
switch (c) {
/* END OF FILE */
case EOF:
DPUT("EOF");
pl = NULL;
break;
/* dictionary */
case '{':
DPUT("getting dictionary");
pl = get_dictionary(f);
break;
/* array */
case '(':
DPUT("getting arrray");
pl = get_array(f);
break;
/* data */
case '<':
DPUT("getting data");
pl = get_data(f);
break;
/* quoted string */
case '"':
DPUT("getting qstring");
pl = get_qstring(f);
break;
/* string */
default:
if (ISSTRINGABLE(c)) {
DPUT("getting string");
/* put back */
ungetc(c, f);
pl = get_string(f);
} else {
COMPLAIN(_("was expecting a string, dictionary, data or array."));
if (c=='#' || c=='/') {
wwarning(_("Comments are not allowed inside WindowMaker owned domain files."));
}
pl = NULL;
}
break;
}
return pl;
}
proplist_t
ReadProplistFromFile(char *file)
{
FILE *f;
proplist_t pl = NULL;
f = fopen(file, "r");
if (!f) {
wsyserror(_("could not open domain file %s"), file);
return NULL;
}
file_name = file;
line_number = 1;
buffer_size = INITIAL_BUFFER_SIZE;
buffer = wmalloc(buffer_size);
pl = get_object(f);
/* check for illegal characters after EOF */
if (get_non_space_char(f)!=EOF && pl) {
COMPLAIN(_("extra data after end of file"));
/*
* We can't just ignore garbage after the file because the "garbage"
* could be the data and the real garbage be in the beginning of
* the file (wich is now, inside pl)
*/
PLRelease(pl);
pl = NULL;
}
free(buffer);
fclose(f);
if (pl) {
proplist_t fpl;
fpl = PLMakeString(file);
PLSetFilename(pl, fpl);
PLRelease(fpl);
}
return pl;
}

156
src/resources.c Normal file
View File

@@ -0,0 +1,156 @@
/* resources.c - manage X resources (fonts, colors etc)
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "texture.h"
#include "screen.h"
#include "pixmap.h"
/*
*----------------------------------------------------------------------
* wLoadFont--
* Loads a single font into a WFont structure, initializing
* data in it. If the font could not be loaded, fixed will be used.
* If fixed can't be loaded either, the function returns NULL.
*
* Returns:
* The font structure or NULL on error.
*
*----------------------------------------------------------------------
*/
WFont*
wLoadFont(char *font_name)
{
WFont *font;
#ifdef I18N_MB
char **missing;
int num_missing = 0;
char *default_string;
int skyline;
#endif
font = malloc(sizeof(WFont));
if (!font)
return NULL;
#ifdef I18N_MB
font->font = XCreateFontSet(dpy, font_name, &missing, &num_missing,
&default_string);
if (num_missing > 0 && font->font) {
wwarning(_("The following character sets are missing in %s:"),
font_name);
for (skyline = 0; skyline < num_missing; skyline++)
wwarning(missing[skyline]);
XFreeStringList(missing);
wwarning(_("The string \"%s\" will be used in place"),
default_string);
wwarning(_("of any characters from those sets."));
}
if (!font->font) {
wwarning(_("could not create font set %s. Trying fixed"), font_name);
font->font = XCreateFontSet(dpy, "fixed", &missing, &num_missing,
&default_string);
if (num_missing > 0) {
XFreeStringList(missing);
}
if (!font->font) {
free(font);
return NULL;
}
}
font->height = XExtentsOfFontSet(font->font)->max_logical_extent.height;
font->y = font->height+XExtentsOfFontSet(font->font)->max_logical_extent.y;
font->y = font->height-font->y;
#else
font->font = XLoadQueryFont(dpy, font_name);
if (!font->font) {
wwarning(_("could not load font %s. Trying fixed"), font_name);
font->font = XLoadQueryFont(dpy, "fixed");
if (!font->font) {
free(font);
return NULL;
}
}
font->height = font->font->ascent+font->font->descent;
font->y = font->font->ascent;
#endif /* !I18N_MB */
return font;
}
void
wFreeFont(WFont *font)
{
#ifdef I18N_MB
XFreeFontSet(dpy, font->font);
#else
XFreeFont(dpy, font->font);
#endif
free(font);
}
/*
* wfatal(_("could not load any usable font set"));
wfatal(_("could not load any usable font"));
*/
int
wGetColor(WScreen *scr, char *color_name, XColor *color)
{
if (!XParseColor(dpy, scr->colormap, color_name, color)) {
wwarning(_("could not parse color \"%s\""), color_name);
return False;
}
if (!XAllocColor(dpy, scr->colormap, color)) {
wwarning(_("could not allocate color \"%s\""), color_name);
return False;
}
return True;
}
void
wFreeColor(WScreen *scr, unsigned long pixel)
{
if (pixel!=scr->white_pixel && pixel!=scr->black_pixel) {
unsigned long colors[1];
colors[0] = pixel;
XFreeColors(dpy, scr->colormap, colors, 1, 0);
}
}

29
src/resources.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMRESOURCES_H_
#define WMRESOURCES_H_
WFont *wLoadFont(char *font_name);
void wFreeFont(WFont *font);
int wGetColor(WScreen *scr, char *color_name, XColor *color);
void wFreeColor(WScreen *scr, unsigned long pixel);
#endif

1682
src/rootmenu.c Normal file

File diff suppressed because it is too large Load Diff

821
src/screen.c Normal file
View File

@@ -0,0 +1,821 @@
/* screen.c - screen management
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include <wraster.h>
#include "WindowMaker.h"
#include "def_pixmaps.h"
#include "screen.h"
#include "texture.h"
#include "pixmap.h"
#include "menu.h"
#include "funcs.h"
#include "actions.h"
#include "properties.h"
#include "dock.h"
#include "resources.h"
#include "workspace.h"
#include "session.h"
#include "balloon.h"
#include <proplist.h>
#include "defaults.h"
#define EVENT_MASK (LeaveWindowMask|EnterWindowMask|PropertyChangeMask\
|SubstructureNotifyMask|PointerMotionMask \
|SubstructureRedirectMask|ButtonPressMask|ButtonReleaseMask\
|KeyPressMask|KeyReleaseMask)
/**** Global variables ****/
extern Cursor wCursor[WCUR_LAST];
extern WPreferences wPreferences;
extern Atom _XA_WINDOWMAKER_STATE;
extern int wScreenCount;
extern WDDomain *WDWindowMaker;
/**** Local ****/
#define STIPPLE_WIDTH 2
#define STIPPLE_HEIGHT 2
static char STIPPLE_DATA[] = {0x02, 0x01};
static int CantManageScreen = 0;
static proplist_t dApplications = NULL;
static proplist_t dWorkspace;
static proplist_t dDock;
static proplist_t dClip;
static void
make_keys()
{
if (dApplications!=NULL)
return;
dApplications = PLMakeString("Applications");
dWorkspace = PLMakeString("Workspace");
dDock = PLMakeString("Dock");
dClip = PLMakeString("Clip");
}
/*
*----------------------------------------------------------------------
* alreadyRunningError--
* X error handler used to catch errors when trying to do
* XSelectInput() on the root window. These errors probably mean that
* there already is some other window manager running.
*
* Returns:
* Nothing, unless something really evil happens...
*
* Side effects:
* CantManageScreen is set to 1;
*----------------------------------------------------------------------
*/
static int
alreadyRunningError(Display *dpy, XErrorEvent *error)
{
CantManageScreen = 1;
return -1;
}
/*
*----------------------------------------------------------------------
* allocButtonPixmaps--
* Allocate pixmaps used on window operation buttons (those in the
* titlebar). The pixmaps are linked to the program. If XPM is supported
* XPM pixmaps are used otherwise, equivalent bitmaps are used.
*
* Returns:
* Nothing
*
* Side effects:
* Allocates shared pixmaps for the screen. These pixmaps should
* not be freed by anybody.
*----------------------------------------------------------------------
*/
static void
allocButtonPixmaps(WScreen *scr)
{
WPixmap *pix;
/* create predefined pixmaps */
pix = wPixmapCreateFromXPMData(scr, PRED_CLOSE_XPM);
if (pix)
pix->shared = 1;
scr->b_pixmaps[WBUT_CLOSE] = pix;
pix = wPixmapCreateFromXPMData(scr, PRED_BROKEN_CLOSE_XPM);
if (pix)
pix->shared = 1;
scr->b_pixmaps[WBUT_BROKENCLOSE] = pix;
pix = wPixmapCreateFromXPMData(scr, PRED_ICONIFY_XPM);
if (pix)
pix->shared = 1;
scr->b_pixmaps[WBUT_ICONIFY] = pix;
pix = wPixmapCreateFromXPMData(scr, PRED_KILL_XPM);
if (pix)
pix->shared = 1;
scr->b_pixmaps[WBUT_KILL] = pix;
}
static void
draw_dot(WScreen *scr, Drawable d, int x, int y, GC gc)
{
XSetForeground(dpy, gc, scr->black_pixel);
XDrawLine(dpy, d, gc, x, y, x+1, y);
XDrawPoint(dpy, d, gc, x, y+1);
XSetForeground(dpy, gc, scr->white_pixel);
XDrawLine(dpy, d, gc, x+2, y, x+2, y+1);
XDrawPoint(dpy, d, gc, x+1, y+1);
}
static WPixmap*
make3Dots(WScreen *scr)
{
WPixmap *wpix;
GC gc2, gc;
XGCValues gcv;
Pixmap pix, mask;
gc = scr->copy_gc;
pix = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size,
wPreferences.icon_size, scr->w_depth);
XSetForeground(dpy, gc, scr->black_pixel);
XFillRectangle(dpy, pix, gc, 0, 0, wPreferences.icon_size,
wPreferences.icon_size);
XSetForeground(dpy, gc, scr->white_pixel);
draw_dot(scr, pix, 4, wPreferences.icon_size-6, gc);
draw_dot(scr, pix, 9, wPreferences.icon_size-6, gc);
draw_dot(scr, pix, 14, wPreferences.icon_size-6, gc);
mask = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size,
wPreferences.icon_size, 1);
gcv.foreground = 0;
gcv.graphics_exposures = False;
gc2 = XCreateGC(dpy, mask, GCForeground|GCGraphicsExposures, &gcv);
XFillRectangle(dpy, mask, gc2, 0, 0, wPreferences.icon_size,
wPreferences.icon_size);
XSetForeground(dpy, gc2, 1);
XFillRectangle(dpy, mask, gc2, 4, wPreferences.icon_size-6, 3, 2);
XFillRectangle(dpy, mask, gc2, 9, wPreferences.icon_size-6, 3, 2);
XFillRectangle(dpy, mask, gc2, 14, wPreferences.icon_size-6, 3, 2);
XFreeGC(dpy, gc2);
wpix = wPixmapCreate(scr, pix, mask);
wpix->shared = 1;
return wpix;
}
static void
allocGCs(WScreen *scr)
{
XGCValues gcv;
XColor color;
unsigned long mtextcolor;
int gcm;
scr->stipple_bitmap =
XCreateBitmapFromData(dpy, scr->w_win, STIPPLE_DATA, STIPPLE_WIDTH,
STIPPLE_HEIGHT);
gcv.stipple = scr->stipple_bitmap;
gcv.foreground = scr->white_pixel;
gcv.fill_style = FillStippled;
gcv.graphics_exposures = False;
gcm = GCForeground|GCStipple|GCFillStyle|GCGraphicsExposures;
scr->stipple_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
/* selected icon border GCs */
gcv.function = GXcopy;
gcv.foreground = scr->white_pixel;
gcv.background = scr->black_pixel;
gcv.line_width = 1;
gcv.line_style = LineDoubleDash;
gcv.fill_style = FillSolid;
gcv.dash_offset = 0;
gcv.dashes = 4;
gcv.graphics_exposures = False;
gcm = GCFunction | GCGraphicsExposures;
gcm |= GCForeground | GCBackground;
gcm |= GCLineWidth | GCLineStyle;
gcm |= GCFillStyle;
gcm |= GCDashOffset | GCDashList;
scr->icon_select_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
gcm = GCForeground|GCGraphicsExposures;
scr->menu_title_pixel[0] = scr->white_pixel;
gcv.foreground = scr->white_pixel;
gcv.graphics_exposures = False;
scr->menu_title_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
scr->mtext_pixel = scr->black_pixel;
mtextcolor = gcv.foreground = scr->black_pixel;
scr->menu_entry_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
/* selected menu entry GC */
gcm = GCForeground|GCBackground|GCGraphicsExposures;
gcv.foreground = scr->white_pixel;
gcv.background = scr->white_pixel;
gcv.graphics_exposures = False;
scr->select_menu_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
/* disabled menu entry GC */
scr->dtext_pixel = scr->black_pixel;
gcm = GCForeground|GCBackground|GCStipple|GCGraphicsExposures;
gcv.stipple = scr->stipple_bitmap;
gcv.graphics_exposures = False;
scr->disabled_menu_entry_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
/* frame GC */
wGetColor(scr, DEF_FRAME_COLOR, &color);
gcv.foreground = color.pixel;
gcv.function = GXxor;
gcv.line_width = DEF_FRAME_THICKNESS;
gcv.subwindow_mode = IncludeInferiors;
gcv.graphics_exposures = False;
scr->frame_gc = XCreateGC(dpy, scr->root_win, GCForeground|GCGraphicsExposures
|GCFunction|GCSubwindowMode|GCLineWidth, &gcv);
/* line GC */
gcv.foreground = color.pixel;
if (gcv.foreground == 0)
/* XOR:ing with a zero is not going to be of much use, so
in that case, we somewhat arbitrarily xor with 17 instead. */
gcv.foreground = 17;
gcv.function = GXxor;
gcv.subwindow_mode = IncludeInferiors;
gcv.line_width = 1;
gcv.cap_style = CapRound;
gcv.graphics_exposures = False;
gcm = GCForeground|GCFunction|GCSubwindowMode|GCLineWidth|GCCapStyle
|GCGraphicsExposures;
scr->line_gc = XCreateGC(dpy, scr->root_win, gcm, &gcv);
scr->line_pixel = gcv.foreground;
/* copy GC */
gcv.foreground = scr->white_pixel;
gcv.background = scr->black_pixel;
gcv.graphics_exposures = False;
scr->copy_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|GCGraphicsExposures, &gcv);
/* window title text GC */
gcv.graphics_exposures = False;
scr->window_title_gc = XCreateGC(dpy, scr->w_win,GCGraphicsExposures,&gcv);
/* icon title GC */
scr->icon_title_gc = XCreateGC(dpy, scr->w_win, GCGraphicsExposures, &gcv);
/* clip title GC */
scr->clip_title_gc = XCreateGC(dpy, scr->w_win, GCGraphicsExposures, &gcv);
/* move/size display GC */
gcv.graphics_exposures = False;
gcm = GCGraphicsExposures;
scr->info_text_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
/* misc drawing GC */
gcv.graphics_exposures = False;
gcm = GCGraphicsExposures;
scr->draw_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
}
static void
createPixmaps(WScreen *scr)
{
WPixmap *pix;
WMPixmap *wmpix;
RImage *image;
Pixmap p, m;
/* load pixmaps */
pix = wPixmapCreateFromXBMData(scr, (char*)MENU_RADIO_INDICATOR_XBM_DATA,
(char*)MENU_RADIO_INDICATOR_XBM_DATA,
MENU_RADIO_INDICATOR_XBM_SIZE,
MENU_RADIO_INDICATOR_XBM_SIZE,
scr->black_pixel, scr->white_pixel);
if (pix!=NULL)
pix->shared = 1;
scr->menu_radio_indicator = pix;
pix = wPixmapCreateFromXBMData(scr, (char*)MENU_CHECK_INDICATOR_XBM_DATA,
(char*)MENU_CHECK_INDICATOR_XBM_DATA,
MENU_CHECK_INDICATOR_XBM_SIZE,
MENU_CHECK_INDICATOR_XBM_SIZE,
scr->black_pixel, scr->white_pixel);
if (pix!=NULL)
pix->shared = 1;
scr->menu_check_indicator = pix;
pix = wPixmapCreateFromXBMData(scr, (char*)MENU_MINI_INDICATOR_XBM_DATA,
(char*)MENU_MINI_INDICATOR_XBM_DATA,
MENU_MINI_INDICATOR_XBM_SIZE,
MENU_MINI_INDICATOR_XBM_SIZE,
scr->black_pixel, scr->white_pixel);
if (pix!=NULL)
pix->shared = 1;
scr->menu_mini_indicator = pix;
pix = wPixmapCreateFromXBMData(scr, (char*)MENU_HIDE_INDICATOR_XBM_DATA,
(char*)MENU_HIDE_INDICATOR_XBM_DATA,
MENU_HIDE_INDICATOR_XBM_SIZE,
MENU_HIDE_INDICATOR_XBM_SIZE,
scr->black_pixel, scr->white_pixel);
if (pix!=NULL)
pix->shared = 1;
scr->menu_hide_indicator = pix;
pix = wPixmapCreateFromXBMData(scr, (char*)MENU_SHADE_INDICATOR_XBM_DATA,
(char*)MENU_SHADE_INDICATOR_XBM_DATA,
MENU_SHADE_INDICATOR_XBM_SIZE,
MENU_SHADE_INDICATOR_XBM_SIZE,
scr->black_pixel, scr->white_pixel);
if (pix!=NULL)
pix->shared = 1;
scr->menu_shade_indicator = pix;
image = wDefaultGetImage(scr, "Logo", "WMPanel");
if (!image) {
wwarning(_("could not load logo image for panels"));
} else {
if (!RConvertImageMask(scr->rcontext, image, &p, &m, 128)) {
wwarning(_("error making logo image for panel:%s"), RErrorString);
} else {
wmpix = WMCreatePixmapFromXPixmaps(scr->wmscreen, p, m,
image->width, image->height,
scr->depth);
WMSetApplicationIconImage(scr->wmscreen, wmpix);
WMReleasePixmap(wmpix);
}
RDestroyImage(image);
}
if (!wPreferences.flags.nodock || !wPreferences.flags.noclip) {
scr->dock_dots = make3Dots(scr);
}
/* titlebar button pixmaps */
allocButtonPixmaps(scr);
}
/*
*----------------------------------------------------------------------
* createInternalWindows--
* Creates some windows used internally by the program. One to
* receive input focus when no other window can get it and another
* to display window geometry information during window resize/move.
*
* Returns:
* Nothing
*
* Side effects:
* Windows are created and some colors are allocated for the
* window background.
*----------------------------------------------------------------------
*/
static void
createInternalWindows(WScreen *scr)
{
int vmask;
XSetWindowAttributes attribs;
/* window for displaying geometry information during resizes and moves */
vmask = CWBorderPixel|CWBackPixmap|CWBackPixel|CWCursor|CWSaveUnder|CWOverrideRedirect;
attribs.border_pixel = 0;
attribs.save_under = True;
attribs.override_redirect = True;
attribs.cursor = wCursor[WCUR_DEFAULT];
attribs.background_pixmap = None;
if (scr->resizebar_texture[0])
attribs.background_pixel = scr->resizebar_texture[0]->normal.pixel;
else
attribs.background_pixel = scr->light_pixel;
vmask |= CWColormap;
attribs.colormap = scr->w_colormap;
wGetGeometryWindowSize(scr, &scr->geometry_display_width,
&scr->geometry_display_height);
scr->geometry_display =
XCreateWindow(dpy, scr->root_win, 1, 1,
scr->geometry_display_width,
scr->geometry_display_height,
1, scr->w_depth, CopyFromParent, scr->w_visual,
vmask, &attribs);
/* InputOnly window to get the focus when no other window can get it */
vmask = CWEventMask|CWOverrideRedirect;
attribs.event_mask = KeyPressMask|FocusChangeMask;
attribs.override_redirect = True;
scr->no_focus_win=XCreateWindow(dpy,scr->root_win,-10, -10, 4, 4, 0, 0,
InputOnly,CopyFromParent, vmask, &attribs);
XSelectInput(dpy, scr->no_focus_win, KeyPressMask|KeyReleaseMask);
XMapWindow(dpy, scr->no_focus_win);
XSetInputFocus (dpy, scr->no_focus_win, RevertToParent, CurrentTime);
/* shadow window for dock buttons */
vmask = CWBorderPixel|CWBackPixmap|CWBackPixel|CWCursor|CWSaveUnder|CWOverrideRedirect;
attribs.border_pixel = 0;
attribs.save_under = True;
attribs.override_redirect = True;
attribs.background_pixmap = None;
attribs.background_pixel = scr->white_pixel;
vmask |= CWColormap;
attribs.colormap = scr->w_colormap;
scr->dock_shadow =
XCreateWindow(dpy, scr->root_win, 0, 0, wPreferences.icon_size,
wPreferences.icon_size, 0, scr->w_depth, CopyFromParent,
scr->w_visual, vmask, &attribs);
/* workspace name balloon for clip */
vmask = CWBackPixel|CWSaveUnder|CWOverrideRedirect|CWColormap;
attribs.save_under = True;
attribs.override_redirect = True;
attribs.colormap = scr->w_colormap;
attribs.background_pixel = scr->icon_back_texture->normal.pixel;
scr->clip_balloon =
XCreateWindow(dpy, scr->root_win, 0, 0, 10, 10, 0, scr->w_depth,
CopyFromParent, scr->w_visual, vmask, &attribs);
/*
* If the window is clicked without having ButtonPress selected, the
* resulting event will have event.xbutton.window == root.
*/
XSelectInput(dpy, scr->clip_balloon, ButtonPressMask);
}
/*
*----------------------------------------------------------------------
* wScreenInit--
* Initializes the window manager for the given screen and
* allocates a WScreen descriptor for it. Many resources are allocated
* for the screen and the root window is setup appropriately.
*
* Returns:
* The WScreen descriptor for the screen.
*
* Side effects:
* Many resources are allocated and the IconSize property is
* set on the root window.
* The program can be aborted if some fatal error occurs.
*
* TODO: User specifiable visual.
*----------------------------------------------------------------------
*/
WScreen*
wScreenInit(int screen_number)
{
WScreen *scr;
XIconSize icon_size[1];
RContextAttributes rattr;
extern int wVisualID;
long event_mask;
WMColor *color;
XErrorHandler oldHandler;
scr = wmalloc(sizeof(WScreen));
memset(scr, 0, sizeof(WScreen));
/* initialize globals */
scr->screen = screen_number;
scr->root_win = RootWindow(dpy, screen_number);
scr->depth = DefaultDepth(dpy, screen_number);
scr->colormap = DefaultColormap(dpy, screen_number);
scr->scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_number));
scr->scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_number));
CantManageScreen = 0;
oldHandler = XSetErrorHandler((XErrorHandler)alreadyRunningError);
event_mask = EVENT_MASK;
if (wPreferences.disable_root_mouse)
event_mask &= ~(ButtonPressMask|ButtonReleaseMask);
XSelectInput(dpy, scr->root_win, event_mask);
XSync(dpy, False);
XSetErrorHandler(oldHandler);
if (CantManageScreen) {
free(scr);
return NULL;
}
XDefineCursor(dpy, scr->root_win, wCursor[WCUR_DEFAULT]);
/* screen descriptor for raster graphic library */
rattr.flags = RC_RenderMode | RC_ColorsPerChannel;
rattr.render_mode = wPreferences.no_dithering?RM_MATCH:RM_DITHER;
rattr.colors_per_channel = wPreferences.cmap_size;
if (rattr.colors_per_channel<2)
rattr.colors_per_channel = 2;
if (wVisualID>=0) {
rattr.flags |= RC_VisualID;
rattr.visualid = wVisualID;
}
scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
if (!scr->rcontext) {
wwarning(_("could not initialize graphics library context: %s"),
RErrorString);
wAbort(False);
} else {
char **formats;
int i = 0;
formats = RSupportedFileFormats();
if (formats) {
for (i=0; formats[i]!=NULL; i++) {
if (strcmp(formats[i], "TIFF")==0) {
scr->flags.supports_tiff = 1;
break;
}
}
RFreeStringList(formats);
}
}
scr->w_win = scr->rcontext->drawable;
scr->w_visual = scr->rcontext->visual;
scr->w_depth = scr->rcontext->depth;
scr->w_colormap = scr->rcontext->cmap;
scr->black_pixel = scr->rcontext->black;
scr->white_pixel = scr->rcontext->white;
/* create screen descriptor for WINGs */
scr->wmscreen = WMCreateScreenWithRContext(dpy, screen_number,
scr->rcontext);
color = WMGrayColor(scr->wmscreen);
scr->light_pixel = WMColorPixel(color);
WMReleaseColor(color);
color = WMDarkGrayColor(scr->wmscreen);
scr->dark_pixel = WMColorPixel(color);
WMReleaseColor(color);
{
XColor xcol;
/* frame boder color */
wGetColor(scr, FRAME_BORDER_COLOR, &xcol);
scr->frame_border_pixel = xcol.pixel;
}
/* create GCs with default values */
allocGCs(scr);
/* read defaults for this screen */
wReadDefaults(scr, WDWindowMaker->dictionary);
/* create initial workspace */
wWorkspaceNew(scr);
createInternalWindows(scr);
/* create shared pixmaps */
createPixmaps(scr);
/* set icon sizes we can accept from clients */
icon_size[0].min_width = 8;
icon_size[0].min_height = 8;
icon_size[0].max_width = wPreferences.icon_size-4;
icon_size[0].max_height = wPreferences.icon_size-4;
icon_size[0].width_inc = 1;
icon_size[0].height_inc = 1;
XSetIconSizes(dpy, scr->root_win, icon_size, 1);
/* setup WindowMaker protocols property in the root window*/
PropSetWMakerProtocols(scr->root_win);
#ifdef BALLOON_TEXT
/* initialize balloon text stuff */
wBalloonInitialize(scr);
#endif
/* kluge to load menu configurations at startup */
OpenRootMenu(scr, -10000, -10000, False);
wMenuUnmap(scr->root_menu);
return scr;
}
void
wScreenRestoreState(WScreen *scr)
{
proplist_t state;
char *path;
make_keys();
if (wScreenCount == 1)
path = wdefaultspathfordomain("WMState");
else {
char buf[16];
sprintf(buf, "WMState.%i", scr->screen);
path = wdefaultspathfordomain(buf);
}
scr->session_state = PLGetProplistWithPath(path);
free(path);
if (!scr->session_state && wScreenCount>1) {
char buf[16];
sprintf(buf, "WMState.%i", scr->screen);
path = wdefaultspathfordomain(buf);
scr->session_state = PLGetProplistWithPath(path);
free(path);
}
if (!wPreferences.flags.noclip) {
state = PLGetDictionaryEntry(scr->session_state, dClip);
scr->clip_icon = wClipRestoreState(scr, state);
}
wWorkspaceRestoreState(scr);
if (!wPreferences.flags.nodock) {
state = PLGetDictionaryEntry(scr->session_state, dDock);
scr->dock = wDockRestoreState(scr, state, WM_DOCK);
}
}
void
wScreenSaveState(WScreen *scr)
{
WWorkspaceState wstate;
WWindow *wwin;
char *str;
proplist_t path, old_state, foo;
make_keys();
/*
* Save current workspace, so can go back to it upon restart.
*/
wstate.workspace = scr->current_workspace;
XChangeProperty(dpy, scr->root_win, _XA_WINDOWMAKER_STATE,
_XA_WINDOWMAKER_STATE, 32, PropModeReplace,
(unsigned char *) &wstate,
sizeof(WWorkspaceState)/sizeof(int));
/* save state of windows */
wwin = scr->focused_window;
while (wwin) {
wWindowSaveState(wwin);
wwin = wwin->prev;
}
old_state = scr->session_state;
scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
PLSetStringCmpHook(NULL);
/* save dock state to file */
if (!wPreferences.flags.nodock) {
wDockSaveState(scr);
} else {
if ((foo = PLGetDictionaryEntry(old_state, dDock))!=NULL) {
PLInsertDictionaryEntry(scr->session_state, dDock, foo);
}
}
if (!wPreferences.flags.noclip) {
wClipSaveState(scr);
} else {
if ((foo = PLGetDictionaryEntry(old_state, dClip))!=NULL) {
PLInsertDictionaryEntry(scr->session_state, dClip, foo);
}
}
wWorkspaceSaveState(scr, old_state);
if (wPreferences.save_session_on_exit) {
wSessionSaveState(scr);
} else {
if ((foo = PLGetDictionaryEntry(old_state, dApplications))!=NULL) {
PLInsertDictionaryEntry(scr->session_state, dApplications, foo);
}
if ((foo = PLGetDictionaryEntry(old_state, dWorkspace))!=NULL) {
PLInsertDictionaryEntry(scr->session_state, dWorkspace, foo);
}
}
/* clean up */
PLSetStringCmpHook(StringCompareHook);
wMenuSaveState(scr);
if (wScreenCount == 1)
str = wdefaultspathfordomain("WMState");
else {
char buf[16];
sprintf(buf, "WMState.%i", scr->screen);
str = wdefaultspathfordomain(buf);
}
path = PLMakeString(str);
free(str);
PLSetFilename(scr->session_state, path);
PLSave(scr->session_state, YES);
PLRelease(path);
PLRelease(old_state);
}
int
wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height)
{
int moved = 0;
int tol_w, tol_h;
if (width > 20)
tol_w = width/2;
else
tol_w = 20;
if (height > 20)
tol_h = height/2;
else
tol_h = 20;
if (*x+width < 10)
*x = -tol_w, moved = 1;
else if (*x >= scr->scr_width - 10)
*x = scr->scr_width - tol_w - 1, moved = 1;
if (*y < -height + 10)
*y = -tol_h, moved = 1;
else if (*y >= scr->scr_height - 10)
*y = scr->scr_height - tol_h - 1, moved = 1;
return moved;
}

281
src/screen.h Normal file
View File

@@ -0,0 +1,281 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMSCREEN_H_
#define WMSCREEN_H_
#include "wconfig.h"
#include "WindowMaker.h"
#include <sys/types.h>
#include <proplist.h>
typedef struct WFont {
#ifndef I18N_MB
XFontStruct *font;
#else
XFontSet font;
#endif
short height;
short y;
} WFont;
#ifdef EXPERIMENTAL
typedef struct {
Pixmap pixmap; /* None means use pixel */
WMPixel pixel;
proplist_t spec; /* retained */
pid_t pid; /* If !=0, process ID of wmsetbg that
* is rendering the pixmap for this
* texture. Set to 0 when finishes */
} WWorkspaceTexture;
#endif /* EXPERIMENTAL */
#define WTB_LEFT 0
#define WTB_RIGHT 1
#define WTB_FOCUSED 0
#define WTB_UNFOCUSED 2
#define WTB_PFOCUSED 4
#define WTB_MENU 6
/*
* each WScreen is saved into a context associated with it's root window
*/
typedef struct _WScreen {
int screen; /* screen number */
int scr_width; /* size of the screen */
int scr_height;
Window root_win; /* root window of screen */
int depth; /* depth of the default visual */
Colormap colormap; /* root colormap */
int root_colormap_install_count;
struct WWindow *original_cmap_window; /* colormap before installing
* root colormap temporarily */
struct WWindow *cmap_window;
Colormap current_colormap;
Window w_win; /* window to use as drawable
* for new GCs, pixmaps etc. */
Visual *w_visual;
int w_depth;
Colormap w_colormap; /* our colormap */
Window no_focus_win; /* window to get focus when nobody
* else can do it */
struct WWindow *focused_window; /* window that has the focus
* Use this list if you want to
* traverse the entire window list
*/
struct WAppIcon *app_icon_list; /* list of all app-icons on screen */
struct WApplication *wapp_list; /* list of all aplications */
struct _WCoreWindow *stacking_list[MAX_WINDOW_LEVELS];
/* array of lists of windows
* in stacking order.
* The array order is in window level
* order and each list on the array
* is ordered from the topmost to
* the lowest window
*/
int window_level_count[MAX_WINDOW_LEVELS];
int window_count; /* number of windows in window_list */
#ifdef EXPERIMENTAL
WWorkspaceTexture *defaultTexture;
WWorkspaceTexture **wspaceTextures;
int wspaceTextureCount;
#endif /* EXPERIMENTAL */
int workspace_count; /* number of workspaces */
struct WWorkspace **workspaces; /* workspace array */
int current_workspace; /* current workspace number */
WMPixel black_pixel;
WMPixel white_pixel;
WMPixel light_pixel;
WMPixel dark_pixel;
Pixmap stipple_bitmap;
Pixmap transp_stipple; /* for making holes in icon masks for
* transparent icon simulation */
WFont *title_font; /* default font for the titlebars */
WFont *menu_title_font; /* font for menu titlebars */
WFont *menu_entry_font; /* font for menu items */
WFont *icon_title_font; /* for icon titles */
WFont *clip_title_font; /* for clip titles */
WFont *info_text_font; /* text on things like geometry
* hint boxes */
WMPixel select_pixel;
WMPixel select_text_pixel;
/* foreground colors */
WMPixel window_title_pixel[3]; /* window titlebar text (foc, unfoc, pfoc)*/
WMPixel menu_title_pixel[3]; /* menu titlebar text */
WMPixel clip_title_pixel[2]; /* clip title text */
WMPixel mtext_pixel; /* menu item text */
WMPixel dtext_pixel; /* disabled menu item text */
WMPixel line_pixel;
WMPixel frame_border_pixel; /* frame border */
union WTexture *menu_title_texture[3];/* menu titlebar texture (tex, -, -) */
union WTexture *window_title_texture[3]; /* win textures (foc, unfoc, pfoc) */
struct WTexSolid *resizebar_texture[3];/* window resizebar texture (tex, -, -) */
union WTexture *menu_item_texture; /* menu item texture */
struct WTexSolid *menu_item_auxtexture; /* additional texture to draw menu
* cascade arrows */
struct WTexSolid *icon_title_texture;/* icon titles */
struct WTexSolid *widget_texture;
struct WTexSolid *icon_back_texture; /* icon back color for shadowing */
GC window_title_gc; /* window title text GC */
GC menu_title_gc; /* menu titles */
GC icon_title_gc; /* icon title background */
GC clip_title_gc; /* clip title */
GC menu_entry_gc; /* menu entries */
GC select_menu_gc; /* selected menu entries */
GC disabled_menu_entry_gc; /* disabled menu entries */
GC info_text_gc; /* for size/position display */
GC frame_gc; /* gc for resize/move frame (root) */
GC line_gc; /* gc for drawing XORed lines (root) */
GC copy_gc; /* gc for XCopyArea() */
GC stipple_gc; /* gc for stippled filling */
GC icon_select_gc;
GC draw_gc; /* gc for drawing misc things */
struct WPixmap *b_pixmaps[PRED_BPIXMAPS]; /* internal pixmaps for buttons*/
struct WPixmap *menu_radio_indicator;/* left menu indicator */
struct WPixmap *menu_check_indicator;/* left menu indicator for checkmark */
struct WPixmap *menu_mini_indicator; /* for miniwindow */
struct WPixmap *menu_hide_indicator; /* for hidden window */
struct WPixmap *menu_shade_indicator; /* for shaded window */
int app_menu_x, app_menu_y; /* position for application menus */
struct WMenu *root_menu; /* root window menu */
struct WMenu *workspace_menu; /* workspace operation */
struct WMenu *switch_menu; /* window list menu */
struct WMenu *window_menu; /* window command menu */
struct WMenu *icon_menu; /* icon/appicon menu */
struct WMenu *workspace_submenu; /* workspace list for window_menu */
struct WDock *dock; /* the application dock */
struct WPixmap *dock_dots; /* 3 dots for the Dock */
Window dock_shadow; /* shadow for dock buttons */
struct WAppIcon *clip_icon; /* The clip main icon */
struct WMenu *clip_menu; /* Menu for clips */
struct WMenu *clip_submenu; /* Workspace list for clips */
struct WMenu *clip_options; /* Options for Clip */
struct WMenu *clip_ws_menu; /* workspace menu for clip */
struct WDock *last_dock;
Window clip_balloon; /* window for workspace name */
Window geometry_display; /* displays the geometry during
* window resize, move etc. */
unsigned int geometry_display_width;
unsigned int geometry_display_height;
struct RContext *rcontext;
WMScreen *wmscreen; /* for widget library */
struct RImage *icon_tile;
struct RImage *clip_tile;
Pixmap icon_tile_pixmap; /* for app supplied icons */
Pixmap def_icon_pixmap; /* default icons */
Pixmap def_ticon_pixmap;
struct WDialogData *dialog_data;
/* state and other informations */
short cascade_index; /* for cascade window placement */
proplist_t session_state;
/* for double-click detection */
Time last_click_time;
Window last_click_window;
int last_click_button;
/* balloon help data */
struct _WBalloon *balloon;
/* for raise-delay */
WMHandlerID *autoRaiseTimer;
Window autoRaiseWindow; /* window that is scheduled to be
* raised */
struct {
unsigned int startup:1; /* during window manager startup */
unsigned int regenerate_icon_textures:1;
unsigned int dnd_data_convertion_status:1;
unsigned int root_menu_changed_shortcuts:1;
unsigned int added_workspace_menu:1;
unsigned int startup2:1; /* startup phase 2 */
unsigned int supports_tiff:1;
unsigned int clip_balloon_mapped:1;
unsigned int next_click_is_not_double:1;
} flags;
} WScreen;
#define WSS_ROOTMENU (1<<0)
#define WSS_SWITCHMENU (1<<1)
#define WSS_WSMENU (1<<2)
typedef struct WWorkspaceState {
int flags;
int workspace;
#if 0 /* obsoleted by saving menus position in WMState */
int menu_x, menu_y;
int smenu_x, smenu_y;
int wmenu_x, wmenu_y;
#endif
} WWorkspaceState;
WScreen *wScreenInit(int screen_number);
void wScreenSaveState(WScreen *scr);
void wScreenRestoreState(WScreen *scr);
int wScreenBringInside(WScreen *scr, int *x, int *y, int width, int height);
/* in startup.c */
WScreen *wScreenWithNumber(int i);
WScreen *wScreenForRootWindow(Window window); /* window must be valid */
WScreen *wScreenForWindow(Window window); /* slower than above functions */
#endif

508
src/session.c Normal file
View File

@@ -0,0 +1,508 @@
/* session.c - session state handling
*
* Copyright (c) 1998 Dan Pascu
*
* WindowMaker window manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "WindowMaker.h"
#include "screen.h"
#include "window.h"
#include "session.h"
#include "wcore.h"
#include "framewin.h"
#include "workspace.h"
#include "funcs.h"
#include "properties.h"
#include "application.h"
#include "appicon.h"
#include "dock.h"
#include "list.h"
#include <proplist.h>
static proplist_t sApplications = NULL;
static proplist_t sCommand;
static proplist_t sName;
static proplist_t sHost;
static proplist_t sWorkspace;
static proplist_t sShaded;
static proplist_t sMiniaturized;
static proplist_t sHidden;
static proplist_t sGeometry;
static proplist_t sDock;
static proplist_t sYes, sNo;
static void
make_keys()
{
if (sApplications!=NULL)
return;
sApplications = PLMakeString("Applications");
sCommand = PLMakeString("Command");
sName = PLMakeString("Name");
sHost = PLMakeString("Host");
sWorkspace = PLMakeString("Workspace");
sShaded = PLMakeString("Shaded");
sMiniaturized = PLMakeString("Miniaturized");
sHidden = PLMakeString("Hidden");
sGeometry = PLMakeString("Geometry");
sDock = PLMakeString("Dock");
sYes = PLMakeString("Yes");
sNo = PLMakeString("No");
}
static int
getBool(proplist_t value)
{
char *val;
if (!PLIsString(value)) {
return 0;
}
if (!(val = PLGetString(value))) {
return 0;
}
if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
|| strcasecmp(val, "YES")==0) {
return 1;
} else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
|| strcasecmp(val, "NO")==0) {
return 0;
} else {
int i;
if (sscanf(val, "%i", &i)==1) {
return (i!=0);
} else {
wwarning(_("can't convert \"%s\" to boolean"), val);
return 0;
}
}
}
static proplist_t
makeWindowState(WWindow *wwin, WApplication *wapp)
{
WScreen *scr = wwin->screen_ptr;
Window win;
int argc;
char **argv;
char *class, *instance, *command=NULL, buffer[256];
proplist_t win_state, cmd, name, workspace;
proplist_t shaded, miniaturized, hidden, geometry;
proplist_t dock;
if (wwin->main_window!=None && wwin->main_window!=wwin->client_win)
win = wwin->main_window;
else
win = wwin->client_win;
if (XGetCommand(dpy, win, &argv, &argc) && argc>0) {
command = FlattenStringList(argv, argc);
XFreeStringList(argv);
}
if (!command)
return NULL;
if (PropGetWMClass(win, &class, &instance)) {
if (class && instance)
sprintf(buffer, "%s.%s", instance, class);
else if (instance)
sprintf(buffer, "%s", instance);
else if (class)
sprintf(buffer, ".%s", class);
else
sprintf(buffer, ".");
name = PLMakeString(buffer);
cmd = PLMakeString(command);
/*sprintf(buffer, "%d", wwin->frame->workspace+1);
workspace = PLMakeString(buffer);*/
workspace = PLMakeString(scr->workspaces[wwin->frame->workspace]->name);
shaded = wwin->flags.shaded ? sYes : sNo;
miniaturized = wwin->flags.miniaturized ? sYes : sNo;
hidden = wwin->flags.hidden ? sYes : sNo;
sprintf(buffer, "%ix%i+%i+%i", wwin->client.width, wwin->client.height,
wwin->frame_x, wwin->frame_y);
geometry = PLMakeString(buffer);
win_state = PLMakeDictionaryFromEntries(sName, name,
sCommand, cmd,
sWorkspace, workspace,
sShaded, shaded,
sMiniaturized, miniaturized,
sHidden, hidden,
sGeometry, geometry,
NULL);
PLRelease(name);
PLRelease(cmd);
PLRelease(workspace);
PLRelease(geometry);
if (wapp && wapp->app_icon && wapp->app_icon->dock) {
int i;
char *name;
if (wapp->app_icon->dock == scr->dock) {
name="Dock";
} else {
for(i=0; i<scr->workspace_count; i++)
if(scr->workspaces[i]->clip == wapp->app_icon->dock)
break;
assert( i < scr->workspace_count);
/*n = i+1;*/
name = scr->workspaces[i]->name;
}
dock = PLMakeString(name);
PLInsertDictionaryEntry(win_state, sDock, dock);
PLRelease(dock);
}
} else {
win_state = NULL;
}
if (instance) XFree(instance);
if (class) XFree(class);
if (command) free(command);
return win_state;
}
void
wSessionSaveState(WScreen *scr)
{
WWindow *wwin = scr->focused_window;
proplist_t win_info, wks;
proplist_t list=NULL;
LinkedList *wapp_list=NULL;
make_keys();
if (!scr->session_state) {
scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
if (!scr->session_state)
return;
}
list = PLMakeArrayFromElements(NULL);
while (wwin) {
WApplication *wapp=wApplicationOf(wwin->main_window);
if (wwin->transient_for==None && list_find(wapp_list, wapp)==NULL
&& !wwin->window_flags.dont_save_session) {
/* A entry for this application was not yet saved. Save one. */
if ((win_info = makeWindowState(wwin, wapp))!=NULL) {
list = PLAppendArrayElement(list, win_info);
PLRelease(win_info);
/* If we were succesful in saving the info for this window
* add the application the window belongs to, to the
* application list, so no multiple entries for the same
* application are saved.
*/
wapp_list = list_cons(wapp, wapp_list);
}
}
wwin = wwin->prev;
}
PLRemoveDictionaryEntry(scr->session_state, sApplications);
PLInsertDictionaryEntry(scr->session_state, sApplications, list);
PLRelease(list);
wks = PLMakeString(scr->workspaces[scr->current_workspace]->name);
PLInsertDictionaryEntry(scr->session_state, sWorkspace, wks);
PLRelease(wks);
list_free(wapp_list);
}
void
wSessionClearState(WScreen *scr)
{
make_keys();
if (!scr->session_state)
return;
PLRemoveDictionaryEntry(scr->session_state, sApplications);
PLRemoveDictionaryEntry(scr->session_state, sWorkspace);
}
static pid_t
execCommand(WScreen *scr, char *command, char *host)
{
pid_t pid;
char **argv;
int argc;
ParseCommand(command, &argv, &argc);
if (argv==NULL) {
return 0;
}
if ((pid=fork())==0) {
char **args;
int i;
SetupEnvironment(scr);
close(ConnectionNumber(dpy));
args = malloc(sizeof(char*)*(argc+1));
if (!args)
exit(111);
for (i=0; i<argc; i++) {
args[i] = argv[i];
}
args[argc] = NULL;
execvp(argv[0], args);
exit(111);
}
while (argc > 0)
free(argv[--argc]);
free(argv);
return pid;
}
static WSavedState*
getWindowState(WScreen *scr, proplist_t win_state)
{
WSavedState *state = wmalloc(sizeof(WSavedState));
proplist_t value;
char *tmp;
int i;
memset(state, 0, sizeof(WSavedState));
state->workspace = -1;
value = PLGetDictionaryEntry(win_state, sWorkspace);
if (value && PLIsString(value)) {
tmp = PLGetString(value);
if (sscanf(tmp, "%i", &state->workspace)!=1) {
state->workspace = -1;
for (i=0; i < scr->workspace_count; i++) {
if (strcmp(scr->workspaces[i]->name, tmp)==0) {
state->workspace = i;
break;
}
}
} else {
state->workspace--;
}
}
if ((value = PLGetDictionaryEntry(win_state, sShaded))!=NULL)
state->shaded = getBool(value);
if ((value = PLGetDictionaryEntry(win_state, sMiniaturized))!=NULL)
state->miniaturized = getBool(value);
if ((value = PLGetDictionaryEntry(win_state, sHidden))!=NULL)
state->hidden = getBool(value);
value = PLGetDictionaryEntry(win_state, sGeometry);
if (value && PLIsString(value)) {
if (sscanf(PLGetString(value), "%ix%i+%i+%i",
&state->w, &state->h, &state->x, &state->y)==4 &&
(state->w>0 && state->h>0)) {
state->use_geometry = 1;
} else if (sscanf(PLGetString(value), "%i,%i,%i,%i",
&state->x, &state->y, &state->w, &state->h)==4 &&
(state->w>0 && state->h>0)) {
/* TODO: remove redundant sscanf() in version 0.20.x */
state->use_geometry = 1;
}
}
return state;
}
#define SAME(x, y) (((x) && (y) && !strcmp((x), (y))) || (!(x) && !(y)))
void
wSessionRestoreState(WScreen *scr)
{
WSavedState *state;
char *instance, *class, *command, *host;
proplist_t win_info, apps, cmd, value;
pid_t pid;
int i, count;
WDock *dock;
WAppIcon *btn=NULL;
int j, n, found;
char *tmp;
make_keys();
if (!scr->session_state)
return;
PLSetStringCmpHook(NULL);
apps = PLGetDictionaryEntry(scr->session_state, sApplications);
if (!apps)
return;
count = PLGetNumberOfElements(apps);
if (count==0)
return;
for (i=0; i<count; i++) {
win_info = PLGetArrayElement(apps, i);
cmd = PLGetDictionaryEntry(win_info, sCommand);
if (!cmd || !PLIsString(cmd) || !(command = PLGetString(cmd))) {
continue;
}
value = PLGetDictionaryEntry(win_info, sName);
if (!value)
continue;
ParseWindowName(value, &instance, &class, "session");
if (!instance && !class)
continue;
value = PLGetDictionaryEntry(win_info, sHost);
if (value && PLIsString(value))
host = PLGetString(value);
else
host = NULL;
state = getWindowState(scr, win_info);
dock = NULL;
value = PLGetDictionaryEntry(win_info, sDock);
if (value && PLIsString(value) && (tmp = PLGetString(value))!=NULL) {
if (sscanf(tmp, "%i", &n)!=1) {
if (!strcasecmp(tmp, "DOCK")) {
dock = scr->dock;
} else {
for (j=0; j < scr->workspace_count; j++) {
if (strcmp(scr->workspaces[j]->name, tmp)==0) {
dock = scr->workspaces[j]->clip;
break;
}
}
}
} else {
if (n == 0) {
dock = scr->dock;
} else if (n>0 && n<=scr->workspace_count) {
dock = scr->workspaces[n-1]->clip;
}
}
}
found = 0;
if (dock!=NULL) {
for (j=0; j<dock->max_icons; j++) {
btn = dock->icon_array[j];
if (btn && SAME(instance, btn->wm_instance) &&
SAME(class, btn->wm_class) &&
SAME(command, btn->command)) {
found = 1;
break;
}
}
}
if (found) {
wDockLaunchWithState(dock, btn, state);
} else if ((pid = execCommand(scr, command, host)) > 0) {
wAddWindowSavedState(instance, class, command, pid, state);
} else {
free(state);
}
if (instance) free(instance);
if (class) free(class);
}
/* clean up */
PLSetStringCmpHook(StringCompareHook);
}
void
wSessionRestoreLastWorkspace(WScreen *scr)
{
proplist_t wks;
int w, i;
char *tmp;
make_keys();
if (!scr->session_state)
return;
PLSetStringCmpHook(NULL);
wks = PLGetDictionaryEntry(scr->session_state, sWorkspace);
if (!wks || !PLIsString(wks))
return;
tmp = PLGetString(wks);
/* clean up */
PLSetStringCmpHook(StringCompareHook);
if (sscanf(tmp, "%i", &w)!=1) {
w = -1;
for (i=0; i < scr->workspace_count; i++) {
if (strcmp(scr->workspaces[i]->name, tmp)==0) {
w = i;
break;
}
}
} else {
w--;
}
if (w!=scr->current_workspace && w<scr->workspace_count) {
wWorkspaceChange(scr, w);
}
}

34
src/session.h Normal file
View File

@@ -0,0 +1,34 @@
/* session.h
*
* Copyright (c) 1998 Dan Pascu
*
* WindowMaker window manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMSESSION_H_
#define WMSESSION_H_
void wSessionSaveState(WScreen *scr);
void wSessionClearState(WScreen *scr);
void wSessionRestoreState(WScreen *scr);
void wSessionRestoreLastWorkspace(WScreen *scr);
#endif

121
src/shutdown.c Normal file
View File

@@ -0,0 +1,121 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include "WindowMaker.h"
#include "window.h"
#include "client.h"
#include "funcs.h"
#include "properties.h"
#include "winspector.h"
extern Atom _XA_WM_DELETE_WINDOW;
extern Time LastTimestamp;
/*
*----------------------------------------------------------------------
* RestoreDesktop--
* Puts the desktop in a usable state when exiting.
*
* Side effects:
* All frame windows are removed and windows are reparented
* back to root. Windows that are outside the screen are
* brought to a viable place.
*
*----------------------------------------------------------------------
*/
void
RestoreDesktop(WScreen *scr)
{
int i;
XGrabServer(dpy);
wDestroyInspectorPanels();
/* reparent windows back to the root window, keeping the stacking order */
for (i=0; i<MAX_WINDOW_LEVELS; i++) {
WCoreWindow *core, *next;
WWindow *wwin;
if (!scr->stacking_list[i])
continue;
core = scr->stacking_list[i];
/* go to the end of the list */
while (core->stacking->under)
core = core->stacking->under;
while (core) {
next = core->stacking->above;
if (core->descriptor.parent_type==WCLASS_WINDOW) {
wwin = core->descriptor.parent;
wwin->flags.mapped=1;
wUnmanageWindow(wwin, !wwin->flags.internal_window);
}
core = next;
}
}
XUngrabServer(dpy);
XSetInputFocus(dpy, PointerRoot, RevertToParent, CurrentTime);
wColormapInstallForWindow(scr, NULL);
PropCleanUp(scr->root_win);
XSync(dpy, 0);
}
/*
*----------------------------------------------------------------------
* WipeDesktop--
* Kills all windows in a screen. Send DeleteWindow to all windows
* that support it and KillClient on all windows that don't.
*
* Side effects:
* All managed windows are closed.
*
* TODO: change to XQueryTree()
*----------------------------------------------------------------------
*/
void
WipeDesktop(WScreen *scr)
{
WWindow *wwin;
wwin = scr->focused_window;
while (wwin) {
if (wwin->protocols.DELETE_WINDOW)
wClientSendProtocol(wwin, _XA_WM_DELETE_WINDOW, LastTimestamp);
else
wClientKill(wwin);
wwin = wwin->prev;
}
XSync(dpy, False);
}

602
src/stacking.c Normal file
View File

@@ -0,0 +1,602 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "WindowMaker.h"
#include "screen.h"
#include "window.h"
#include "funcs.h"
#include "actions.h"
#include "properties.h"
#include "stacking.h"
/*** Global Variables ***/
extern XContext wStackContext;
extern WPreferences wPreferences;
static int
levelToIndex(int level)
{
switch (level) {
case WMNormalWindowLevel:
return 0;
case WMFloatingWindowLevel:
return 1;
case WMDockWindowLevel:
return 2;
case WMSubmenuWindowLevel:
return 3;
case WMMainMenuWindowLevel:
return 4;
default:
return 0;
}
}
/*
*----------------------------------------------------------------------
* RemakeStackList--
* Remakes the stacking_list for the screen, getting the real
* stacking order from the server and reordering windows that are not
* in the correct stacking.
*
* Side effects:
* The stacking order list and the actual window stacking
* may be changed (corrected)
*
*----------------------------------------------------------------------
*/
void
RemakeStackList(WScreen *scr)
{
Window *windows;
unsigned int nwindows;
Window junkr, junkp;
WCoreWindow *frame;
WCoreWindow *onbotw[MAX_WINDOW_LEVELS];
int level;
int i, c;
if (!XQueryTree(dpy, scr->root_win, &junkr, &junkp, &windows, &nwindows)) {
wwarning(_("could not get window list!!"));
return;
} else {
for (i=0; i<MAX_WINDOW_LEVELS; i++) {
scr->stacking_list[i] = NULL;
onbotw[i] = NULL;
scr->window_level_count[i] = 0;
}
/* verify list integrity */
c=0;
for (i=0; i<nwindows; i++) {
if (XFindContext(dpy, windows[i], wStackContext, (XPointer*)&frame)
==XCNOENT) {
continue;
}
if (!frame) continue;
c++;
level = levelToIndex(frame->stacking->window_level);
if (onbotw[level])
onbotw[level]->stacking->above = frame;
frame->stacking->under = onbotw[level];
frame->stacking->above = NULL;
onbotw[level] = frame;
scr->window_level_count[level]++;
}
XFree(windows);
#ifdef DEBUG0
if (c!=scr->window_count) {
puts("Found different number of windows than in window lists!!!");
}
#endif
scr->window_count = c;
}
/* now, just concatenate the lists */
for (i=0; i<MAX_WINDOW_LEVELS; i++) {
scr->stacking_list[i] = onbotw[i];
if (onbotw[i])
onbotw[i]->stacking->above = NULL;
}
CommitStacking(scr);
}
/*
*----------------------------------------------------------------------
* CommitStacking--
* Reorders the actual window stacking, so that it has the stacking
* order in the internal window stacking lists. It does the opposite
* of RemakeStackList().
*
* Side effects:
* Windows may be restacked.
*----------------------------------------------------------------------
*/
void
CommitStacking(WScreen *scr)
{
WCoreWindow *tmp;
int nwindows;
Window *windows;
int i, level;
nwindows = scr->window_count;
windows = wmalloc(sizeof(Window)*nwindows);
i=0;
for (level=MAX_WINDOW_LEVELS-1; level>=0; level--) {
tmp = scr->stacking_list[level];
while (tmp) {
#ifndef DEBUG
if (i>=nwindows) {
puts("Internal inconsistency! window_count is incorrect!!!");
printf("window_count says %i windows\n", nwindows);
free(windows);
return;
}
#endif
windows[i++] = tmp->window;
tmp = tmp->stacking->under;
}
}
XRestackWindows(dpy, windows, i);
free(windows);
}
/*
*----------------------------------------------------------------------
* moveFrameToUnder--
* Reestacks windows so that "frame" is under "under".
*
* Returns:
* None
*
* Side effects:
* Changes the stacking order of frame.
*----------------------------------------------------------------------
*/
static void
moveFrameToUnder(WCoreWindow *under, WCoreWindow *frame)
{
Window wins[2];
wins[0] = under->window;
wins[1] = frame->window;
XRestackWindows(dpy, wins, 2);
}
/*
*----------------------------------------------------------------------
* wRaiseFrame--
* Raises a frame taking the window level and the on_top flag
* into account.
*
* Returns:
* None
*
* Side effects:
* Window stacking order and window list is changed.
*
*----------------------------------------------------------------------
*/
void
wRaiseFrame(WCoreWindow *frame)
{
WCoreWindow *wlist=frame;
int level = levelToIndex(frame->stacking->window_level);
int i;
/* already on top */
if (frame->stacking->above == NULL) {
return;
}
/* insert on top of other windows */
while (wlist)
wlist = wlist->stacking->above;
/* window is inserted before the point found */
if (wlist==NULL) {
/* top most window (last on the list) */
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
frame->stacking->above = NULL;
frame->stacking->under = frame->screen_ptr->stacking_list[level];
frame->screen_ptr->stacking_list[level]->stacking->above=frame;
frame->screen_ptr->stacking_list[level] = frame;
} else if (frame!=wlist) {
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
frame->stacking->above = wlist;
frame->stacking->under = wlist->stacking->under;
if (wlist->stacking->under)
wlist->stacking->under->stacking->above = frame;
wlist->stacking->under = frame;
}
if (wPreferences.on_top_transients) {
/* raise transients under us from bottom to top
* so that the order is kept */
again:
wlist = frame->stacking->under;
while (wlist && wlist->stacking->under)
wlist = wlist->stacking->under;
while (wlist && wlist!=frame) {
if (wlist->stacking->child_of == frame) {
wRaiseFrame(wlist);
goto again;
}
wlist = wlist->stacking->above;
}
# if 0
again:
wlist = frame->stacking->under;
while (wlist) {
if (wlist->stacking->child_of == frame) {
/* transient for us */
wRaiseFrame(wlist);
goto again; /* need this or we'll get in a loop */
}
wlist = wlist->stacking->under;
}
#endif
}
/* try to optimize things a little */
if (frame->stacking->above == NULL) {
WCoreWindow *above=NULL;
for (i=level+1; i<MAX_WINDOW_LEVELS; i++) {
if (frame->screen_ptr->stacking_list[i]!=NULL) {
/* can't optimize */
above = frame->screen_ptr->stacking_list[i];
while (above->stacking->under)
above = above->stacking->under;
break;
}
}
if (!above) {
XRaiseWindow(dpy, frame->window);
} else {
moveFrameToUnder(above, frame);
}
} else {
moveFrameToUnder(frame->stacking->above, frame);
}
}
void
wRaiseLowerFrame(WCoreWindow *frame)
{
if (!frame->stacking->above
||(frame->stacking->window_level
!=frame->stacking->above->stacking->window_level))
wLowerFrame(frame);
else
wRaiseFrame(frame);
}
void
wLowerFrame(WCoreWindow *frame)
{
WScreen *scr=frame->screen_ptr;
WCoreWindow *prev, *wlist=frame;
int level = levelToIndex(frame->stacking->window_level);
int i;
/* already in bottom */
if (wlist->stacking->under==NULL) {
return;
}
if (wPreferences.on_top_transients &&
wlist->stacking->under==wlist->stacking->child_of) {
return;
}
prev = wlist;
/* remove from the list */
if (scr->stacking_list[level] == frame) {
/* it was the top window */
scr->stacking_list[level] = frame->stacking->under;
scr->stacking_list[level]->stacking->above = NULL;
} else {
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
}
wlist = scr->stacking_list[level];
/* look for place to put this window */
if (wPreferences.on_top_transients) {
WCoreWindow *owner = frame->stacking->child_of;
if (owner != wlist) {
while (wlist->stacking->under) {
/* if this is a transient, it should not be placed under
* it's owner */
if (owner == wlist->stacking->under)
break;
wlist = wlist->stacking->under;
}
}
} else {
while (wlist->stacking->under) {
wlist = wlist->stacking->under;
}
}
/* insert under the place found */
frame->stacking->above = wlist;
frame->stacking->under = wlist->stacking->under;
if (wlist->stacking->under)
wlist->stacking->under->stacking->above = frame;
wlist->stacking->under = frame;
/* try to optimize things a little */
if (frame->stacking->above == NULL) {
WCoreWindow *above = NULL;
for (i=level-1; i>=0; i--) {
if (scr->stacking_list[i]!=NULL) {
/* can't optimize */
above = scr->stacking_list[i];
while (above->stacking->under)
above = above->stacking->under;
break;
}
}
if (!above) {
XLowerWindow(dpy, frame->window);
} else {
moveFrameToUnder(above, frame);
}
} else {
moveFrameToUnder(frame->stacking->above, frame);
}
}
/*
*----------------------------------------------------------------------
* AddToStackList--
* Inserts the frame in the top of the stacking list. The
* stacking precedence is obeyed.
*
* Returns:
* None
*
* Side effects:
* The frame is added to it's screen's window list.
*----------------------------------------------------------------------
*/
void
AddToStackList(WCoreWindow *frame)
{
WCoreWindow *prev, *tmpw, *wlist;
int index = levelToIndex(frame->stacking->window_level);
frame->screen_ptr->window_count++;
frame->screen_ptr->window_level_count[index]++;
XSaveContext(dpy, frame->window, wStackContext, (XPointer)frame);
tmpw = frame->screen_ptr->stacking_list[index];
if (!tmpw) {
frame->screen_ptr->stacking_list[index] = frame;
frame->stacking->above = NULL;
frame->stacking->under = NULL;
CommitStacking(frame->screen_ptr);
return;
}
prev = tmpw;
/* check if this is a transient owner */
if (wPreferences.on_top_transients) {
WCoreWindow *trans = NULL;
wlist = frame->screen_ptr->stacking_list[index];
while (wlist) {
if (wlist->stacking->child_of == frame)
trans = wlist;
wlist = wlist->stacking->under;
}
frame->stacking->above = trans;
if (trans) {
frame->stacking->under = trans->stacking->under;
if (trans->stacking->under) {
trans->stacking->under->stacking->above = frame;
}
trans->stacking->under = frame;
} else {
frame->stacking->under = tmpw;
tmpw->stacking->above = frame;
frame->screen_ptr->stacking_list[index] = frame;
}
} else {
/* put on top of the stacking list */
frame->stacking->above = NULL;
frame->stacking->under = tmpw;
tmpw->stacking->above = frame;
frame->screen_ptr->stacking_list[index] = frame;
}
CommitStacking(frame->screen_ptr);
}
/*
*----------------------------------------------------------------------
* MoveInStackListAbove--
* Moves the frame above "next".
*
* Returns:
* None
*
* Side effects:
* Stacking order may be changed.
* Window level for frame may be changed.
*----------------------------------------------------------------------
*/
void
MoveInStackListAbove(WCoreWindow *next, WCoreWindow *frame)
{
WCoreWindow *tmpw;
int index;
if (!next || frame->stacking->under == next)
return;
if (frame->stacking->window_level != next->stacking->window_level)
ChangeStackingLevel(frame, next->stacking->window_level);
index = levelToIndex(frame->stacking->window_level);
tmpw = frame->screen_ptr->stacking_list[index];
if (tmpw == frame)
frame->screen_ptr->stacking_list[index] = frame->stacking->under;
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
if (next->stacking->above)
next->stacking->above->stacking->under = frame;
frame->stacking->under = next;
frame->stacking->above = next->stacking->above;
next->stacking->above = frame;
if (tmpw == next)
frame->screen_ptr->stacking_list[index] = frame;
/* try to optimize things a little */
if (frame->stacking->above == NULL) {
WCoreWindow *above=NULL;
int i;
for (i=index+1; i<MAX_WINDOW_LEVELS; i++) {
if (frame->screen_ptr->stacking_list[i]!=NULL) {
/* can't optimize */
above = frame->screen_ptr->stacking_list[i];
while (above->stacking->under)
above = above->stacking->under;
break;
}
}
if (!above) {
XRaiseWindow(dpy, frame->window);
} else {
moveFrameToUnder(above, frame);
}
} else {
moveFrameToUnder(frame->stacking->above, frame);
}
}
/*
*----------------------------------------------------------------------
* MoveInStackListUnder--
* Moves the frame under "prev".
*
* Returns:
* None
*
* Side effects:
* Stacking order may be changed.
* Window level for frame may be changed.
*----------------------------------------------------------------------
*/
void
MoveInStackListUnder(WCoreWindow *prev, WCoreWindow *frame)
{
WCoreWindow *tmpw;
int index;
if (!prev || frame->stacking->above == prev)
return;
if (frame->stacking->window_level != prev->stacking->window_level)
ChangeStackingLevel(frame, prev->stacking->window_level);
index = levelToIndex(frame->stacking->window_level);
tmpw = frame->screen_ptr->stacking_list[index];
if (tmpw == frame)
frame->screen_ptr->stacking_list[index] = frame->stacking->under;
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
if (prev->stacking->under)
prev->stacking->under->stacking->above = frame;
frame->stacking->above = prev;
frame->stacking->under = prev->stacking->under;
prev->stacking->under = frame;
moveFrameToUnder(prev, frame);
}
void
RemoveFromStackList(WCoreWindow *frame)
{
int index = levelToIndex(frame->stacking->window_level);
if (XDeleteContext(dpy, frame->window, wStackContext)==XCNOENT) {
#ifdef DEBUG0
wwarning("RemoveFromStackingList(): window not in list ");
#endif
return;
}
/* remove from the window stack list */
if (frame->stacking->under)
frame->stacking->under->stacking->above = frame->stacking->above;
if (frame->stacking->above)
frame->stacking->above->stacking->under = frame->stacking->under;
else /* this was the first window on the list */
frame->screen_ptr->stacking_list[index] = frame->stacking->under;
frame->screen_ptr->window_count--;
frame->screen_ptr->window_level_count[index]--;
}
void
ChangeStackingLevel(WCoreWindow *frame, int new_level)
{
int old_level;
if (frame->stacking->window_level == new_level)
return;
old_level = frame->stacking->window_level;
RemoveFromStackList(frame);
frame->stacking->window_level = new_level;
AddToStackList(frame);
if (old_level > new_level) {
wRaiseFrame(frame);
} else {
wLowerFrame(frame);
}
}

46
src/stacking.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMSTACKING_H_
#define WMSTACKING_H_
void wRaiseFrame(WCoreWindow *frame);
void wLowerFrame(WCoreWindow *frame);
void wRaiseLowerFrame(WCoreWindow *frame);
void AddToStackList(WCoreWindow *frame);
void MoveInStackListAbove(WCoreWindow *next, WCoreWindow *frame);
void MoveInStackListUnder(WCoreWindow *prev, WCoreWindow *frame);
void RemoveFromStackList(WCoreWindow *frame);
void ChangeStackingLevel(WCoreWindow *frame, int new_level);
void RemakeStackList(WScreen *scr);
void CommitStacking(WScreen *scr);
#endif

1
src/stamp-h.in Normal file
View File

@@ -0,0 +1 @@
timestamp

898
src/startup.c Normal file
View File

@@ -0,0 +1,898 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#ifdef __FreeBSD__
#include <sys/signal.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <X11/cursorfont.h>
#include <X11/Xproto.h>
#include <X11/keysym.h>
#include "WindowMaker.h"
#include "GNUstep.h"
#ifdef MWM_HINTS
# include "motif.h"
#endif
#include "texture.h"
#include "screen.h"
#include "window.h"
#include "actions.h"
#include "client.h"
#include "funcs.h"
#include "dock.h"
#include "workspace.h"
#include "keybind.h"
#include "framewin.h"
#include "session.h"
#include "defaults.h"
#include "xutil.h"
#ifdef WMSOUND
#include "wmsound.h"
#endif
#if 0
#ifdef SYS_SIGLIST_DECLARED
extern const char * const sys_siglist[];
#endif
#endif
/****** Global Variables ******/
extern WPreferences wPreferences;
extern WDDomain *WDWindowMaker;
extern WDDomain *WDRootMenu;
extern WDDomain *WDWindowAttributes;
extern WShortKey wKeyBindings[WKBD_LAST];
extern int wScreenCount;
/* contexts */
extern XContext wWinContext;
extern XContext wAppWinContext;
extern XContext wStackContext;
/* atoms */
extern Atom _XA_WM_STATE;
extern Atom _XA_WM_CHANGE_STATE;
extern Atom _XA_WM_PROTOCOLS;
extern Atom _XA_WM_TAKE_FOCUS;
extern Atom _XA_WM_DELETE_WINDOW;
extern Atom _XA_WM_SAVE_YOURSELF;
extern Atom _XA_WM_CLIENT_LEADER;
extern Atom _XA_WM_COLORMAP_WINDOWS;
extern Atom _XA_GNUSTEP_WM_ATTR;
extern Atom _XA_WINDOWMAKER_MENU;
extern Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
extern Atom _XA_WINDOWMAKER_STATE;
extern Atom _XA_WINDOWMAKER_WM_FUNCTION;
extern Atom _XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW;
extern Atom _XA_GNUSTEP_WM_RESIZEBAR;
#ifdef OFFIX_DND
extern Atom _XA_DND_PROTOCOL;
extern Atom _XA_DND_SELECTION;
#endif
/* cursors */
extern Cursor wCursor[WCUR_LAST];
/* special flags */
extern char WRestartASAP;
extern char WExitASAP;
extern char WDelayedActionSet;
/***** Local *****/
static WScreen **wScreen = NULL;
static unsigned int _NumLockMask = 0;
static unsigned int _ScrollLockMask = 0;
static void manageAllWindows();
extern void NotifyDeadProcess(pid_t pid, unsigned char status);
static int
catchXError(Display *dpy, XErrorEvent *error)
{
char buffer[MAXLINE];
/* ignore some errors */
if (error->resourceid != None
&& ((error->error_code == BadDrawable
&& error->request_code == X_GetGeometry)
|| (error->error_code == BadMatch
&& (error->request_code == X_SetInputFocus))
|| (error->error_code == BadWindow)
/*
&& (error->request_code == X_GetWindowAttributes
|| error->request_code == X_SetInputFocus
|| error->request_code == X_ChangeWindowAttributes
|| error->request_code == X_GetProperty
|| error->request_code == X_ChangeProperty
|| error->request_code == X_QueryTree
|| error->request_code == X_GrabButton
|| error->request_code == X_UngrabButton
|| error->request_code == X_SendEvent
|| error->request_code == X_ConfigureWindow))
*/
|| (error->request_code == X_InstallColormap))) {
#ifndef DEBUG
return 0;
#else
printf("got X error %x %x %x\n", error->request_code,
error->error_code, (unsigned)error->resourceid);
return 0;
#endif
}
FormatXError(dpy, error, buffer, MAXLINE);
wwarning(_("internal X error: %s\n"), buffer);
return -1;
}
/*
*----------------------------------------------------------------------
* handleXIO-
* Handle X shutdowns and other stuff.
*----------------------------------------------------------------------
*/
static int
handleXIO(Display *dpy)
{
exit(0);
}
/*
*----------------------------------------------------------------------
* delayedAction-
* Action to be executed after the signal() handler is exited.
*----------------------------------------------------------------------
*/
static void
delayedAction(void *cdata)
{
WDelayedActionSet = 0;
/*
* Make the event dispatcher do whatever it needs to do,
* including handling zombie processes, restart and exit
* signals.
*/
DispatchEvent(NULL);
}
/*
*----------------------------------------------------------------------
* handleSig--
* general signal handler. Exits the program gently.
*----------------------------------------------------------------------
*/
static RETSIGTYPE
handleSig(int sig)
{
static int already_crashed = 0;
#ifndef NO_EMERGENCY_AUTORESTART
char *argv[2];
argv[1] = NULL;
#endif
/*
* No functions that potentially do Xlib calls should be called from
* here. Xlib calls are not atomic so, so the logical integrity of
* Xlib is not guaranteed if a Xlib call is made from a signal handler.
*/
if (sig == SIGHUP) {
#ifdef SYS_SIGLIST_DECLARED
wwarning(_("got signal %i (%s) - restarting\n"), sig, sys_siglist[sig]);
#else
wwarning(_("got signal %i - restarting\n"), sig);
#endif
WRestartASAP = 1;
/* setup idle handler, so that this will be handled when
* the select() is returned becaused of the signal, even if
* there are no X events in the queue */
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
return;
} else if (sig==SIGTERM) {
printf(_("%s: Received signal SIGTERM. Exiting..."), ProgName);
WExitASAP = 1;
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
return;
}
#ifdef SYS_SIGLIST_DECLARED
wfatal(_("got signal %i (%s)\n"), sig, sys_siglist[sig]);
#else
wfatal(_("got signal %i\n"), sig);
#endif
if (sig==SIGSEGV || sig==SIGFPE || sig==SIGBUS || sig==SIGILL) {
if (already_crashed) {
wfatal(_("crashed while trying to do some post-crash cleanup. Aborting immediatelly."));
abort();
}
already_crashed = 1;
#ifndef NO_EMERGENCY_AUTORESTART
/* restart another window manager so that the X session doesn't
* go to space */
wwarning(_("trying to start alternative window manager..."));
if (dpy)
XCloseDisplay(dpy);
dpy = NULL;
argv[0] = FALLBACK_WINDOWMANAGER;
execvp(FALLBACK_WINDOWMANAGER, argv);
argv[0] = "fvwm";
execvp("fvwm", argv);
argv[0] = "twm";
execvp("twm", argv);
#endif /* !NO_EMERGENCY_AUTORESTART */
}
wAbort(sig==SIGSEGV);
}
static RETSIGTYPE
ignoreSig(int signal)
{
return;
}
static RETSIGTYPE
buryChild(int foo)
{
pid_t pid;
int status;
/* R.I.P. */
pid = waitpid(-1, &status, WNOHANG);
if (pid>0) {
NotifyDeadProcess(pid, WEXITSTATUS(status));
/*
* Make sure that the kid will be buried even if there are
* no events in the X event queue
*/
if (!WDelayedActionSet) {
WDelayedActionSet = 1;
WMAddIdleHandler(delayedAction, NULL);
}
}
}
static int
getWorkspaceState(Window root, WWorkspaceState **state)
{
Atom type_ret;
int fmt_ret;
unsigned long nitems_ret;
unsigned long bytes_after_ret;
if (XGetWindowProperty(dpy, root, _XA_WINDOWMAKER_STATE, 0,
sizeof(WWorkspaceState),
True, _XA_WINDOWMAKER_STATE,
&type_ret, &fmt_ret, &nitems_ret, &bytes_after_ret,
(unsigned char **)state)!=Success)
return 0;
if (type_ret==_XA_WINDOWMAKER_STATE)
return 1;
else
return 0;
}
static void
getOffendingModifiers()
{
int i;
XModifierKeymap *modmap;
KeyCode nlock, slock;
static mask_table[8] = {
ShiftMask,LockMask,ControlMask,Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
nlock = XKeysymToKeycode(dpy, XK_Num_Lock);
slock = XKeysymToKeycode(dpy, XK_Scroll_Lock);
/*
* Find out the masks for the NumLock and ScrollLock modifiers,
* so that we can bind the grabs for when they are enabled too.
*/
modmap = XGetModifierMapping(dpy);
if (modmap!=NULL && modmap->max_keypermod>0) {
for (i=0; i<8*modmap->max_keypermod; i++) {
if (modmap->modifiermap[i]==nlock && nlock!=0)
_NumLockMask = mask_table[i/modmap->max_keypermod];
else if (modmap->modifiermap[i]==slock && slock!=0)
_ScrollLockMask = mask_table[i/modmap->max_keypermod];
}
}
if (modmap)
XFreeModifiermap(modmap);
}
#ifdef NUMLOCK_HACK
void
wHackedGrabKey(int keycode, unsigned int modifiers,
Window grab_window, Bool owner_events, int pointer_mode,
int keyboard_mode)
{
if (modifiers == AnyModifier)
return;
/* grab all combinations of the modifier with CapsLock, NumLock and
* ScrollLock. How much memory/CPU does such a monstrosity consume
* in the server?
*/
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers|_NumLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers|_ScrollLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers|_NumLockMask|_ScrollLockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask)
XGrabKey(dpy, keycode, modifiers|_NumLockMask|LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_ScrollLockMask)
XGrabKey(dpy, keycode, modifiers|_ScrollLockMask|LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
if (_NumLockMask && _ScrollLockMask)
XGrabKey(dpy, keycode, modifiers|_NumLockMask|_ScrollLockMask|LockMask,
grab_window, owner_events, pointer_mode, keyboard_mode);
/* phew, I guess that's all, right? */
}
void
wHackedGrabButton(unsigned int button, unsigned int modifiers,
Window grab_window, Bool owner_events,
unsigned int event_mask, int pointer_mode,
int keyboard_mode, Window confine_to, Cursor cursor)
{
if (modifiers==AnyModifier)
return;
/* same as above, but for mouse buttons */
if (_NumLockMask)
XGrabButton(dpy, button, modifiers|_NumLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers|_ScrollLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers|_ScrollLockMask|_NumLockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask)
XGrabButton(dpy, button, modifiers|_NumLockMask|LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_ScrollLockMask)
XGrabButton(dpy, button, modifiers|_ScrollLockMask|LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
if (_NumLockMask && _ScrollLockMask)
XGrabButton(dpy, button, modifiers|_ScrollLockMask|_NumLockMask|LockMask,
grab_window, owner_events, event_mask, pointer_mode,
keyboard_mode, confine_to, cursor);
}
void
wHackedUngrabButton(unsigned int button, unsigned int modifiers,
Window grab_window)
{
XUngrabButton(dpy, button, modifiers|_NumLockMask,
grab_window);
XUngrabButton(dpy, button, modifiers|_ScrollLockMask,
grab_window);
XUngrabButton(dpy, button, modifiers|_NumLockMask|_ScrollLockMask,
grab_window);
XUngrabButton(dpy, button, modifiers|_NumLockMask|LockMask,
grab_window);
XUngrabButton(dpy, button, modifiers|_ScrollLockMask|LockMask,
grab_window);
XUngrabButton(dpy, button, modifiers|_NumLockMask|_ScrollLockMask|LockMask,
grab_window);
}
#endif /* NUMLOCK_HACK */
WScreen*
wScreenWithNumber(int i)
{
assert(i < wScreenCount);
return wScreen[i];
}
WScreen*
wScreenForRootWindow(Window window)
{
int i;
if (wScreenCount==1)
return wScreen[0];
/*
* Since the number of heads will probably be small (normally 2),
* it should be faster to use this than a hash table, because
* of the overhead.
*/
for (i=0; i<wScreenCount; i++) {
if (wScreen[i]->root_win == window) {
return wScreen[i];
}
}
assert("bad_root_window" && 0);
return NULL;
}
WScreen*
wScreenForWindow(Window window)
{
XWindowAttributes attr;
if (XGetWindowAttributes(dpy, window, &attr)) {
return wScreenForRootWindow(attr.root);
}
return NULL;
}
/*
*----------------------------------------------------------
* StartUp--
* starts the window manager and setup global data.
* Called from main() at startup.
*
* Side effects:
* global data declared in main.c is initialized
*----------------------------------------------------------
*/
void
StartUp(Bool defaultScreenOnly)
{
WWorkspaceState *ws_state;
struct sigaction sig_action;
int j, max;
/*
* Ignore CapsLock in modifiers
*/
ValidModMask = 0xff & ~LockMask;
getOffendingModifiers();
/*
* Ignore NumLock and ScrollLock too
*/
ValidModMask &= ~(_NumLockMask|_ScrollLockMask);
memset(&wKeyBindings, 0, sizeof(wKeyBindings));
wWinContext = XUniqueContext();
wAppWinContext = XUniqueContext();
wStackContext = XUniqueContext();
_XA_WM_STATE = XInternAtom(dpy, "WM_STATE", False);
_XA_WM_CHANGE_STATE = XInternAtom(dpy, "WM_CHANGE_STATE", False);
_XA_WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
_XA_WM_TAKE_FOCUS = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
_XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
_XA_WM_SAVE_YOURSELF = XInternAtom(dpy, "WM_SAVE_YOURSELF", False);
_XA_WM_CLIENT_LEADER = XInternAtom(dpy, "WM_CLIENT_LEADER", False);
_XA_WM_COLORMAP_WINDOWS = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
_XA_GNUSTEP_WM_ATTR = XInternAtom(dpy, GNUSTEP_WM_ATTR_NAME, False);
#ifdef MWM_HINTS
_XA_MOTIF_WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
#endif
_XA_WINDOWMAKER_MENU = XInternAtom(dpy, "_WINDOWMAKER_MENU", False);
_XA_WINDOWMAKER_STATE = XInternAtom(dpy, "_WINDOWMAKER_STATE", False);
_XA_WINDOWMAKER_WM_PROTOCOLS =
XInternAtom(dpy, "_WINDOWMAKER_WM_PROTOCOLS", False);
_XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW =
XInternAtom(dpy, WINDOWMAKER_WM_MINIATURIZE_WINDOW, False);
_XA_GNUSTEP_WM_RESIZEBAR =
XInternAtom(dpy, GNUSTEP_WM_RESIZEBAR, False);
_XA_WINDOWMAKER_WM_FUNCTION = XInternAtom(dpy, "_WINDOWMAKER_WM_FUNCTION",
False);
#ifdef OFFIX_DND
_XA_DND_SELECTION = XInternAtom(dpy, "DndSelection", False);
_XA_DND_PROTOCOL = XInternAtom(dpy, "DndProtocol", False);
#endif
/* cursors */
wCursor[WCUR_NORMAL] = XCreateFontCursor(dpy, XC_left_ptr);
wCursor[WCUR_ARROW] = XCreateFontCursor(dpy, XC_top_left_arrow);
wCursor[WCUR_MOVE] = XCreateFontCursor(dpy, XC_fleur);
wCursor[WCUR_RESIZE] = XCreateFontCursor(dpy, XC_sizing);
wCursor[WCUR_WAIT] = XCreateFontCursor(dpy, XC_watch);
wCursor[WCUR_QUESTION] = XCreateFontCursor(dpy, XC_question_arrow);
wCursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name???*/
/* emergency exit... */
sig_action.sa_handler = handleSig;
sigemptyset(&sig_action.sa_mask);
/* Here we don't care about SA_RESTART since these signals will close
* wmaker anyway.
* -Dan */
sig_action.sa_flags = 0;
sigaction(SIGINT, &sig_action, NULL);
sigaction(SIGTERM, &sig_action, NULL);
sigaction(SIGQUIT, &sig_action, NULL);
sigaction(SIGSEGV, &sig_action, NULL);
sigaction(SIGBUS, &sig_action, NULL);
sigaction(SIGFPE, &sig_action, NULL);
/* Here we set SA_RESTART for safety, because SIGHUP may not be handled
* immediately.
* -Dan */
sig_action.sa_flags = SA_RESTART;
sigaction(SIGHUP, &sig_action, NULL);
/* ignore dead pipe */
sig_action.sa_handler = ignoreSig;
sig_action.sa_flags = SA_RESTART;
sigaction(SIGPIPE, &sig_action, NULL);
/* handle dead children */
sig_action.sa_handler = buryChild;
sig_action.sa_flags = SA_NOCLDSTOP|SA_RESTART;
sigaction(SIGCHLD, &sig_action, NULL);
/* handle X shutdowns a such */
XSetIOErrorHandler(handleXIO);
/* set hook for out event dispatcher in WINGs event dispatcher */
WMHookEventHandler(DispatchEvent);
/* initialize defaults stuff */
WDWindowMaker = wDefaultsInitDomain("WindowMaker", True);
if (!WDWindowMaker->dictionary) {
wwarning(_("could not read domain \"%s\" from defaults database"),
"WindowMaker");
}
/* read defaults that don't change until a restart and are
* screen independent */
wReadStaticDefaults(WDWindowMaker ? WDWindowMaker->dictionary : NULL);
/* check sanity of some values */
if (wPreferences.icon_size < 16) {
wwarning(_("icon size is configured to %i, but it's too small. Using 16, instead\n"),
wPreferences.icon_size);
wPreferences.icon_size = 16;
}
/* init other domains */
WDRootMenu = wDefaultsInitDomain("WMRootMenu", False);
if (!WDRootMenu->dictionary) {
wwarning(_("could not read domain \"%s\" from defaults database"),
"WMRootMenu");
}
WDWindowAttributes = wDefaultsInitDomain("WMWindowAttributes", True);
if (!WDWindowAttributes->dictionary) {
wwarning(_("could not read domain \"%s\" from defaults database"),
"WMWindowAttributes");
}
/* Sound init */
#ifdef WMSOUND
wSoundInit(dpy);
#endif
XSetErrorHandler((XErrorHandler)catchXError);
if (defaultScreenOnly) {
max = 1;
} else {
max = ScreenCount(dpy);
}
wScreen = wmalloc(sizeof(WScreen*)*max);
for (j = 0; j < max; j++) {
if (defaultScreenOnly || max==1) {
wScreen[j] = wScreenInit(DefaultScreen(dpy));
if (!wScreen[j]) {
wfatal(_("it seems that there already is a window manager running"));
exit(1);
}
} else {
wScreen[j] = wScreenInit(j);
if (!wScreen[j]) {
wwarning(_("could not manage screen %i"), j);
continue;
}
}
wScreenCount++;
/* restore workspace state */
if (!getWorkspaceState(wScreen[j]->root_win, &ws_state)) {
ws_state = NULL;
}
wScreenRestoreState(wScreen[j]);
/* manage all windows that were already
* here before us */
if (!wPreferences.flags.nodock && wScreen[j]->dock)
wScreen[j]->last_dock = wScreen[j]->dock;
manageAllWindows(wScreen[j]);
/* restore saved menus */
wMenuRestoreState(wScreen[j]);
/* If we're not restarting restore session */
if (ws_state == NULL)
wSessionRestoreState(wScreen[j]);
/* auto-launch apps */
if (!wPreferences.flags.nodock && wScreen[j]->dock) {
wScreen[j]->last_dock = wScreen[j]->dock;
wDockDoAutoLaunch(wScreen[j]->dock, 0);
}
/* auto-launch apps in clip */
if (!wPreferences.flags.noclip) {
int i;
for(i=0; i<wScreen[j]->workspace_count; i++) {
if (wScreen[j]->workspaces[i]->clip) {
wScreen[j]->last_dock = wScreen[j]->workspaces[i]->clip;
wDockDoAutoLaunch(wScreen[j]->workspaces[i]->clip, i);
}
}
}
/* go to workspace where we were before restart */
if (ws_state) {
wWorkspaceForceChange(wScreen[j], ws_state->workspace);
XFree(ws_state);
} else {
wSessionRestoreLastWorkspace(wScreen[j]);
}
}
if (wScreenCount == 0) {
wfatal(_("could not manage any screen"));
exit(1);
}
/* setup defaults file polling */
WMAddTimerHandler(3000, wDefaultsCheckDomains, NULL);
}
static int
getState(Window window)
{
Atom type;
int form;
unsigned long nitems, bytes_rem;
unsigned char *data;
long ret;
if (XGetWindowProperty(dpy, window, _XA_WM_STATE, 0, 3, False,
_XA_WM_STATE, &type,&form,&nitems,&bytes_rem,
&data)==Success) {
if (data != NULL) {
ret = *(long*)data;
free(data);
return ret;
}
}
return -1;
}
/*
*-----------------------------------------------------------------------
* manageAllWindows--
* Manages all windows in the screen.
*
* Notes:
* Called when the wm is being started.
* No events can be processed while the windows are being
* reparented/managed.
*-----------------------------------------------------------------------
*/
static void
manageAllWindows(WScreen *scr)
{
Window root, parent;
Window *children;
unsigned int nchildren;
XWindowAttributes wattribs;
unsigned int i, j;
int state;
WWindow *wwin;
XWMHints *wmhints;
XGrabServer(dpy);
XQueryTree(dpy, scr->root_win, &root, &parent, &children, &nchildren);
scr->flags.startup = 1;
/* first remove all icon windows */
for (i=0; i<nchildren; i++) {
if (children[i]==None)
continue;
wmhints = XGetWMHints(dpy, children[i]);
if (wmhints && (wmhints->flags & IconWindowHint)) {
for (j = 0; j < nchildren; j++) {
if (children[j] == wmhints->icon_window) {
XFree(wmhints);
wmhints = NULL;
children[j] = None;
break;
}
}
}
if (wmhints) {
XFree(wmhints);
}
}
/* map all windows without OverrideRedirect */
for (i=0; i<nchildren; i++) {
if (children[i]==None)
continue;
XGetWindowAttributes(dpy, children[i], &wattribs);
state = getState(children[i]);
if (!wattribs.override_redirect
&& (state>=0 || wattribs.map_state!=IsUnmapped)) {
XUnmapWindow(dpy, children[i]);
if (state==WithdrawnState) {
/* move the window far away so that it doesn't flash */
XMoveWindow(dpy, children[i], scr->scr_width+10,
scr->scr_height+10);
}
wwin = wManageWindow(scr, children[i]);
if (wwin) {
if (state==WithdrawnState) {
wwin->flags.mapped = 0;
wClientSetState(wwin, WithdrawnState, None);
XSelectInput(dpy, wwin->client_win, NoEventMask);
XRemoveFromSaveSet(dpy, wwin->client_win);
wUnmanageWindow(wwin, True);
} else {
/* apply states got from WSavedState */
/* shaded + minimized is not restored correctly */
if (wwin->flags.shaded) {
wwin->flags.shaded = 0;
wShadeWindow(wwin);
}
if (wwin->flags.hidden) {
WApplication *wapp = wApplicationOf(wwin->main_window);
wwin->flags.hidden = 0;
if (wapp) {
wHideApplication(wapp);
}
wwin->flags.ignore_next_unmap=1;
} else {
if (wwin->wm_hints &&
(wwin->wm_hints->flags & StateHint) && state<0)
state=wwin->wm_hints->initial_state;
if (state==IconicState) {
wIconifyWindow(wwin);
wwin->flags.ignore_next_unmap=1;
} else {
wClientSetState(wwin, NormalState, None);
}
}
}
}
if (state==WithdrawnState) {
/* move the window back to it's old position */
XMoveWindow(dpy, children[i], wattribs.x, wattribs.y);
}
}
}
XUngrabServer(dpy);
XFree(children);
scr->flags.startup = 0;
scr->flags.startup2 = 1;
while (XPending(dpy)) {
XEvent ev;
WMNextEvent(dpy, &ev);
WMHandleEvent(&ev);
}
wWorkspaceForceChange(scr, 0);
if (!wPreferences.flags.noclip)
wDockShowIcons(scr->workspaces[scr->current_workspace]->clip);
scr->flags.startup2 = 0;
}

310
src/superfluous.c Normal file
View File

@@ -0,0 +1,310 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <unistd.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "screen.h"
#include "superfluous.h"
#include "dock.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
extern WPreferences wPreferences;
#ifdef SPEAKER_SOUND
static void
play(Display *dpy, int pitch, int delay)
{
XKeyboardControl kc;
kc.bell_pitch = pitch;
kc.bell_percent = 50;
kc.bell_duration = delay;
XChangeKeyboardControl(dpy, KBBellPitch|KBBellDuration|KBBellPercent,&kc);
XBell(dpy, 50);
XFlush(dpy);
wusleep(delay);
}
#endif
void
DoKaboom(WScreen *scr, Window win, int x, int y)
{
int i, j, k;
int sw=scr->scr_width, sh=scr->scr_height;
short px[PIECES], py[PIECES];
char pvx[PIECES], pvy[PIECES];
char ax[PIECES], ay[PIECES];
Pixmap tmp;
XImage *img;
img=XGetImage(dpy, win, 0, 0, wPreferences.icon_size,
wPreferences.icon_size, AllPlanes, ZPixmap);
XUnmapWindow(dpy,win);
if (!img)
return;
XSetClipMask(dpy, scr->copy_gc, None);
tmp = XCreatePixmap(dpy, scr->root_win, wPreferences.icon_size,
wPreferences.icon_size, scr->depth);
XPutImage(dpy, tmp, scr->copy_gc, img, 0, 0, 0, 0, wPreferences.icon_size,
wPreferences.icon_size);
XDestroyImage(img);
for (i=0,k=0; i<wPreferences.icon_size/PSIZE; i++) {
for (j=0; j<wPreferences.icon_size/PSIZE; j++) {
if (rand()%3) {
ax[k]=i;
ay[k]=j;
px[k]=x+i*PSIZE;
py[k]=y+j*PSIZE;
pvx[k]=rand()%7-3;
#ifdef SPREAD_ICON
pvy[k]=rand()%7-3;
#else
pvy[k]=-12-rand()%6;
#endif
k++;
} else {
ax[k]=-1;
}
}
}
j=k;
while (k>0) {
for (i=0; i<j; i++) {
if (ax[i]>=0) {
px[i]+=pvx[i];
py[i]+=pvy[i];
#ifdef SPREAD_ICON
pvx[i]+=(pvx[i]>0 ? 2 : -2);
pvy[i]+=(pvy[i]>0 ? 2 : -2);
/* The following are nice, but too slow.
* The animation can have an unknown duration, depending
* on what rand() returns. Until the animation ends, the user
* cannot do anything, which is not too good. -Dan
*/
/*pvx[i]+=rand()%5-2;
pvy[i]+=rand()%5-2;*/
#else
pvy[i]++;
#endif
if (px[i]<-wPreferences.icon_size || px[i]>sw || py[i]>sh
#ifdef SPREAD_ICON
|| px[i]<0 || py[i]<0
#endif
) {
ax[i]=-1;
k--;
} else {
XCopyArea(dpy, tmp, scr->root_win, scr->copy_gc,
ax[i]*PSIZE, ay[i]*PSIZE,
PSIZE, PSIZE, px[i], py[i]);
}
}
}
#ifdef SPEAKER_SOUND
play(dpy, 100+rand()%250, 12);
#else
# if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
wusleep(MINIATURIZE_ANIMATION_DELAY_Z*2);
# endif
#endif
for (i=0; i<j; i++) {
if (ax[i]>=0) {
XClearArea(dpy, scr->root_win, px[i], py[i], PSIZE, PSIZE, 1);
}
}
}
XFreePixmap(dpy, tmp);
}
Pixmap
MakeGhostDock(WDock *dock, int sx, int dx, int y)
{
WScreen *scr = dock->screen_ptr;
XImage *img;
RImage *back, *dock_image;
Pixmap pixmap;
int i, virtual_tiles, h, j, n;
unsigned long red_mask, green_mask, blue_mask;
virtual_tiles = 0;
for (i=0; i<dock->max_icons; i++) {
if (dock->icon_array[i]!=NULL &&
dock->icon_array[i]->yindex > virtual_tiles)
virtual_tiles = dock->icon_array[i]->yindex;
}
virtual_tiles++;
h = virtual_tiles * wPreferences.icon_size;
h = (y + h > scr->scr_height) ? scr->scr_height-y : h;
virtual_tiles = h / wPreferences.icon_size; /* The visible ones */
if (h % wPreferences.icon_size)
virtual_tiles++; /* There is one partially visible tile at end */
img=XGetImage(dpy, scr->root_win, dx, y, wPreferences.icon_size, h,
AllPlanes, ZPixmap);
if (!img)
return None;
red_mask = img->red_mask;
green_mask = img->green_mask;
blue_mask = img->blue_mask;
back = RCreateImageFromXImage(scr->rcontext, img, NULL);
XDestroyImage(img);
if (!back) {
return None;
}
for (i=0;i<dock->max_icons;i++) {
if (dock->icon_array[i]!=NULL &&
dock->icon_array[i]->yindex < virtual_tiles) {
Pixmap which;
j = dock->icon_array[i]->yindex * wPreferences.icon_size;
n = (h - j < wPreferences.icon_size) ? h - j :
wPreferences.icon_size;
if (dock->icon_array[i]->icon->pixmap)
which = dock->icon_array[i]->icon->pixmap;
else
which = dock->icon_array[i]->icon->core->window;
img=XGetImage(dpy, which, 0, 0, wPreferences.icon_size, n,
AllPlanes, ZPixmap);
if (!img){
RDestroyImage(back);
return None;
}
img->red_mask = red_mask;
img->green_mask = green_mask;
img->blue_mask = blue_mask;
dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL);
XDestroyImage(img);
if (!dock_image) {
RDestroyImage(back);
return None;
}
RCombineAreaWithOpaqueness(back, dock_image, 0, 0,
wPreferences.icon_size, n,
0, j, 30 * 256 / 100);
RDestroyImage(dock_image);
}
}
RConvertImage(scr->rcontext, back, &pixmap);
RDestroyImage(back);
return pixmap;
}
Pixmap
MakeGhostIcon(WScreen *scr, Drawable drawable)
{
RImage *back;
RColor color;
Pixmap pixmap;
if (!drawable)
return None;
back = RCreateImageFromDrawable(scr->rcontext, drawable, None);
if (!back)
return None;
color.red = 0xff;
color.green = 0xff;
color.blue = 0xff;
color.alpha = 200;
RClearImage(back, &color);
RConvertImage(scr->rcontext, back, &pixmap);
RDestroyImage(back);
return pixmap;
}
#ifdef WINDOW_BIRTH_ZOOM
void
DoWindowBirth(WWindow *wwin)
{
int width = wwin->frame->core->width;
int height = wwin->frame->core->height;
int w = WMIN(width, 20);
int h = WMIN(height, 20);
int x, y;
int dw, dh;
int i;
dw = (width-w)/WINDOW_BIRTH_STEPS;
dh = (height-h)/WINDOW_BIRTH_STEPS;
x = wwin->frame_x + (width-w)/2;
y = wwin->frame_y + (height-h)/2;
XMoveResizeWindow(dpy, wwin->frame->core->window, x, y, w, h);
XMapWindow(dpy, wwin->frame->core->window);
XFlush(dpy);
for (i=0; i<WINDOW_BIRTH_STEPS; i++) {
x -= dw/2 + dw%2;
y -= dh/2 + dh%2;
w += dw;
h += dh;
XMoveResizeWindow(dpy, wwin->frame->core->window, x, y, w, h);
XFlush(dpy);
}
XMoveResizeWindow(dpy, wwin->frame->core->window,
wwin->frame_x, wwin->frame_y, width, height);
XFlush(dpy);
}
#else
void
DoWindowBirth(WWindow *wwin)
{
/* dummy stub */
}
#endif

30
src/superfluous.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#define PSIZE 4
#define PIECES ((64/PSIZE)*(64/PSIZE))
extern void DoKaboom();
extern Pixmap MakeGhostDock();
extern Pixmap MakeGhostIcon();

306
src/switchmenu.c Normal file
View File

@@ -0,0 +1,306 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997 Shige Abe and
* Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "WindowMaker.h"
#include "window.h"
#include "actions.h"
#include "client.h"
#include "funcs.h"
#include "stacking.h"
#include "workspace.h"
#include "framewin.h"
/********* Global Variables *******/
extern WPreferences wPreferences;
extern Time LastTimestamp;
/*
* FocusWindow
*
* - Needs to check if already in the right workspace before
* calling wChangeWorkspace?
*
* Order:
* Switch to correct workspace
* Unshade if shaded
* If iconified then deiconify else focus/raise.
*/
static void
focusWindow(WMenu *menu, WMenuEntry *entry)
{
WWindow *wwin;
WScreen *scr;
int x, y, move=0;
wwin = (WWindow*)entry->clientdata;
scr = wwin->screen_ptr;
wWorkspaceChange(menu->frame->screen_ptr, wwin->frame->workspace);
if (wwin->flags.shaded) {
wUnshadeWindow(wwin);
}
if (wwin->flags.hidden) {
wUnhideApplication(wApplicationOf(wwin->main_window), False, False);
} else if (wwin->flags.miniaturized) {
wDeiconifyWindow(wwin);
} else {
wSetFocusTo(menu->frame->screen_ptr, wwin);
wRaiseFrame(wwin->frame->core);
}
x = wwin->frame_x;
y = wwin->frame_y;
/* bring window back to visible area */
move = wScreenBringInside(scr, &x, &y, wwin->frame->core->width,
wwin->frame->core->height);
if (move) {
wWindowConfigure(wwin, x, y, wwin->client.width, wwin->client.height);
}
}
/*
*
* Open switch menu
*
*/
void
OpenSwitchMenu(WScreen *scr, int x, int y, int keyboard)
{
WMenu *switchmenu = scr->switch_menu;
WWindow *wwin;
if (switchmenu) {
if (switchmenu->flags.mapped) {
if (!switchmenu->flags.buttoned) {
wMenuUnmap(switchmenu);
} else {
wRaiseFrame(switchmenu->frame->core);
if (keyboard)
wMenuMapAt(switchmenu, 0, 0, True);
else
wMenuMapCopyAt(switchmenu, x-switchmenu->frame->core->width/2,
y-switchmenu->frame->top_width/2);
}
} else {
wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
y-switchmenu->frame->top_width/2, keyboard);
}
return;
}
switchmenu = wMenuCreate(scr,_("Windows"),True);
scr->switch_menu = switchmenu;
wwin = scr->focused_window;
while (wwin) {
UpdateSwitchMenu(scr, wwin, ACTION_ADD);
wwin = wwin->prev;
}
if (switchmenu) {
if (!switchmenu->flags.realized)
wMenuRealize(switchmenu);
wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2,
y-switchmenu->frame->top_width/2, keyboard);
}
}
/*
*
* Update switch menu
*
*
*/
void
UpdateSwitchMenu(WScreen *scr, WWindow *wwin, int action)
{
WMenu *switchmenu = scr->switch_menu;
WMenuEntry *entry;
char title[MAX_MENU_TEXT_LENGTH+6];
int i;
int checkVisibility = 0;
if (!wwin->screen_ptr->switch_menu)
return;
/*
* This menu is updated under the following conditions:
*
* 1. When a window is created.
* 2. When a window is destroyed.
*
* 3. When a window changes it's title.
*/
if (action == ACTION_ADD) {
char *t;
if (wwin->flags.internal_window
|| wwin->window_flags.skip_window_list)
return;
if (wwin->frame->title)
sprintf(title, "%s", wwin->frame->title);
else
sprintf(title, "%s", DEF_WINDOW_TITLE);
t = ShrinkString(scr->menu_entry_font, title, MAX_WINDOWLIST_WIDTH);
entry = wMenuAddCallback(switchmenu, t, focusWindow, wwin);
free(t);
entry->flags.indicator = 1;
entry->rtext = wmalloc(MAX_WORKSPACENAME_WIDTH+8);
if (wwin->window_flags.omnipresent)
sprintf(entry->rtext, "[*]");
else
sprintf(entry->rtext, "[%s]",
scr->workspaces[wwin->frame->workspace]->name);
if (wwin->flags.hidden) {
entry->flags.indicator_type = MI_HIDDEN;
entry->flags.indicator_on = 1;
} else if (wwin->flags.miniaturized) {
entry->flags.indicator_type = MI_MINIWINDOW;
entry->flags.indicator_on = 1;
} else if (wwin->flags.focused) {
entry->flags.indicator_type = MI_DIAMOND;
entry->flags.indicator_on = 1;
} else if (wwin->flags.shaded) {
entry->flags.indicator_type = MI_SHADED;
entry->flags.indicator_on = 1;
}
wMenuRealize(switchmenu);
checkVisibility = 1;
} else {
char *t;
for (i=0; i<switchmenu->entry_no; i++) {
entry = switchmenu->entries[i];
/* this is the entry that was changed */
if (entry->clientdata == wwin) {
switch (action) {
case ACTION_REMOVE:
wMenuRemoveItem(switchmenu, i);
wMenuRealize(switchmenu);
checkVisibility = 1;
break;
case ACTION_CHANGE:
if (entry->text)
free(entry->text);
if (wwin->frame->title)
sprintf(title, "%s", wwin->frame->title);
else
sprintf(title, "%s", DEF_WINDOW_TITLE);
t = ShrinkString(scr->menu_entry_font, title,
MAX_WINDOWLIST_WIDTH);
entry->text = t;
/* fall through to update workspace number */
case ACTION_CHANGE_WORKSPACE:
if (entry->rtext) {
if (wwin->window_flags.omnipresent)
sprintf(entry->rtext, "[*]");
else
sprintf(entry->rtext, "[%s]",
scr->workspaces[wwin->frame->workspace]->name);
}
wMenuRealize(switchmenu);
checkVisibility = 1;
break;
case ACTION_CHANGE_STATE:
if (wwin->flags.hidden) {
entry->flags.indicator_type = MI_HIDDEN;
entry->flags.indicator_on = 1;
} else if (wwin->flags.miniaturized) {
entry->flags.indicator_type = MI_MINIWINDOW;
entry->flags.indicator_on = 1;
} else if (wwin->flags.shaded && !wwin->flags.focused) {
entry->flags.indicator_type = MI_SHADED;
entry->flags.indicator_on = 1;
} else {
entry->flags.indicator_on = wwin->flags.focused;
entry->flags.indicator_type = MI_DIAMOND;
}
wMenuPaint(switchmenu);
break;
}
break;
}
}
}
if (checkVisibility) {
int tmp;
tmp = switchmenu->frame->top_width + 5;
/* if menu got unreachable, bring it to a visible place */
if (switchmenu->frame_x < tmp - (int)switchmenu->frame->core->width) {
wMenuMove(switchmenu, tmp - (int)switchmenu->frame->core->width,
switchmenu->frame_y, False);
}
}
wMenuPaint(switchmenu);
}
void
UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
{
WMenu *menu = scr->switch_menu;
int i;
WWindow *wwin;
if (!menu)
return;
for (i=0; i<menu->entry_no; i++) {
wwin = (WWindow*)menu->entries[i]->clientdata;
if (wwin->frame->workspace==workspace
&& !wwin->window_flags.omnipresent) {
if (wwin->window_flags.omnipresent)
sprintf(menu->entries[i]->rtext, "[*]");
else
sprintf(menu->entries[i]->rtext, "[%s]",
scr->workspaces[wwin->frame->workspace]->name);
menu->flags.realized = 0;
}
}
if (!menu->flags.realized)
wMenuRealize(menu);
}

674
src/text.c Normal file
View File

@@ -0,0 +1,674 @@
/********************************************************************\
* text.c -- a basic text field *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <ctype.h>
#include "WindowMaker.h"
#include "funcs.h"
#include "text.h"
#include "actions.h"
/* X11R5 don't have this */
#ifndef IsPrivateKeypadKey
#define IsPrivateKeypadKey(keysym) \
(((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
#endif
#define TEXT_SHIFT -4 /* Move the text up relative to the bottom of
* the text-box */
#if 0
# define ENTER(X) fprintf(stderr,"Entering: %s()\n", X);
# define LEAVE(X) fprintf(stderr,"Leaving: %s()\n", X);
# define DEBUG(X) fprintf(stderr,"debug: %s()\n", X);
#else
# define ENTER(X)
# define LEAVE(X)
# define DEBUG(X)
#endif
extern Cursor wCursor[WCUR_LAST];
/********************************************************************\
* The event handler for the text-field: *
\********************************************************************/
static void textEventHandler( WObjDescriptor *desc, XEvent *event );
static void handleExpose( WObjDescriptor *desc, XEvent *event );
static void textInsert( WTextInput *wtext, char *txt );
#if 0
static void blink(void *data);
#endif
/********************************************************************\
* handleKeyPress *
* handle cursor keys, regular keys, etc. Inserts characters in *
* text field, at cursor position, if it is a "Normal" key. If *
* ksym is the delete key, backspace key, etc., the appropriate *
* action is performed on the text in the text field. Does not *
* refresh the text field *
* *
* Args: wText - the text field *
* ksym - the key that was pressed *
* Return: True, unless the ksym is ignored *
* Global: modifier - the bitfield that keeps track of the modifier *
* keys that are down *
\********************************************************************/
static int
handleKeyPress( WTextInput *wtext, XKeyEvent *event )
{
KeySym ksym;
char buffer[32];
int count;
count = XLookupString(event, buffer, 32, &ksym, NULL);
/* Ignore these keys: */
if( IsFunctionKey(ksym) || IsKeypadKey(ksym) ||
IsMiscFunctionKey(ksym) || IsPFKey(ksym) ||
IsPrivateKeypadKey(ksym) )
/* If we don't handle it, make sure it isn't a key that
* the window manager needs to see */
return False;
/* Take care of the cursor keys.. ignore up and down
* cursor keys */
else if( IsCursorKey(ksym) )
{
int length = wtext->text.length;
switch(ksym)
{
case XK_Home:
case XK_Begin:
wtext->text.endPos = 0;
break;
case XK_Left:
wtext->text.endPos--;
break;
case XK_Right:
wtext->text.endPos++;
break;
case XK_End:
wtext->text.endPos = length;
break;
default:
return False;
}
/* make sure that the startPos and endPos have values
* that make sense (ie the are in [0..length] ) */
if( wtext->text.endPos < 0 )
wtext->text.endPos = 0;
if( wtext->text.endPos > length )
wtext->text.endPos = length;
wtext->text.startPos = wtext->text.endPos;
}
else
{
switch(ksym)
{
/* Ignore these keys: */
case XK_Escape:
wtext->canceled = True;
case XK_Return:
wtext->done = True;
break;
case XK_Tab:
case XK_Num_Lock:
break;
case XK_Delete:
/* delete after cursor */
if( (wtext->text.endPos == wtext->text.startPos) &&
(wtext->text.endPos < wtext->text.length) )
wtext->text.endPos++;
textInsert( wtext, "" );
break;
case XK_BackSpace:
/* delete before cursor */
if( (wtext->text.endPos == wtext->text.startPos) &&
(wtext->text.startPos > 0) )
wtext->text.startPos--;
textInsert( wtext, "" );
break;
default:
if (count==1 && !iscntrl(buffer[0])) {
buffer[count] = 0;
textInsert( wtext, buffer);
}
}
}
return True;
}
/********************************************************************\
* textXYtoPos *
* given X coord, return position in array *
\********************************************************************/
static int
textXtoPos( WTextInput *wtext, int x )
{
int pos;
x -= wtext->xOffset;
for( pos=0; wtext->text.txt[pos] != '\0'; pos++ )
{
if( x < 0 )
break;
else
x -= wTextWidth( wtext->font->font, &(wtext->text.txt[pos]), 1 );
}
return pos;
}
/********************************************************************\
* wTextCreate *
* create an instance of a text class *
* *
* Args: *
* Return: *
* Global: dpy - the display *
\********************************************************************/
WTextInput *
wTextCreate( WCoreWindow *core, int x, int y, int width, int height )
{
WTextInput *wtext;
ENTER("wTextCreate");
wtext = wmalloc(sizeof(WTextInput));
wtext->core = wCoreCreate( core, x, y, width, height );
wtext->core->descriptor.handle_anything = &textEventHandler;
wtext->core->descriptor.handle_expose = &handleExpose;
wtext->core->descriptor.parent_type = WCLASS_TEXT_INPUT;
wtext->core->descriptor.parent = wtext;
wtext->font = core->screen_ptr->menu_entry_font;
XDefineCursor( dpy, wtext->core->window, wCursor[WCUR_TEXT] );
/* setup the text: */
wtext->text.txt = (char *)wmalloc(sizeof(char));
wtext->text.txt[0] = '\0';
wtext->text.length = 0;
wtext->text.startPos = 0;
wtext->text.endPos = 0;
{
XGCValues gcv;
gcv.foreground = core->screen_ptr->black_pixel;
gcv.background = core->screen_ptr->white_pixel;
#ifndef I18N_MB
gcv.font = wtext->font->font->fid;
#endif
gcv.line_width = 1;
gcv.function = GXcopy;
wtext->gc = XCreateGC( dpy, wtext->core->window,
(GCForeground|GCBackground|
#ifndef I18N_MB
GCFont|
#endif
GCFunction|GCLineWidth),
&gcv );
/* set up the regular context */
gcv.foreground = core->screen_ptr->black_pixel;
gcv.background = core->screen_ptr->white_pixel;
#ifndef I18N_MB
gcv.font = wtext->font->font->fid;
#endif
gcv.line_width = 1;
gcv.function = GXcopy;
wtext->regGC = XCreateGC( dpy, wtext->core->window,
(GCForeground|GCBackground|
#ifndef I18N_MB
GCFont|
#endif
GCFunction|GCLineWidth),
&gcv );
/* set up the inverted context */
gcv.function = GXcopyInverted;
wtext->invGC = XCreateGC( dpy, wtext->core->window,
(GCForeground|GCBackground|
#ifndef I18N_MB
GCFont|
#endif
GCFunction|GCLineWidth),
&gcv );
/* and set the background! */
XSetWindowBackground( dpy, wtext->core->window, gcv.background );
}
/* Figure out the y-offset... */
wtext->yOffset = (height - wtext->font->height)/2;
wtext->xOffset = wtext->yOffset;
wtext->canceled = False;
wtext->done = False; /* becomes True when the user *
* hits "Return" key */
XMapRaised(dpy, wtext->core->window);
LEAVE("wTextCreate");
return wtext;
}
/********************************************************************\
* wTextDestroy *
* *
* Args: wtext - the text field *
* Return: *
* Global: dpy - the display *
\********************************************************************/
void
wTextDestroy( WTextInput *wtext )
{
ENTER("wTextDestroy")
#if 0
if (wtext->magic)
wDeleteTimerHandler(wtext->magic);
wtext->magic = NULL;
#endif
XFreeGC( dpy, wtext->gc );
XFreeGC( dpy, wtext->regGC );
XFreeGC( dpy, wtext->invGC );
free( wtext->text.txt );
wCoreDestroy( wtext->core );
free( wtext );
LEAVE("wTextDestroy");
}
/* The text-field consists of a frame drawn around the outside,
* and a textbox inside. The space between the frame and the
* text-box is the xOffset,yOffset. When the text needs refreshing,
* we only have to redraw the part inside the text-box, and we can
* leave the frame. If we get an expose event, or for some reason
* need to redraw the frame, wTextPaint will redraw the frame, and
* then call wTextRefresh to redraw the text-box */
/********************************************************************\
* textRefresh *
* Redraw the text field. Call this after messing with the text *
* field. wTextRefresh re-draws the inside of the text field. If *
* the frame-area of the text-field needs redrawing, call *
* wTextPaint() *
* *
* Args: wtext - the text field *
* Return: none *
* Global: dpy - the display *
\********************************************************************/
static void
textRefresh( WTextInput *wtext )
{
int x1,x2,y1,y2;
char *ptr = wtext->text.txt;
/* x1,y1 is the upper left corner of the text box */
x1 = wtext->xOffset;
y1 = wtext->yOffset;
/* x2,y2 is the lower right corner of the text box */
x2 = wtext->core->width - wtext->xOffset;
y2 = wtext->core->height - wtext->yOffset;
/* Fill in the text field. Use the invGC to draw the rectangle,
* becuase then it will be the background color */
XFillRectangle( dpy, wtext->core->window, wtext->invGC,
x1, y1, x2-x1, y2-y1 );
/* Draw the text normally */
wDrawString(wtext->core->window, wtext->font, wtext->regGC,
x1, y2+TEXT_SHIFT, ptr, wtext->text.length);
/* Draw the selected text */
if( wtext->text.startPos != wtext->text.endPos )
{
int sp,ep;
/* we need sp < ep */
if( wtext->text.startPos > wtext->text.endPos )
{
sp = wtext->text.endPos;
ep = wtext->text.startPos;
}
else
{
sp = wtext->text.startPos;
ep = wtext->text.endPos;
}
/* x1,y1 is now the upper-left of the selected area */
x1 += wTextWidth( wtext->font->font, ptr, sp );
/* and x2,y2 is the lower-right of the selected area */
ptr += sp * sizeof(char);
x2 = x1 +wTextWidth( wtext->font->font, ptr, (ep - sp) );
/* Fill in the area where the selected text will go: *
* use the regGC to draw the rectangle, becuase then it *
* will be the color of the non-selected text */
XFillRectangle( dpy, wtext->core->window, wtext->regGC,
x1, y1, x2-x1, y2-y1 );
/* Draw the selected text... use invGC so it will be the
* opposite color as the filled rectangle */
wDrawString(wtext->core->window, wtext->font, wtext->invGC,
x1, y2+TEXT_SHIFT, ptr, (ep - sp));
}
/* And draw a quick little line for the cursor position */
x1 = wTextWidth( wtext->font->font, wtext->text.txt, wtext->text.endPos )
+ wtext->xOffset;
XDrawLine( dpy, wtext->core->window, wtext->regGC, x1, 2, x1,
wtext->core->height - 3 );
}
/********************************************************************\
* wTextPaint *
* *
* Args: wtext - the text field *
* Return: *
* Global: dpy - the display *
\********************************************************************/
void
wTextPaint( WTextInput *wtext )
{
ENTER("wTextPaint");
/* refresh */
textRefresh( wtext );
/* Draw box */
XDrawRectangle(dpy, wtext->core->window, wtext->gc, 0, 0,
wtext->core->width-1, wtext->core->height-1);
LEAVE("wTextPaint");
}
/********************************************************************\
* wTextGetText *
* return the string in the text field wText. DO NOT FREE THE *
* RETURNED STRING! *
* *
* Args: wtext - the text field *
* Return: the text in the text field (NULL terminated) *
* Global: *
\********************************************************************/
char *
wTextGetText( WTextInput *wtext )
{
if (!wtext->canceled)
return wtext->text.txt;
else
return NULL;
}
/********************************************************************\
* wTextPutText *
* Put the string txt in the text field wText. The text field *
* needs to be explicitly refreshed after wTextPutText by calling *
* wTextRefresh(). *
* The string txt is copied *
* *
* Args: wtext - the text field *
* txt - the new text string... freed by the text field! *
* Return: none *
* Global: *
\********************************************************************/
void
wTextPutText( WTextInput *wtext, char *txt )
{
int length = strlen(txt);
/* no memory leaks! free the old txt */
if( wtext->text.txt != NULL )
free( wtext->text.txt );
wtext->text.txt = (char *)wmalloc((length+1)*sizeof(char));
strcpy(wtext->text.txt, txt );
wtext->text.length = length;
/* By default No text is selected, and the cursor is at the end */
wtext->text.startPos = length;
wtext->text.endPos = length;
}
/********************************************************************\
* textInsert *
* Insert some text at the cursor. (if startPos != endPos, *
* replace the selected text, otherwise insert) *
* The string txt is copied. *
* *
* Args: wText - the text field *
* txt - the new text string... freed by the text field! *
* Return: none *
* Global: *
\********************************************************************/
static void
textInsert( WTextInput *wtext, char *txt )
{
char *newTxt;
int newLen, txtLen, i,j;
int sp,ep;
/* we need sp < ep */
if( wtext->text.startPos > wtext->text.endPos )
{
sp = wtext->text.endPos;
ep = wtext->text.startPos;
}
else
{
sp = wtext->text.startPos;
ep = wtext->text.endPos;
}
txtLen = strlen(txt);
newLen = wtext->text.length + txtLen - (ep - sp) + 1;
newTxt = (char *)malloc(newLen*sizeof(char));
/* copy the old text up to sp */
for( i=0; i<sp; i++ )
newTxt[i] = wtext->text.txt[i];
/* insert new text */
for( j=0; j<txtLen; j++,i++ )
newTxt[i] = txt[j];
/* copy old text after ep */
for( j=ep; j<wtext->text.length; j++,i++ )
newTxt[i] = wtext->text.txt[j];
newTxt[i] = '\0';
/* By default No text is selected, and the cursor is at the end
* of inserted text */
wtext->text.startPos = sp+txtLen;
wtext->text.endPos = sp+txtLen;
free(wtext->text.txt);
wtext->text.txt = newTxt;
wtext->text.length = newLen-1;
}
/********************************************************************\
* wTextSelect *
* Select some text. If start == end, then the cursor is moved *
* to that position. If end == -1, then the text from start to *
* the end of the text entered in the text field is selected. *
* The text field is not automatically re-drawn! You must call *
* wTextRefresh to re-draw the text field. *
* *
* Args: wtext - the text field *
* start - the beginning of the selected text *
* end - the end of the selected text *
* Return: none *
* Global: *
\********************************************************************/
void
wTextSelect( WTextInput *wtext, int start, int end )
{
if( end == -1 )
wtext->text.endPos = wtext->text.length;
else
wtext->text.endPos = end;
wtext->text.startPos = start;
}
#if 0
static void
blink(void *data)
{
int x;
WTextInput *wtext = (WTextInput*)data;
GC gc;
/* And draw a quick little line for the cursor position */
if (wtext->blink_on) {
gc = wtext->regGC;
wtext->blink_on = 0;
} else {
gc = wtext->invGC;
wtext->blink_on = 1;
}
x = wTextWidth( wtext->font->font, wtext->text.txt, wtext->text.endPos )
+ wtext->xOffset;
XDrawLine( dpy, wtext->core->window, gc, x, 2, x, wtext->core->height-3);
if (wtext->blinking)
wtext->magic = wAddTimerHandler(CURSOR_BLINK_RATE, blink, data);
}
#endif
/********************************************************************\
* textEventHandler -- handles and dispatches all the events that *
* the text field class supports *
* *
* Args: desc - all we need to know about this object *
* Return: none *
* Global: *
\********************************************************************/
static void
textEventHandler( WObjDescriptor *desc, XEvent *event )
{
WTextInput *wtext = desc->parent;
int handled = False; /* has the event been handled */
switch( event->type )
{
case MotionNotify:
/* If the button isn't down, we don't care about the
* event, but otherwise we want to adjust the selected
* text so we can wTextRefresh() */
if( event->xmotion.state & (Button1Mask|Button3Mask|Button2Mask) )
{
DEBUG("MotionNotify");
handled = True;
wtext->text.endPos = textXtoPos( wtext, event->xmotion.x );
}
break;
case ButtonPress:
DEBUG("ButtonPress");
handled = True;
wtext->text.startPos = textXtoPos( wtext, event->xbutton.x );
wtext->text.endPos = wtext->text.startPos;
break;
case ButtonRelease:
DEBUG("ButtonRelease");
handled = True;
wtext->text.endPos = textXtoPos( wtext, event->xbutton.x );
break;
case KeyPress:
DEBUG("KeyPress");
handled = handleKeyPress( wtext, &event->xkey );
break;
case EnterNotify:
DEBUG("EnterNotify");
handled = True;
#if 0
if (!wtext->magic)
{
wtext->magic = wAddTimerHandler(CURSOR_BLINK_RATE, blink, wtext);
wtext->blink_on = !wtext->blink_on;
blink(wtext);
wtext->blinking = 1;
}
#endif
break;
case LeaveNotify:
DEBUG("LeaveNotify");
handled = True;
#if 0
wtext->blinking = 0;
if (wtext->blink_on)
blink(wtext);
if (wtext->magic)
wDeleteTimerHandler(wtext->magic);
wtext->magic = NULL;
#endif
break;
default:
break;
}
if( handled )
textRefresh(wtext);
else
WMHandleEvent(event);
return;
}
static void
handleExpose(WObjDescriptor *desc, XEvent *event)
{
wTextPaint(desc->parent);
}

66
src/text.h Normal file
View File

@@ -0,0 +1,66 @@
/********************************************************************\
* text.h -- a basic text field *
* Copyright (C) 1997 Robin D. Clark *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
* Author: Rob Clark *
* Internet: rclark@cs.hmc.edu *
* Address: 609 8th Street *
* Huntington Beach, CA 92648-4632 *
\********************************************************************/
#ifndef __TEXT_H__
#define __TEXT_H__
#include "wcore.h"
typedef struct {
char *txt; /* ptr to the text */
int length; /* length of txt[] */
int startPos; /* beginning of selected text */
int endPos; /* end of selected text */
} WTextBlock; /* if startPos == endPos, no txt *
* is selected... they give the *
* cursor position. */
typedef struct {
WCoreWindow *core;
WFont *font;
WTextBlock text;
GC gc;
GC regGC; /* the normal GC */
GC invGC; /* inverted, for selected text */
WMagicNumber *magic;
short xOffset;
short yOffset;
unsigned int done:1;
unsigned int blink_on:1;
unsigned int blinking:1;
unsigned int canceled:1;
} WTextInput;
/** PROTOTYPES ******************************************************/
WTextInput* wTextCreate( WCoreWindow *core, int x, int y, int width,
int height );
void wTextDestroy( WTextInput *wText );
void wTextPaint( WTextInput *wText );
char* wTextGetText( WTextInput *wText );
void wTextPutText( WTextInput *wText, char *txt );
void wTextInsert( WTextInput *wText, char *txt );
void wTextSelect( WTextInput *wText, int start, int end );
void wTextRefresh( WTextInput *wText );
#endif

566
src/texture.c Normal file
View File

@@ -0,0 +1,566 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "texture.h"
#include "funcs.h"
extern WPreferences wPreferences;
static Pixmap renderTexture(WScreen *scr, int width, int height,
WTexture *texture, int rel);
static void bevelImage(RImage *image, int relief);
WTexSolid*
wTextureMakeSolid(WScreen *scr, XColor *color)
{
WTexSolid *texture;
int gcm;
XGCValues gcv;
texture = wmalloc(sizeof(WTexture));
texture->type = WTEX_SOLID;
texture->subtype = 0;
XAllocColor(dpy, scr->w_colormap, color);
texture->normal = *color;
if (color->red==0 && color->blue==0 && color->green == 0) {
texture->light.red = 0xb6da;
texture->light.green = 0xb6da;
texture->light.blue = 0xb6da;
texture->dim.red = 0x6185;
texture->dim.green = 0x6185;
texture->dim.blue = 0x6185;
} else {
RColor rgb;
RHSVColor hsv, hsv2;
int v;
rgb.red = color->red >> 8;
rgb.green = color->green >> 8;
rgb.blue = color->blue >> 8;
RRGBtoHSV(&rgb, &hsv);
RHSVtoRGB(&hsv, &rgb);
hsv2 = hsv;
v = hsv.value*16/10;
hsv.value = (v > 255 ? 255 : v);
RHSVtoRGB(&hsv, &rgb);
texture->light.red = rgb.red << 8;
texture->light.green = rgb.green << 8;
texture->light.blue = rgb.blue << 8;
hsv2.value = hsv2.value/2;
RHSVtoRGB(&hsv2, &rgb);
texture->dim.red = rgb.red << 8;
texture->dim.green = rgb.green << 8;
texture->dim.blue = rgb.blue << 8;
}
texture->dark.red = 0;
texture->dark.green = 0;
texture->dark.blue = 0;
XAllocColor(dpy, scr->w_colormap, &texture->light);
XAllocColor(dpy, scr->w_colormap, &texture->dim);
XAllocColor(dpy, scr->w_colormap, &texture->dark);
gcm = GCForeground|GCBackground|GCGraphicsExposures;
gcv.graphics_exposures = False;
gcv.background = gcv.foreground = texture->light.pixel;
texture->light_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
gcv.background = gcv.foreground = texture->dim.pixel;
texture->dim_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
gcv.background = gcv.foreground = texture->dark.pixel;
texture->dark_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
gcv.background = gcv.foreground = color->pixel;
texture->normal_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
return texture;
}
static int
dummyErrorHandler(Display *foo, XErrorEvent *bar)
{
#ifdef DEBUG
wwarning("your server is buggy. Tell the author if some error related to color occurs");
#endif
return 0;
}
void
wTextureDestroy(WScreen *scr, WTexture *texture)
{
int i;
int count=0;
unsigned long colors[8];
#ifdef DEBUG
if (texture==NULL) {
printf("BUG: trying to free NULL texture\n");
return;
}
#endif
/*
* some stupid servers don't like white or black being freed...
*/
#define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel)
switch (texture->any.type) {
case WTEX_SOLID:
XFreeGC(dpy, texture->solid.light_gc);
XFreeGC(dpy, texture->solid.dark_gc);
XFreeGC(dpy, texture->solid.dim_gc);
if (CANFREE(texture->solid.light.pixel))
colors[count++] = texture->solid.light.pixel;
if (CANFREE(texture->solid.dim.pixel))
colors[count++] = texture->solid.dim.pixel;
if (CANFREE(texture->solid.dark.pixel))
colors[count++] = texture->solid.dark.pixel;
break;
case WTEX_PIXMAP:
RDestroyImage(texture->pixmap.pixmap);
break;
case WTEX_MHGRADIENT:
case WTEX_MVGRADIENT:
case WTEX_MDGRADIENT:
for (i=0; texture->mgradient.colors[i]!=NULL; i++) {
free(texture->mgradient.colors[i]);
}
free(texture->mgradient.colors);
break;
}
if (CANFREE(texture->any.color.pixel))
colors[count++] = texture->any.color.pixel;
if (count > 0) {
XErrorHandler oldhandler;
/* ignore error from buggy servers that don't know how
* to do reference counting for colors. */
oldhandler = XSetErrorHandler(dummyErrorHandler);
XFreeColors(dpy, scr->colormap, colors, count, 0);
XSync(dpy,0);
XSetErrorHandler(oldhandler);
}
XFreeGC(dpy, texture->any.gc);
free(texture);
#undef CANFREE
}
WTexGradient*
wTextureMakeGradient(WScreen *scr, int style, XColor *from, XColor *to)
{
WTexGradient *texture;
XGCValues gcv;
texture = wmalloc(sizeof(WTexture));
memset(texture, 0, sizeof(WTexture));
texture->type = style;
texture->subtype = 0;
texture->color1 = *from;
texture->color2 = *to;
texture->normal.red = (from->red + to->red)/2;
texture->normal.green = (from->green + to->green)/2;
texture->normal.blue = (from->blue + to->blue)/2;
XAllocColor(dpy, scr->w_colormap, &texture->normal);
gcv.background = gcv.foreground = texture->normal.pixel;
gcv.graphics_exposures = False;
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|GCGraphicsExposures, &gcv);
return texture;
}
WTexMGradient*
wTextureMakeMGradient(WScreen *scr, int style, RColor **colors)
{
WTexMGradient *texture;
XGCValues gcv;
int i;
texture = wmalloc(sizeof(WTexture));
memset(texture, 0, sizeof(WTexture));
texture->type = style;
texture->subtype = 0;
i=0;
while (colors[i]!=NULL) i++;
i--;
texture->normal.red = (colors[0]->red<<8);
texture->normal.green = (colors[0]->green<<8);
texture->normal.blue = (colors[0]->blue<<8);
texture->colors = colors;
XAllocColor(dpy, scr->w_colormap, &texture->normal);
gcv.background = gcv.foreground = texture->normal.pixel;
gcv.graphics_exposures = False;
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|GCGraphicsExposures, &gcv);
return texture;
}
WTexPixmap*
wTextureMakePixmap(WScreen *scr, int style, char *pixmap_file, XColor *color)
{
WTexPixmap *texture;
XGCValues gcv;
RImage *image;
char *file;
file = FindImage(wPreferences.pixmap_path, pixmap_file);
if (!file) {
wwarning(_("image file \"%s\" used as texture could not be found."),
pixmap_file);
return NULL;
}
image = RLoadImage(scr->rcontext, file, 0);
if (!image) {
wwarning(_("could not load texture pixmap \"%s\":%s"), file,
RErrorString);
free(file);
return NULL;
}
free(file);
texture = wmalloc(sizeof(WTexture));
memset(texture, 0, sizeof(WTexture));
texture->type = WTEX_PIXMAP;
texture->subtype = style;
texture->normal = *color;
XAllocColor(dpy, scr->w_colormap, &texture->normal);
gcv.background = gcv.foreground = texture->normal.pixel;
gcv.graphics_exposures = False;
texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
|GCGraphicsExposures, &gcv);
texture->pixmap = image;
return texture;
}
RImage*
wTextureRenderImage(WTexture *texture, int width, int height, int relief)
{
RImage *image;
RColor color1, color2;
int d;
int subtype;
switch (texture->any.type) {
case WTEX_SOLID:
image = RCreateImage(width, height, False);
color1.red = texture->solid.normal.red >> 8;
color1.green = texture->solid.normal.green >> 8;
color1.blue = texture->solid.normal.blue >> 8;
color1.alpha = 255;
RClearImage(image, &color1);
break;
case WTEX_PIXMAP:
if (texture->pixmap.subtype == WTP_TILE) {
image = RMakeTiledImage(texture->pixmap.pixmap, width, height);
} else if (texture->pixmap.subtype == WTP_CENTER) {
color1.red = texture->pixmap.normal.red>>8;
color1.green = texture->pixmap.normal.green>>8;
color1.blue = texture->pixmap.normal.blue>>8;
color1.alpha = 255;
image = RMakeCenteredImage(texture->pixmap.pixmap, width, height,
&color1);
} else {
image = RScaleImage(texture->pixmap.pixmap, width, height);
}
break;
case WTEX_HGRADIENT:
subtype = RGRD_HORIZONTAL;
goto render_gradient;
case WTEX_VGRADIENT:
subtype = RGRD_VERTICAL;
goto render_gradient;
case WTEX_DGRADIENT:
subtype = RGRD_DIAGONAL;
render_gradient:
color1.red = texture->gradient.color1.red >> 8;
color1.green = texture->gradient.color1.green >> 8;
color1.blue = texture->gradient.color1.blue >> 8;
color2.red = texture->gradient.color2.red >> 8;
color2.green = texture->gradient.color2.green >> 8;
color2.blue = texture->gradient.color2.blue >> 8;
image = RRenderGradient(width, height, &color1, &color2, subtype);
break;
case WTEX_MHGRADIENT:
subtype = RGRD_HORIZONTAL;
goto render_mgradient;
case WTEX_MVGRADIENT:
subtype = RGRD_VERTICAL;
goto render_mgradient;
case WTEX_MDGRADIENT:
subtype = RGRD_DIAGONAL;
render_mgradient:
image = RRenderMultiGradient(width, height,
&(texture->mgradient.colors[1]),
subtype);
break;
default:
puts("ERROR in wTextureRenderImage()");
image = NULL;
}
if (!image) {
wwarning(_("could not render texture: %s"), RErrorString);
return None;
}
/* render bevel */
switch (relief) {
case WREL_ICON:
d = RBEV_RAISED3;
break;
case WREL_RAISED:
d = RBEV_RAISED2;
break;
case WREL_SUNKEN:
d = RBEV_SUNKEN;
break;
case WREL_FLAT:
d = 0;
break;
case WREL_MENUENTRY:
d = -WREL_MENUENTRY;
break;
default:
d = 0;
}
if (d > 0) {
RBevelImage(image, d);
} else if (d < 0) {
bevelImage(image, -d);
}
return image;
}
/* used only for menu entries */
void
wTextureRender(WScreen *scr, WTexture *texture, Pixmap *data,
int width, int height, int relief)
{
if (!texture)
return;
/*
switch (texture->any.type) {
case WTEX_DGRADIENT:
case WTEX_VGRADIENT:
case WTEX_HGRADIENT:
case WTEX_MHGRADIENT:
case WTEX_MVGRADIENT:
case WTEX_MDGRADIENT:
case WTEX_PIXMAP:
*/
if (!*data) {
*data = renderTexture(scr, width, height, texture, relief);
}/*
break;
}*/
}
static void
bevelImage(RImage *image, int relief)
{
int width = image->width;
int height = image->height;
RColor color;
switch (relief) {
case WREL_MENUENTRY:
color.red = color.green = color.blue = 80;
color.alpha = 0;
ROperateLine(image, RAddOperation, 1, 0, width-2, 0, &color);
ROperateLine(image, RAddOperation, 0, 0, 0, height-1, &color);
color.red = color.green = color.blue = 40;
color.alpha = 0;
ROperateLine(image, RSubtractOperation, width-1, 0, width-1,
height-1, &color);
ROperateLine(image, RSubtractOperation, 1, height-2, width-2,
height-2, &color);
color.red = color.green = color.blue = 0;
color.alpha = 255;
RDrawLine(image, 0, height-1, width-1, height-1, &color);
break;
}
}
static Pixmap
renderTexture(WScreen *scr, int width, int height, WTexture *texture,
int rel)
{
RImage *img;
Pixmap pix;
img = wTextureRenderImage(texture, width, height, rel);
if (!img) {
wwarning(_("could not render texture: %s"), RErrorString);
return None;
}
if (!RConvertImage(scr->rcontext, img, &pix)) {
wwarning(_("error rendering image:%s"), RErrorString);
}
RDestroyImage(img);
return pix;
}
void
wDrawBevel(WCoreWindow *core, WTexSolid *texture, int relief)
{
GC light, dim, dark;
XSegment segs[4];
if (relief==WREL_FLAT) return;
light = texture->light_gc;
dim = texture->dim_gc;
dark = texture->dark_gc;
switch (relief) {
case WREL_FLAT:
return;
case WREL_MENUENTRY:
case WREL_RAISED:
case WREL_ICON:
segs[0].x1 = 1;
segs[0].x2 = core->width - 2;
segs[0].y2 = segs[0].y1 = core->height - 2;
segs[1].x1 = core->width - 2;
segs[1].y1 = 1;
segs[1].x2 = core->width - 2;
segs[1].y2 = core->height - 2;
XDrawSegments(dpy, core->window, dim, segs, 2);
segs[0].x1 = 0;
segs[0].x2 = core->width - 1;
segs[0].y2 = segs[0].y1 = core->height - 1;
segs[1].x1 = segs[1].x2 = core->width - 1;
segs[1].y1 = 0;
segs[1].y2 = core->height - 1;
XDrawSegments(dpy, core->window, dark, segs, 2);
segs[0].x1 = segs[0].y1 = segs[0].y2 = 0;
segs[0].x2 = core->width - 2;
segs[1].x1 = segs[1].y1 = 0;
segs[1].x2 = 0;
segs[1].y2 = core->height - 2;
XDrawSegments(dpy, core->window, light, segs, 2);
if (relief==WREL_ICON) {
segs[0].x1 = segs[0].y1 = segs[0].y2 = 1;
segs[0].x2 = core->width - 2;
segs[1].x1 = segs[1].y1 = 1;
segs[1].x2 = 1;
segs[1].y2 = core->height - 2;
XDrawSegments(dpy, core->window, light, segs, 2);
}
break;
case WREL_SUNKEN:
segs[0].x1 = 0;
segs[0].x2 = core->width - 1;
segs[0].y2 = segs[0].y1 = 0;
segs[1].x1 = segs[1].x2 = 0;
segs[1].y1 = 0;
segs[1].y2 = core->height - 1;
XDrawSegments(dpy, core->window, dark, segs, 2);
segs[0].x1 = 0;
segs[0].y1 = segs[0].y2 = core->height - 1;
segs[0].x2 = core->width - 1;
segs[1].x2 = segs[1].x1 = core->width - 1;
segs[1].y1 = 1;
segs[1].y2 = core->height - 1;
XDrawSegments(dpy, core->window, light, segs, 2);
break;
}
}

156
src/texture.h Normal file
View File

@@ -0,0 +1,156 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMTEXTURE_H_
#define WMTEXTURE_H_
#include "screen.h"
#include "wcore.h"
/* texture relief */
#define WREL_RAISED 0
#define WREL_SUNKEN 1
#define WREL_FLAT 2
#define WREL_ICON 4
#define WREL_MENUENTRY 6
/* texture types */
#define WREL_BORDER_MASK 1
#define WTEX_SOLID ((1<<1)|WREL_BORDER_MASK)
#define WTEX_HGRADIENT ((1<<2)|WREL_BORDER_MASK)
#define WTEX_VGRADIENT ((1<<3)|WREL_BORDER_MASK)
#define WTEX_DGRADIENT ((1<<4)|WREL_BORDER_MASK)
#define WTEX_MHGRADIENT ((1<<5)|WREL_BORDER_MASK)
#define WTEX_MVGRADIENT ((1<<6)|WREL_BORDER_MASK)
#define WTEX_MDGRADIENT ((1<<7)|WREL_BORDER_MASK)
#define WTEX_PIXMAP (1<<8)
/* pixmap subtypes */
#define WTP_TILE 2
#define WTP_SCALE 4
#define WTP_CENTER 6
/*
* (solid <color>)
* (hgradient <color> <color>)
* (vgradient <color> <color>)
* (dgradient <color> <color>)
* (pixmap <file> <mode>)
*/
typedef struct {
short type; /* type of texture */
char subtype; /* subtype of the texture */
XColor color; /* default background color */
GC gc; /* gc for the background color */
} WTexAny;
typedef struct WTexSolid {
short type;
char subtype;
XColor normal;
GC normal_gc;
GC light_gc;
GC dim_gc;
GC dark_gc;
XColor light;
XColor dim;
XColor dark;
} WTexSolid;
typedef struct WTexGradient {
short type;
char subtype;
XColor normal;
GC normal_gc;
XColor color1;
XColor color2;
} WTexGradient;
typedef struct WTexMGradient {
short type;
char subtype;
XColor normal;
GC normal_gc;
RColor **colors;
} WTexMGradient;
typedef struct WTexPixmap {
short type;
char subtype;
XColor normal;
GC normal_gc;
struct RImage *pixmap;
} WTexPixmap;
typedef struct WTexCompose {
short type;
char subtype;
XColor normal;
GC normal_gc;
union WTexture *back;
union WTexture *fore;
int opacity;
} WTexCompose;
typedef union WTexture {
WTexAny any;
WTexSolid solid;
WTexGradient gradient;
WTexMGradient mgradient;
WTexPixmap pixmap;
WTexCompose compose;
} WTexture;
WTexSolid *wTextureMakeSolid(WScreen*, XColor*);
WTexGradient *wTextureMakeGradient(WScreen*, int, XColor*, XColor*);
WTexMGradient *wTextureMakeMGradient(WScreen*, int, RColor**);
WTexPixmap *wTextureMakePixmap(WScreen *scr, int style, char *pixmap_file,
XColor *color);
void wTextureDestroy(WScreen*, WTexture*);
void wTexturePaint(WTexture *, Pixmap *, WCoreWindow*, int, int);
void wTextureRender(WScreen*, WTexture*, Pixmap*, int, int, int);
struct RImage *wTextureRenderImage(WTexture*, int, int, int);
void wTexturePaintTitlebar(struct WWindow *wwin, WTexture *texture, Pixmap *tdata,
int repaint);
#define FREE_PIXMAP(p) if ((p)!=None) XFreePixmap(dpy, (p)), (p)=None
void wDrawBevel(WCoreWindow *core, WTexSolid *texture, int relief);
#endif

444
src/wconfig.h Normal file
View File

@@ -0,0 +1,444 @@
/*
* wconfig.h- default configuration and definitions
*
* WindowMaker window manager
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef WMCONFIG_H_
#define WMCONFIG_H_
#include "config.h"
/*
*--------------------------------------------------------------------
* Feature Selection
*
* Comment out the following #defines if you want to
* disable a feature.
* Also check the features you can enable through configure.
*--------------------------------------------------------------------
*/
/* undefine ANIMATIONS if you don't want animations for iconification,
* shading, icon arrangement etc. */
#define ANIMATIONS
/*
* #undef if you dont want the window creation animation when superfluous
* is enabled.
* THIS WILL NOT BE MADE RUN-TIME.
*/
#define WINDOW_BIRTH_ZOOM
/*
* mimic N*XTSTEP behaviour as close as possible.
* affected behaviour:
* - disable auto-lower miniwindows
*/
#undef STRICTNS
/*
* undefine USECPP if you don't want your config files to be preprocessed
* by cpp
*/
#define USECPP
/* #define CPP_PATH /lib/cpp */
/*
* Internationalization (I18N) support
* Multi-byte (japanese, korean, chinese etc.) character support
* set by configure
*/
#undef I18N_MB
/*
* sound support
*/
#define WMSOUND
/*
* support for OffiX DND drag and drop in the Dock
*/
#define OFFIX_DND
/* define CONFIGURE_WINDOW_WHILE_MOVING if you want WindowMaker to send
* the synthetic ConfigureNotify event to windows while moving at every
* single movement. Default is to send a synthetic ConfigureNotify event
* only at the end of window moving, which improves performance.
*/
#undef CONFIGURE_WINDOW_WHILE_MOVING
/*
* Undefine BALLOON_TEXT if you don't want balloons for showing extra
* information, like window titles that are not fully visible.
*/
#define BALLOON_TEXT
/*
* If balloons should be shaped or be simple rectangles.
* The X server must support the shape extensions and it's support
* must be enabled (default).
*/
#define SHAPED_BALLOON
/*
* Define NO_EMERGENCY_AUTORESTART if you don't want another window manager
* automatically started when WindowMaker crashes. The X session will die
* in some cases if wmaker crashes and autorestart is disabled.
*/
#undef NO_EMERGENCY_AUTORESTART
/*
* The window manager that is autorestarted
*/
#define FALLBACK_WINDOWMANAGER "blackbox"
/* Define if you want MWM hint support (and consequently GNOME). */
#define MWM_HINTS
/*
* Turn on a hack to make mouse and keyboard actions work even if
* the NumLock or ScrollLock modifiers are turned on. They might
* inflict a performance/memory penalty.
*
* If you're an X expert (knows the implementation of XGrabKey() in X)
* and knows that the penalty is small (or not), please tell me.
*/
#define NUMLOCK_HACK
/*
* define SHADOW_RESIZEBAR if you want a resizebar with shadows like in
* NextStep 3.x ??, instead of the default Openstep look. NEXTSTEP 3.3
* also does not have these shadows.
*/
#undef SHADOW_RESIZEBAR
/*
* define REDUCE_APPICONS if you want apps with the same WM_INSTANCE &&
* WM_CLASS to share an appicon
*/
#undef REDUCE_APPICONS
/*
* Define SPREAD_ICON if you want icon blowing animation (when detached from
* dock/clip in the superfluous mode), to spread the icon in four directions.
* If this is undefined, then the classic "Falling pieces" animation is used.
*/
#undef SPREAD_ICON
/*
*--------------------------------------------------------------------
* Default Configuration
*
* Some of the following options can be configured in
* the preference files, but if for some reason, they can't
* be used, these defaults will be.
* There are also some options that can only be configured here,
* at compile time.
*--------------------------------------------------------------------
*/
/* list of paths to look for the config files, searched in order
* of appearance */
#define DEF_CONFIG_PATHS \
"~/GNUstep/Library/WindowMaker:"PKGDATADIR
/* name of the script to execute at startup */
#define DEF_INIT_SCRIPT "autostart"
#define DEF_EXIT_SCRIPT "exitscript"
#define DEFAULTS_DIR "Defaults"
/* pixmap path */
#define DEF_PIXMAP_PATHS \
"(\"~/pixmaps\",\"~/GNUstep/Library/WindowMaker/Pixmaps\",\""PIXMAPDIR"\")"
/* icon path */
#define DEF_ICON_PATHS \
"(\"~/pixmaps\",\"~/GNUstep/Library/Icons\",\"/usr/include/X11/pixmaps/\",\""PIXMAPDIR"\")"
/* window title to use for untitled windows */
#define DEF_WINDOW_TITLE "Untitled"
/* default style */
#define DEF_FRAME_COLOR "white"
#ifdef I18N_MB
#define DEF_TITLE_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_MENU_TITLE_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_MENU_ENTRY_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_ICON_TITLE_FONT "\"-*-*-medium-r-normal--10-*\""
#define DEF_CLIP_TITLE_FONT "\"-*-*-medium-r-normal--10-*\""
#define DEF_INFO_TEXT_FONT "\"-*-*-medium-r-normal--14-*\""
#else /* I18N_MB */
#define DEF_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_MENU_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_MENU_ENTRY_FONT "\"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_ICON_TITLE_FONT "\"-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*\""
#define DEF_CLIP_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-10-*-*-*-*-*-*-*\""
#define DEF_INFO_TEXT_FONT "\"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\""
#endif /* !I18N_MB */
#define HELVETICA10_FONT "-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*"
#define DEF_FRAME_THICKNESS 1 /* linewidth of the move/resize frame */
#define DEF_XPM_CLOSENESS 40000
/* default position of application menus */
#define DEF_APPMENU_X 10
#define DEF_APPMENU_Y 10
/* do not divide main menu and submenu in different tiers,
* opposed to OpenStep */
#define SINGLE_MENULEVEL
/* Zoom animation */
#define MINIATURIZE_ANIMATION_FRAMES_Z 5
#define MINIATURIZE_ANIMATION_STEPS_Z 12
#define MINIATURIZE_ANIMATION_DELAY_Z 500
/* Twist animation */
#define MINIATURIZE_ANIMATION_FRAMES_T 12
#define MINIATURIZE_ANIMATION_STEPS_T 16
#define MINIATURIZE_ANIMATION_DELAY_T 1000
#define MINIATURIZE_ANIMATION_TWIST_T 0.5
/* Flip animation */
#define MINIATURIZE_ANIMATION_FRAMES_F 12
#define MINIATURIZE_ANIMATION_STEPS_F 16
#define MINIATURIZE_ANIMATION_DELAY_F 1000
#define MINIATURIZE_ANIMATION_TWIST_F 0.5
#define BALLOON_DELAY 1000
/* animation speed constants */
/* icon slide */
#define ICON_SLIDE_SLOWDOWN_UF 20
#define ICON_SLIDE_DELAY_UF 0
#define ICON_SLIDE_STEPS_UF 15
#define ICON_SLIDE_SLOWDOWN_F 30
#define ICON_SLIDE_DELAY_F 0
#define ICON_SLIDE_STEPS_F 10
#define ICON_SLIDE_SLOWDOWN_M 40
#define ICON_SLIDE_DELAY_M 0
#define ICON_SLIDE_STEPS_M 5
#define ICON_SLIDE_SLOWDOWN_S 50
#define ICON_SLIDE_DELAY_S 0
#define ICON_SLIDE_STEPS_S 3
#define ICON_SLIDE_SLOWDOWN_U 50
#define ICON_SLIDE_DELAY_U 3
#define ICON_SLIDE_STEPS_U 3
/* menu scrolling */
#define MENU_SCROLL_STEPS_UF 14
#define MENU_SCROLL_DELAY_UF 0
#define MENU_SCROLL_STEPS_F 10
#define MENU_SCROLL_DELAY_F 5
#define MENU_SCROLL_STEPS_M 6
#define MENU_SCROLL_DELAY_M 5
#define MENU_SCROLL_STEPS_S 4
#define MENU_SCROLL_DELAY_S 6
#define MENU_SCROLL_STEPS_U 1
#define MENU_SCROLL_DELAY_U 8
/* shade animation */
#define SHADE_STEPS_UF 5
#define SHADE_DELAY_UF 0
#define SHADE_STEPS_F 10
#define SHADE_DELAY_F 0
#define SHADE_STEPS_M 15
#define SHADE_DELAY_M 0
#define SHADE_STEPS_S 30
#define SHADE_DELAY_S 0
#define SHADE_STEPS_U 20
#define SHADE_DELAY_U 10
/* window birth animation steps (DO NOT MAKE IT RUN-TIME) */
#define WINDOW_BIRTH_STEPS 20
/* Delay when cycling colors of selected icons. */
#define COLOR_CYCLE_DELAY 300
/* Position increment for smart placement. >= 1 raise these values if it's
* too slow for you */
#define PLACETEST_HSTEP 8
#define PLACETEST_VSTEP 8
#define DOCK_EXTRA_SPACE 1
/* Vicinity in which an icon can be attached to the clip */
#define CLIP_ATTACH_VICINITY 1
/* Delay (in ms) after which the clip will autocollapse when leaved */
#define AUTO_COLLAPSE_DELAY 1000
/* Max. number of icons the clip can have */
#define CLIP_MAX_ICONS 32
/* blink interval when invoking a menu item */
#define MENU_BLINK_DELAY 60000
#define MENU_BLINK_COUNT 2
#define CURSOR_BLINK_RATE 300
#define MOVE_THRESHOLD 3 /* how many pixels to move before dragging windows */
#define HRESIZE_THRESHOLD 3
#define MAX_WORKSPACENAME_WIDTH 16
#define MAX_WINDOWLIST_WIDTH 160 /* max width of window title in
* window list */
#define DEFAULTS_CHECK_INTERVAL 2000 /* how often wmaker will check for
* changes in the config files */
/* if your keyboard don't have arrow keys */
#undef ARROWLESS_KBD
/* don't put titles in miniwindows */
#undef NO_MINIWINDOW_TITLES
/*
* disable/enable workspace indicator in the dock
*/
#undef WS_INDICATOR
/* the button positions in the clip */
#define LCLIPB_X 4
#define RCLIPB_X 32
#define CLIPB_Y 41
#define CLIPB_W 27
#define CLIPB_H 18
/*
*----------------------------------------------------------------------
* You should not modify the following values, unless you know
* what you're doing.
*----------------------------------------------------------------------
*/
#define WM_PI 3.14159265358979323846
#define FRAME_BORDER_COLOR "black"
#define FRAME_BORDER_WIDTH 1 /* width of window border for frames */
#define RESIZEBAR_HEIGHT 8 /* height of the resizebar */
#define RESIZEBAR_MIN_WIDTH 20 /* min. width of handles-corner_width */
#define RESIZEBAR_CORNER_WIDTH 28 /* width of the corner of resizebars */
#define TITLEBAR_EXTRA_HEIGHT 8
#define MENU_INDICATOR_SPACE 12
/* minimum size for windows */
#define MIN_WINDOW_SIZE 5
#define MIN_TITLEFONT_HEIGHT(h) ((h)>14 ? (h) : 14)
#define ICON_WIDTH 64 /* size of the icon window */
#define ICON_HEIGHT 64
#define ICON_BORDER_WIDTH 2
#define MAX_ICON_WIDTH 60 /* size of the icon pixmap */
#define MAX_ICON_HEIGHT 48
#define MAX_WORKSPACES 100
#define MAX_MENU_TEXT_LENGTH 512
#define MAX_RESTART_ARGS 16
#define MAX_COMMAND_SIZE 1024
#define MAX_DEAD_PROCESSES 128
#define MAXLINE 1024
#ifdef _MAX_PATH
# define DEFAULT_PATH_MAX _MAX_PATH
#else
# define DEFAULT_PATH_MAX 512
#endif
#ifndef SHAPE
#undef SHAPED_BALLOON
#endif
#define DEBUG0
#if HAVE_LIBINTL_H && I18N
# include <libintl.h>
# define _(text) gettext(text)
#else
# define _(text) (text)
#endif
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
# define INLINE inline
#else
# define INLINE
#endif
#endif /* WMCONFIG_H_ */

444
src/wconfig.h.in Normal file
View File

@@ -0,0 +1,444 @@
/*
* wconfig.h- default configuration and definitions
*
* WindowMaker window manager
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef WMCONFIG_H_
#define WMCONFIG_H_
#include "config.h"
/*
*--------------------------------------------------------------------
* Feature Selection
*
* Comment out the following #defines if you want to
* disable a feature.
* Also check the features you can enable through configure.
*--------------------------------------------------------------------
*/
/* undefine ANIMATIONS if you don't want animations for iconification,
* shading, icon arrangement etc. */
#define ANIMATIONS
/*
* #undef if you dont want the window creation animation when superfluous
* is enabled.
* THIS WILL NOT BE MADE RUN-TIME.
*/
#define WINDOW_BIRTH_ZOOM
/*
* mimic N*XTSTEP behaviour as close as possible.
* affected behaviour:
* - disable auto-lower miniwindows
*/
#undef STRICTNS
/*
* undefine USECPP if you don't want your config files to be preprocessed
* by cpp
*/
#define USECPP
/* #define CPP_PATH @CPP_PATH@ */
/*
* Internationalization (I18N) support
* Multi-byte (japanese, korean, chinese etc.) character support
* set by configure
*/
@I18N_MB@
/*
* sound support
*/
@SOUND@
/*
* support for OffiX DND drag and drop in the Dock
*/
#define OFFIX_DND
/* define CONFIGURE_WINDOW_WHILE_MOVING if you want WindowMaker to send
* the synthetic ConfigureNotify event to windows while moving at every
* single movement. Default is to send a synthetic ConfigureNotify event
* only at the end of window moving, which improves performance.
*/
#undef CONFIGURE_WINDOW_WHILE_MOVING
/*
* Undefine BALLOON_TEXT if you don't want balloons for showing extra
* information, like window titles that are not fully visible.
*/
#define BALLOON_TEXT
/*
* If balloons should be shaped or be simple rectangles.
* The X server must support the shape extensions and it's support
* must be enabled (default).
*/
#define SHAPED_BALLOON
/*
* Define NO_EMERGENCY_AUTORESTART if you don't want another window manager
* automatically started when WindowMaker crashes. The X session will die
* in some cases if wmaker crashes and autorestart is disabled.
*/
#undef NO_EMERGENCY_AUTORESTART
/*
* The window manager that is autorestarted
*/
#define FALLBACK_WINDOWMANAGER "blackbox"
/* Define if you want MWM hint support (and consequently GNOME). */
#define MWM_HINTS
/*
* Turn on a hack to make mouse and keyboard actions work even if
* the NumLock or ScrollLock modifiers are turned on. They might
* inflict a performance/memory penalty.
*
* If you're an X expert (knows the implementation of XGrabKey() in X)
* and knows that the penalty is small (or not), please tell me.
*/
#define NUMLOCK_HACK
/*
* define SHADOW_RESIZEBAR if you want a resizebar with shadows like in
* NextStep 3.x ??, instead of the default Openstep look. NEXTSTEP 3.3
* also does not have these shadows.
*/
#undef SHADOW_RESIZEBAR
/*
* define REDUCE_APPICONS if you want apps with the same WM_INSTANCE &&
* WM_CLASS to share an appicon
*/
@REDUCE_APPICONS@
/*
* Define SPREAD_ICON if you want icon blowing animation (when detached from
* dock/clip in the superfluous mode), to spread the icon in four directions.
* If this is undefined, then the classic "Falling pieces" animation is used.
*/
#undef SPREAD_ICON
/*
*--------------------------------------------------------------------
* Default Configuration
*
* Some of the following options can be configured in
* the preference files, but if for some reason, they can't
* be used, these defaults will be.
* There are also some options that can only be configured here,
* at compile time.
*--------------------------------------------------------------------
*/
/* list of paths to look for the config files, searched in order
* of appearance */
#define DEF_CONFIG_PATHS \
"~/GNUstep/Library/WindowMaker:"PKGDATADIR
/* name of the script to execute at startup */
#define DEF_INIT_SCRIPT "autostart"
#define DEF_EXIT_SCRIPT "exitscript"
#define DEFAULTS_DIR "Defaults"
/* pixmap path */
#define DEF_PIXMAP_PATHS \
"(\"~/pixmaps\",\"~/GNUstep/Library/WindowMaker/Pixmaps\",\""PIXMAPDIR"\")"
/* icon path */
#define DEF_ICON_PATHS \
"(\"~/pixmaps\",\"~/GNUstep/Library/Icons\",\"/usr/include/X11/pixmaps/\",\""PIXMAPDIR"\")"
/* window title to use for untitled windows */
#define DEF_WINDOW_TITLE "Untitled"
/* default style */
#define DEF_FRAME_COLOR "white"
#ifdef I18N_MB
#define DEF_TITLE_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_MENU_TITLE_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_MENU_ENTRY_FONT "\"-*-*-medium-r-normal--14-*\""
#define DEF_ICON_TITLE_FONT "\"-*-*-medium-r-normal--10-*\""
#define DEF_CLIP_TITLE_FONT "\"-*-*-medium-r-normal--10-*\""
#define DEF_INFO_TEXT_FONT "\"-*-*-medium-r-normal--14-*\""
#else /* I18N_MB */
#define DEF_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_MENU_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_MENU_ENTRY_FONT "\"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\""
#define DEF_ICON_TITLE_FONT "\"-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*\""
#define DEF_CLIP_TITLE_FONT "\"-*-helvetica-bold-r-normal-*-10-*-*-*-*-*-*-*\""
#define DEF_INFO_TEXT_FONT "\"-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\""
#endif /* !I18N_MB */
#define HELVETICA10_FONT "-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*"
#define DEF_FRAME_THICKNESS 1 /* linewidth of the move/resize frame */
#define DEF_XPM_CLOSENESS 40000
/* default position of application menus */
#define DEF_APPMENU_X 10
#define DEF_APPMENU_Y 10
/* do not divide main menu and submenu in different tiers,
* opposed to OpenStep */
#define SINGLE_MENULEVEL
/* Zoom animation */
#define MINIATURIZE_ANIMATION_FRAMES_Z 5
#define MINIATURIZE_ANIMATION_STEPS_Z 12
#define MINIATURIZE_ANIMATION_DELAY_Z 500
/* Twist animation */
#define MINIATURIZE_ANIMATION_FRAMES_T 12
#define MINIATURIZE_ANIMATION_STEPS_T 16
#define MINIATURIZE_ANIMATION_DELAY_T 1000
#define MINIATURIZE_ANIMATION_TWIST_T 0.5
/* Flip animation */
#define MINIATURIZE_ANIMATION_FRAMES_F 12
#define MINIATURIZE_ANIMATION_STEPS_F 16
#define MINIATURIZE_ANIMATION_DELAY_F 1000
#define MINIATURIZE_ANIMATION_TWIST_F 0.5
#define BALLOON_DELAY 1000
/* animation speed constants */
/* icon slide */
#define ICON_SLIDE_SLOWDOWN_UF 20
#define ICON_SLIDE_DELAY_UF 0
#define ICON_SLIDE_STEPS_UF 15
#define ICON_SLIDE_SLOWDOWN_F 30
#define ICON_SLIDE_DELAY_F 0
#define ICON_SLIDE_STEPS_F 10
#define ICON_SLIDE_SLOWDOWN_M 40
#define ICON_SLIDE_DELAY_M 0
#define ICON_SLIDE_STEPS_M 5
#define ICON_SLIDE_SLOWDOWN_S 50
#define ICON_SLIDE_DELAY_S 0
#define ICON_SLIDE_STEPS_S 3
#define ICON_SLIDE_SLOWDOWN_U 50
#define ICON_SLIDE_DELAY_U 3
#define ICON_SLIDE_STEPS_U 3
/* menu scrolling */
#define MENU_SCROLL_STEPS_UF 14
#define MENU_SCROLL_DELAY_UF 0
#define MENU_SCROLL_STEPS_F 10
#define MENU_SCROLL_DELAY_F 5
#define MENU_SCROLL_STEPS_M 6
#define MENU_SCROLL_DELAY_M 5
#define MENU_SCROLL_STEPS_S 4
#define MENU_SCROLL_DELAY_S 6
#define MENU_SCROLL_STEPS_U 1
#define MENU_SCROLL_DELAY_U 8
/* shade animation */
#define SHADE_STEPS_UF 5
#define SHADE_DELAY_UF 0
#define SHADE_STEPS_F 10
#define SHADE_DELAY_F 0
#define SHADE_STEPS_M 15
#define SHADE_DELAY_M 0
#define SHADE_STEPS_S 30
#define SHADE_DELAY_S 0
#define SHADE_STEPS_U 20
#define SHADE_DELAY_U 10
/* window birth animation steps (DO NOT MAKE IT RUN-TIME) */
#define WINDOW_BIRTH_STEPS 20
/* Delay when cycling colors of selected icons. */
#define COLOR_CYCLE_DELAY 300
/* Position increment for smart placement. >= 1 raise these values if it's
* too slow for you */
#define PLACETEST_HSTEP 8
#define PLACETEST_VSTEP 8
#define DOCK_EXTRA_SPACE 1
/* Vicinity in which an icon can be attached to the clip */
#define CLIP_ATTACH_VICINITY 1
/* Delay (in ms) after which the clip will autocollapse when leaved */
#define AUTO_COLLAPSE_DELAY 1000
/* Max. number of icons the clip can have */
#define CLIP_MAX_ICONS 32
/* blink interval when invoking a menu item */
#define MENU_BLINK_DELAY 60000
#define MENU_BLINK_COUNT 2
#define CURSOR_BLINK_RATE 300
#define MOVE_THRESHOLD 3 /* how many pixels to move before dragging windows */
#define HRESIZE_THRESHOLD 3
#define MAX_WORKSPACENAME_WIDTH 16
#define MAX_WINDOWLIST_WIDTH 160 /* max width of window title in
* window list */
#define DEFAULTS_CHECK_INTERVAL 2000 /* how often wmaker will check for
* changes in the config files */
/* if your keyboard don't have arrow keys */
#undef ARROWLESS_KBD
/* don't put titles in miniwindows */
#undef NO_MINIWINDOW_TITLES
/*
* disable/enable workspace indicator in the dock
*/
#undef WS_INDICATOR
/* the button positions in the clip */
#define LCLIPB_X 4
#define RCLIPB_X 32
#define CLIPB_Y 41
#define CLIPB_W 27
#define CLIPB_H 18
/*
*----------------------------------------------------------------------
* You should not modify the following values, unless you know
* what you're doing.
*----------------------------------------------------------------------
*/
#define WM_PI 3.14159265358979323846
#define FRAME_BORDER_COLOR "black"
#define FRAME_BORDER_WIDTH 1 /* width of window border for frames */
#define RESIZEBAR_HEIGHT 8 /* height of the resizebar */
#define RESIZEBAR_MIN_WIDTH 20 /* min. width of handles-corner_width */
#define RESIZEBAR_CORNER_WIDTH 28 /* width of the corner of resizebars */
#define TITLEBAR_EXTRA_HEIGHT 8
#define MENU_INDICATOR_SPACE 12
/* minimum size for windows */
#define MIN_WINDOW_SIZE 5
#define MIN_TITLEFONT_HEIGHT(h) ((h)>14 ? (h) : 14)
#define ICON_WIDTH 64 /* size of the icon window */
#define ICON_HEIGHT 64
#define ICON_BORDER_WIDTH 2
#define MAX_ICON_WIDTH 60 /* size of the icon pixmap */
#define MAX_ICON_HEIGHT 48
#define MAX_WORKSPACES 100
#define MAX_MENU_TEXT_LENGTH 512
#define MAX_RESTART_ARGS 16
#define MAX_COMMAND_SIZE 1024
#define MAX_DEAD_PROCESSES 128
#define MAXLINE 1024
#ifdef _MAX_PATH
# define DEFAULT_PATH_MAX _MAX_PATH
#else
# define DEFAULT_PATH_MAX 512
#endif
#ifndef SHAPE
#undef SHAPED_BALLOON
#endif
#define DEBUG0
#if HAVE_LIBINTL_H && I18N
# include <libintl.h>
# define _(text) gettext(text)
#else
# define _(text) (text)
#endif
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
# define INLINE inline
#else
# define INLINE
#endif
#endif /* WMCONFIG_H_ */

185
src/wcore.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
/****** Global Variables ******/
extern WPreferences wPreferences;
/* cursors */
extern Cursor wCursor[WCUR_LAST];
extern XContext wWinContext;
/*
*----------------------------------------------------------------------
* wCoreCreateTopLevel--
* Creates a toplevel window used for icons, menus and dialogs.
*
* Returns:
* The created window.
*----------------------------------------------------------------------
*/
WCoreWindow*
wCoreCreateTopLevel(WScreen *screen, int x, int y, int width, int height,
int bwidth)
{
WCoreWindow *core;
int vmask;
XSetWindowAttributes attribs;
core = wmalloc(sizeof(WCoreWindow));
memset(core, 0, sizeof(WCoreWindow));
vmask = /*CWBackPixmap|*/CWBackPixel|CWBorderPixel|CWCursor|CWEventMask
|CWOverrideRedirect;
attribs.override_redirect = True;
attribs.cursor = wCursor[WCUR_DEFAULT];
attribs.background_pixmap = None;
attribs.background_pixel = screen->light_pixel;
attribs.border_pixel = screen->frame_border_pixel;
attribs.event_mask = SubstructureRedirectMask | ButtonPressMask
| ButtonReleaseMask | ButtonMotionMask | ExposureMask | EnterWindowMask
| LeaveWindowMask;
vmask |= CWColormap;
attribs.colormap = screen->w_colormap;
core->window = XCreateWindow(dpy, screen->root_win, x, y, width, height,
bwidth, screen->w_depth, CopyFromParent,
screen->w_visual, vmask, &attribs);
core->width = width;
core->height = height;
core->screen_ptr = screen;
core->descriptor.self = core;
XClearWindow(dpy, core->window);
XSaveContext(dpy, core->window, wWinContext, (XPointer)&core->descriptor);
return core;
}
/*
*----------------------------------------------------------------------
* wCoreCreate--
* Creates a brand new child window.
* The window will have a border width of 0 and color is black.
*
* Returns:
* A initialized core window structure.
*
* Side effects:
* A window context for the created window is saved.
*
* Notes:
* The event mask is initialized to a default value.
*
*----------------------------------------------------------------------
*/
WCoreWindow*
wCoreCreate(WCoreWindow *parent, int x, int y, int width, int height)
{
WCoreWindow *core;
int vmask;
XSetWindowAttributes attribs;
core=wmalloc(sizeof(WCoreWindow));
memset(core, 0, sizeof(WCoreWindow));
vmask = CWBackPixmap|CWBackPixel|CWBorderPixel|CWCursor|CWEventMask;
attribs.cursor = wCursor[WCUR_DEFAULT];
attribs.background_pixmap = None;
attribs.background_pixel = parent->screen_ptr->black_pixel;
attribs.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask
| ButtonReleaseMask | ButtonMotionMask | ExposureMask | EnterWindowMask
| LeaveWindowMask;
/*
vmask |= CWColormap;
attribs.colormap = parent->screen_ptr->w_colormap;
*/
core->window =
XCreateWindow(dpy, parent->window, x, y, width, height, 0,
parent->screen_ptr->w_depth, CopyFromParent,
parent->screen_ptr->w_visual, vmask, &attribs);
core->width=width;
core->height=height;
core->screen_ptr = parent->screen_ptr;
core->descriptor.self = core;
XSaveContext(dpy, core->window, wWinContext, (XPointer)&core->descriptor);
return core;
}
void
wCoreDestroy(WCoreWindow *core)
{
if (core->stacking) {
free(core->stacking);
}
XDeleteContext(dpy, core->window, wWinContext);
XDestroyWindow(dpy, core->window);
free(core);
}
void
wCoreConfigure(WCoreWindow *core, int req_x, int req_y, int req_w, int req_h)
{
XWindowChanges xwc;
unsigned int mask;
mask = CWX|CWY;
xwc.x = req_x;
xwc.y = req_y;
if (req_w <= 0)
req_w = core->width;
if (req_h <= 0)
req_h = core->height;
if (req_w != core->width || req_h != core->height) {
mask |= CWWidth | CWHeight;
xwc.width = req_w;
xwc.height = req_h;
core->width = req_w;
core->height = req_h;
}
XConfigureWindow(dpy, core->window, mask, &xwc);
}

57
src/wcore.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMCORE_H_
#define WMCORE_H_
#include "screen.h"
typedef struct WStacking {
struct _WCoreWindow *above;
struct _WCoreWindow *under;
short window_level;
struct _WCoreWindow *child_of; /* owner for transient window */
} WStacking;
typedef struct _WCoreWindow {
Window window;
unsigned int width; /* size of the window */
unsigned int height;
WScreen *screen_ptr; /* ptr to screen of the window */
WObjDescriptor descriptor;
WStacking *stacking; /* window stacking information */
} WCoreWindow;
#include "pixmap.h"
WCoreWindow *wCoreCreateTopLevel(WScreen *screen, int x, int y, int width,
int height, int bwidth);
WCoreWindow *wCoreCreate(WCoreWindow *parent, int x, int y,
int width, int height);
void wCoreDestroy(WCoreWindow *core);
void wCoreConfigure(WCoreWindow *core, int req_x, int req_y,
int req_w, int req_h);
#endif

586
src/wdefaults.c Normal file
View File

@@ -0,0 +1,586 @@
/* wdefaults.c - window specific defaults
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <wraster.h>
#include "WindowMaker.h"
#include "window.h"
#include "screen.h"
#include "funcs.h"
#include "workspace.h"
#include "defaults.h"
#include "icon.h"
/* Global stuff */
extern WPreferences wPreferences;
extern proplist_t wAttributeDomainName;
extern WDDomain *WDWindowAttributes;
/* Local stuff */
/* type converters */
static int getBool(proplist_t, proplist_t);
static char* getString(proplist_t, proplist_t);
static proplist_t ANoTitlebar = NULL;
static proplist_t ANoResizebar;
static proplist_t ANoMiniaturizeButton;
static proplist_t ANoCloseButton;
static proplist_t ANoHideOthers;
static proplist_t ANoMouseBindings;
static proplist_t ANoKeyBindings;
static proplist_t ANoAppIcon; /* app */
static proplist_t AKeepOnTop;
static proplist_t AOmnipresent;
static proplist_t ASkipWindowList;
static proplist_t AKeepInsideScreen;
static proplist_t AUnfocusable;
static proplist_t AAlwaysUserIcon;
static proplist_t AStartMiniaturized;
static proplist_t AStartHidden; /* app */
static proplist_t ADontSaveSession; /* app */
static proplist_t AEmulateAppIcon;
static proplist_t AStartWorkspace;
static proplist_t AIcon;
static proplist_t AnyWindow;
static proplist_t No;
static void
init_wdefaults(WScreen *scr)
{
AIcon = PLMakeString("Icon");
ANoTitlebar = PLMakeString("NoTitlebar");
ANoResizebar = PLMakeString("NoResizebar");
ANoMiniaturizeButton = PLMakeString("NoMiniaturizeButton");
ANoCloseButton = PLMakeString("NoCloseButton");
ANoHideOthers = PLMakeString("NoHideOthers");
ANoMouseBindings = PLMakeString("NoMouseBindings");
ANoKeyBindings = PLMakeString("NoKeyBindings");
ANoAppIcon = PLMakeString("NoAppIcon");
AKeepOnTop = PLMakeString("KeepOnTop");
AOmnipresent = PLMakeString("Omnipresent");
ASkipWindowList = PLMakeString("SkipWindowList");
AKeepInsideScreen = PLMakeString("KeepInsideScreen");
AUnfocusable = PLMakeString("Unfocusable");
AAlwaysUserIcon = PLMakeString("AlwaysUserIcon");
AStartMiniaturized = PLMakeString("StartMiniaturized");
AStartHidden = PLMakeString("StartHidden");
ADontSaveSession = PLMakeString("DontSaveSession");
AEmulateAppIcon = PLMakeString("EmulateAppIcon");
AStartWorkspace = PLMakeString("StartWorkspace");
AnyWindow = PLMakeString("*");
No = PLMakeString("No");
/*
if (!scr->wattribs) {
scr->wattribs = PLGetDomain(wAttributeDomainName);
}*/
}
static proplist_t
get_value(proplist_t dict_win, proplist_t dict_class, proplist_t dict_name,
proplist_t dict_any, proplist_t option, proplist_t default_value,
Bool useGlobalDefault)
{
proplist_t value;
if (dict_win) {
value = PLGetDictionaryEntry(dict_win, option);
if (value)
return value;
}
if (dict_name) {
value = PLGetDictionaryEntry(dict_name, option);
if (value)
return value;
}
if (dict_class) {
value = PLGetDictionaryEntry(dict_class, option);
if (value)
return value;
}
if (!useGlobalDefault)
return NULL;
if (dict_any) {
value = PLGetDictionaryEntry(dict_any, option);
if (value)
return value;
}
return default_value;
}
void
wDefaultFillAttributes(WScreen *scr, char *instance, char *class,
WWindowAttributes *attr, Bool useGlobalDefault)
{
proplist_t value;
proplist_t key1, key2, key3;
proplist_t dw, dc, dn, da;
char buffer[256];
if (class && instance)
key1 = PLMakeString(strcat(strcat(strcpy(buffer,instance),"."),class));
else
key1 = NULL;
if (instance)
key2 = PLMakeString(instance);
else
key2 = NULL;
if (class)
key3 = PLMakeString(class);
else
key3 = NULL;
if (!ANoTitlebar) {
init_wdefaults(scr);
}
PLSetStringCmpHook(NULL);
if (WDWindowAttributes->dictionary) {
dw = key1 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key1) : NULL;
dn = key2 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key2) : NULL;
dc = key3 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key3) : NULL;
if (useGlobalDefault)
da = PLGetDictionaryEntry(WDWindowAttributes->dictionary, AnyWindow);
else
da = NULL;
} else {
dw = NULL;
dn = NULL;
dc = NULL;
da = NULL;
}
if (key1)
PLRelease(key1);
if (key2)
PLRelease(key2);
if (key3)
PLRelease(key3);
/* get the data */
value = get_value(dw, dc, dn, da, ANoTitlebar, No, useGlobalDefault);
if (value)
attr->no_titlebar = getBool(ANoTitlebar, value);
value = get_value(dw, dc, dn, da, ANoResizebar, No, useGlobalDefault);
if (value)
attr->no_resizebar = getBool(ANoResizebar, value);
value = get_value(dw, dc, dn, da, ANoMiniaturizeButton, No, useGlobalDefault);
if (value)
attr->no_miniaturize_button = getBool(ANoMiniaturizeButton, value);
value = get_value(dw, dc, dn, da, ANoCloseButton, No, useGlobalDefault);
if (value)
attr->no_close_button = getBool(ANoCloseButton, value);
value = get_value(dw, dc, dn, da, ANoHideOthers, No, useGlobalDefault);
if (value)
attr->no_hide_others = getBool(ANoHideOthers, value);
value = get_value(dw, dc, dn, da, ANoMouseBindings, No, useGlobalDefault);
if (value)
attr->no_bind_mouse = getBool(ANoMouseBindings, value);
value = get_value(dw, dc, dn, da, ANoKeyBindings, No, useGlobalDefault);
if (value)
attr->no_bind_keys = getBool(ANoKeyBindings, value);
value = get_value(dw, dc, dn, da, ANoAppIcon, No, useGlobalDefault);
if (value)
attr->no_appicon = getBool(ANoAppIcon, value);
value = get_value(dw, dc, dn, da, AKeepOnTop, No, useGlobalDefault);
if (value)
attr->floating = getBool(AKeepOnTop, value);
value = get_value(dw, dc, dn, da, AOmnipresent, No, useGlobalDefault);
if (value)
attr->omnipresent = getBool(AOmnipresent, value);
value = get_value(dw, dc, dn, da, ASkipWindowList, No, useGlobalDefault);
if (value)
attr->skip_window_list = getBool(ASkipWindowList, value);
value = get_value(dw, dc, dn, da, AKeepInsideScreen, No, useGlobalDefault);
if (value)
attr->dont_move_off = getBool(AKeepInsideScreen, value);
value = get_value(dw, dc, dn, da, AUnfocusable, No, useGlobalDefault);
if (value)
attr->no_focusable = getBool(AUnfocusable, value);
value = get_value(dw, dc, dn, da, AAlwaysUserIcon, No, useGlobalDefault);
if (value)
attr->always_user_icon = getBool(AAlwaysUserIcon, value);
value = get_value(dw, dc, dn, da, AStartMiniaturized, No, useGlobalDefault);
if (value)
attr->start_miniaturized = getBool(AStartMiniaturized, value);
value = get_value(dw, dc, dn, da, AStartHidden, No, useGlobalDefault);
if (value)
attr->start_hidden = getBool(AStartHidden, value);
value = get_value(dw, dc, dn, da, ADontSaveSession, No, useGlobalDefault);
if (value)
attr->dont_save_session = getBool(ADontSaveSession, value);
value = get_value(dw, dc, dn, da, AEmulateAppIcon, No, useGlobalDefault);
if (value)
attr->emulate_appicon = getBool(AEmulateAppIcon, value);
/* clean up */
PLSetStringCmpHook(StringCompareHook);
}
proplist_t
get_generic_value(WScreen *scr, char *instance, char *class, proplist_t option,
Bool noDefault)
{
proplist_t value, key, dict;
char buffer[256];
value = NULL;
PLSetStringCmpHook(NULL);
if (class && instance) {
key = PLMakeString(strcat(strcat(strcpy(buffer,instance),"."),class));
dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
PLRelease(key);
if (dict) {
value = PLGetDictionaryEntry(dict, option);
}
}
if (!value && instance) {
key = PLMakeString(instance);
dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
PLRelease(key);
if (dict) {
value = PLGetDictionaryEntry(dict, option);
}
}
if (!value && class) {
key = PLMakeString(class);
dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
PLRelease(key);
if (dict) {
value = PLGetDictionaryEntry(dict, option);
}
}
if (!value && !noDefault) {
dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, AnyWindow);
if (dict) {
value = PLGetDictionaryEntry(dict, option);
}
}
PLSetStringCmpHook(StringCompareHook);
return value;
}
char*
wDefaultGetIconFile(WScreen *scr, char *instance, char *class,
Bool noDefault)
{
proplist_t value;
char *tmp;
if (!ANoTitlebar) {
init_wdefaults(scr);
}
if (!WDWindowAttributes->dictionary)
return NULL;
value = get_generic_value(scr, instance, class, AIcon, noDefault);
if (!value)
return NULL;
tmp = getString(AIcon, value);
return tmp;
}
RImage*
wDefaultGetImage(WScreen *scr, char *winstance, char *wclass)
{
char *file_name;
char *path;
RImage *image;
file_name = wDefaultGetIconFile(scr, winstance, wclass, False);
if (!file_name)
return NULL;
path = FindImage(wPreferences.icon_path, file_name);
if (!path) {
wwarning(_("could not find icon file \"%s\""), file_name);
return NULL;
}
image = RLoadImage(scr->rcontext, path, 0);
if (!image) {
wwarning(_("error loading image file \"%s\""), path, RErrorString);
}
free(path);
image = wIconValidateIconSize(scr, image);
return image;
}
int
wDefaultGetStartWorkspace(WScreen *scr, char *instance, char *class)
{
proplist_t value;
int w, i;
char *tmp;
if (!ANoTitlebar) {
init_wdefaults(scr);
}
if (!WDWindowAttributes->dictionary)
return -1;
value = get_generic_value(scr, instance, class, AStartWorkspace,
False);
if (!value)
return -1;
tmp = getString(AStartWorkspace, value);
if (!tmp || strlen(tmp)==0)
return -1;
if (sscanf(tmp, "%i", &w)!=1) {
w = -1;
for (i=0; i < scr->workspace_count; i++) {
if (strcmp(scr->workspaces[i]->name, tmp)==0) {
w = i;
break;
}
}
} else {
w--;
}
return w;
}
void
wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file)
{
WDDomain *db = WDWindowAttributes;
proplist_t icon_value=NULL, value, attr, key, def_win, def_icon=NULL;
proplist_t dict = db->dictionary;
char *buffer;
int same = 0;
if (!dict) {
dict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
if (dict) {
db->dictionary = dict;
value = PLMakeString(db->path);
PLSetFilename(dict, value);
PLRelease(value);
}
else
return;
}
PLSetStringCmpHook(NULL);
if (instance && class) {
buffer = wmalloc(strlen(instance) + strlen(class) + 2);
strcat(strcat(strcpy(buffer, instance), "."), class);
key = PLMakeString(buffer);
if (PLGetDictionaryEntry(dict, key)==NULL) {
PLRelease(key);
key = PLMakeString(instance);
if (PLGetDictionaryEntry(dict, key)==NULL) {
PLRelease(key);
key = PLMakeString(class);
if (PLGetDictionaryEntry(dict, key)==NULL) {
PLRelease(key);
key = PLMakeString(buffer);
}
}
}
free(buffer);
} else if (instance) {
key = PLMakeString(instance);
} else if (class) {
key = PLMakeString(class);
} else {
key = PLRetain(AnyWindow);
}
if (file) {
value = PLMakeString(file);
icon_value = PLMakeDictionaryFromEntries(AIcon, value, NULL);
PLRelease(value);
if ((def_win = PLGetDictionaryEntry(dict, AnyWindow)) != NULL) {
def_icon = PLGetDictionaryEntry(def_win, AIcon);
}
if (def_icon && !strcmp(PLGetString(def_icon), file))
same = 1;
}
if((attr = PLGetDictionaryEntry(dict, key)) != NULL) {
if (PLIsDictionary(attr)) {
if (icon_value!=NULL && !same)
PLMergeDictionaries(attr, icon_value);
else
PLRemoveDictionaryEntry(attr, AIcon);
}
}
else if (icon_value!=NULL && !same) {
PLInsertDictionaryEntry(dict, key, icon_value);
}
PLSave(dict, YES);
PLRelease(key);
if(icon_value)
PLRelease(icon_value);
PLSetStringCmpHook(StringCompareHook);
}
/* --------------------------- Local ----------------------- */
static int
getBool(proplist_t key, proplist_t value)
{
char *val;
if (!PLIsString(value)) {
wwarning(_("Wrong option format for key \"%s\". Should be %s."),
PLGetString(key), "Boolean");
return 0;
}
val = PLGetString(value);
if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
|| val[0]=='t' || val[0]=='1'))
|| (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
return 1;
} else if ((val[1]=='\0'
&& (val[0]=='n' || val[0]=='N' || val[0]=='F'
|| val[0]=='f' || val[0]=='0'))
|| (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
return 0;
} else {
wwarning(_("can't convert \"%s\" to boolean"), val);
/* We return False if we can't convert to BOOLEAN.
* This is because all options defaults to False.
* -1 is not checked and thus is interpreted as True,
* which is not good.*/
return 0;
}
}
/*
* WARNING: Do not free value returned by this!!
*/
static char*
getString(proplist_t key, proplist_t value)
{
if (!PLIsString(value)) {
wwarning(_("Wrong option format for key \"%s\". Should be %s."),
PLGetString(key), "String");
return NULL;
}
return PLGetString(value);
}

43
src/wdefaults.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMWDEFAULTS_H_
#define WMWDEFAULTS_H_
/* bit flags for the above window attributes */
#define WA_TITLEBAR (1<<0)
#define WA_RESIZABLE (1<<1)
#define WA_CLOSABLE (1<<2)
#define WA_MINIATURIZABLE (1<<3)
#define WA_BROKEN_CLOSE (1<<4)
#define WA_SHADEABLE (1<<5)
#define WA_FOCUSABLE (1<<6)
#define WA_OMNIPRESENT (1<<7)
#define WA_SKIP_WINDOW_LIST (1<<8)
#define WA_FLOATING (1<<9)
#define WA_IGNORE_KEYS (1<<10)
#define WA_IGNORE_MOUSE (1<<11)
#define WA_IGNORE_HIDE_OTHERS (1<<12)
#define WA_NOT_APPLICATION (1<<13)
#define WA_DONT_MOVE_OFF (1<<14)
#endif

2212
src/window.c Normal file

File diff suppressed because it is too large Load Diff

296
src/window.h Normal file
View File

@@ -0,0 +1,296 @@
/*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMWINDOW_H_
#define WMWINDOW_H_
#include <wraster.h>
#include "wconfig.h"
#include "GNUstep.h"
#ifdef MWM_HINTS
# include "motif.h"
#endif
#include "texture.h"
#include "menu.h"
#include "application.h"
/* not defined in my X11 headers */
#ifndef UrgencyHint
#define UrgencyHint (1L << 8)
#endif
#define BORDER_TOP 1
#define BORDER_BOTTOM 2
#define BORDER_LEFT 4
#define BORDER_RIGHT 8
#define BORDER_ALL (1|2|4|8)
#define CLIENT_EVENTS (StructureNotifyMask | PropertyChangeMask\
| EnterWindowMask | LeaveWindowMask | ColormapChangeMask \
| FocusChangeMask)
typedef enum {
WFM_PASSIVE, WFM_NO_INPUT, WFM_LOCALLY_ACTIVE, WFM_GLOBALLY_ACTIVE
} FocusMode;
/*
* window attribute flags.
*
* Note: attributes that should apply to the application as a
* whole should only access the flags from the app->main_window_desc->window_flags
* This is to make sure that the application doesn't have many different
* values for the same option. For example, imagine xfoo, which has
* foo.bar as leader and it a child window named foo.baz. If you set
* StartHidden YES for foo.bar and NO for foo.baz we must *always* guarantee
* that the value that will be used will be that of the leader foo.bar.
* The attributes inspector must always save application wide options
* in the name of the leader window, not the child.
*/
/*
* All flags must have their default values = 0
*/
typedef struct {
/* OpenStep */
unsigned int no_titlebar:1; /* draw titlebar? */
unsigned int no_resizable:1;
unsigned int no_closable:1;
unsigned int no_miniaturizable:1;
/* decorations */
unsigned int no_resizebar:1; /* draw the bottom handle? */
unsigned int no_close_button:1; /* draw a close button? */
unsigned int no_miniaturize_button:1; /* draw an iconify button? */
unsigned int broken_close:1; /* is the close button broken? */
/* ours */
unsigned int kill_close:1; /* can't send WM_DELETE_WINDOW */
unsigned int no_shadeable:1;
unsigned int omnipresent:1;
unsigned int skip_window_list:1;
unsigned int floating:1; /* put in NSFloatingWindowLevel */
unsigned int no_bind_keys:1; /* intercept wm kbd binds
* while window is focused */
unsigned int no_bind_mouse:1; /* intercept mouse events
* on client area while window
* is focused */
unsigned int no_hide_others:1; /* hide window when doing hideothers */
unsigned int no_appicon:1; /* make app icon */
unsigned int dont_move_off:1;
unsigned int no_focusable:1;
unsigned int always_user_icon:1; /* ignore client IconPixmap or
* IconWindow */
unsigned int start_miniaturized:1;
unsigned int start_hidden:1;
unsigned int dont_save_session:1; /* do not save app's state in session */
/*
* emulate_app_icon must be automatically disabled for apps that can
* generate their own appicons and for apps that have no_appicon=1
*/
unsigned int emulate_appicon:1;
} WWindowAttributes;
/*
* Window manager protocols that both the client as we understand.
*/
typedef struct {
unsigned int TAKE_FOCUS:1;
unsigned int SAVE_YOURSELF:1;
unsigned int DELETE_WINDOW:1;
/* WindowMaker specific */
unsigned int MINIATURIZE_WINDOW:1;
} WProtocols;
/*
* Stores client window information. Each client window has it's
* structure created when it's being first mapped.
*/
typedef struct WWindow {
struct WWindow *prev; /* window focus list */
struct WWindow *next;
WScreen *screen_ptr; /* pointer to the screen structure */
WWindowAttributes window_flags; /* window attribute flags */
struct InspectorPanel *inspector; /* pointer to attribute editor panel */
struct WFrameWindow *frame; /* the frame window */
int frame_x, frame_y; /* position of the frame in root*/
struct {
int x, y;
unsigned int width, height; /* original geometry of the window */
} old_geometry; /* (before things like maximize) */
/* client window info */
short old_border_width; /* original border width of client_win*/
Window client_win; /* the window we're managing */
WObjDescriptor client_descriptor; /* dummy descriptor for client */
struct {
int x, y; /* position of *client* relative
* to root */
unsigned int width, height; /* size of the client window */
} client;
XSizeHints *normal_hints; /* WM_NORMAL_HINTS */
XWMHints *wm_hints; /* WM_HINTS (optional) */
char *wm_instance; /* instance of WM_CLASS */
char *wm_class; /* class of WM_CLASS */
GNUstepWMAttributes *wm_gnustep_attr;/* GNUstep window attributes */
int state; /* state as in ICCCM */
Window transient_for; /* WM_TRANSIENT_FOR */
Window group_id; /* the leader window of the group */
Window client_leader; /* WM_CLIENT_LEADER if not
internal_window */
Window main_window; /* main window for the application */
int cmap_window_no;
Window *cmap_windows;
/* protocols */
WProtocols protocols; /* accepted WM_PROTOCOLS */
FocusMode focus_mode; /* type of keyboard input focus */
struct {
/* state flags */
unsigned int mapped:1;
unsigned int focused:1;
unsigned int miniaturized:1;
unsigned int hidden:1;
unsigned int shaded:1;
unsigned int maximized:2;
unsigned int semi_focused:1;
/* window type flags */
unsigned int urgent:1; /* if wm_hints says this is urgent */
#ifdef SHAPE
unsigned int shaped:1;
#endif
/* info flags */
unsigned int buttons_dont_fit:1;
unsigned int rebuild_texture:1;/* the window was resized and
* gradients should be re-rendered */
unsigned int needs_full_repaint:1;/* does a full repaint of the
* window next time it's painted */
unsigned int icon_moved:1; /* icon for this window was moved
* by the user */
unsigned int ignore_next_unmap:1;
unsigned int selected:1; /* multiple window selection */
unsigned int skip_next_animation:1;
unsigned int internal_window:1;
unsigned int changing_workspace:1;
unsigned int inspector_open:1; /* attrib inspector is already open */
unsigned int destroyed:1; /* window was already destroyed */
} flags; /* state of the window */
char *icon_text;
struct WIcon *icon; /* icon info for the window */
int icon_x, icon_y; /* position of the icon */
} WWindow;
typedef struct WSavedState {
int workspace;
int miniaturized;
int shaded;
int hidden;
int use_geometry;
int x, y, w, h;
} WSavedState;
typedef struct WWindowState {
char *instance;
char *class;
char *command;
pid_t pid;
WSavedState *state;
struct WWindowState *next;
} WWindowState;
void wWindowDestroy(WWindow *wwin);
WWindow *wWindowCreate();
#ifdef SHAPE
void wWindowSetShape(WWindow *wwin);
#endif
WWindow *wManageWindow(WScreen *scr, Window window);
void wUnmanageWindow(WWindow *wwin, int restore);
void wWindowFocus(WWindow *wwin);
void wWindowUnfocus(WWindow *wwin);
void wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight);
void wWindowConfigure(WWindow *wwin, int req_x, int req_y,
int req_width, int req_height);
void wWindowMove(WWindow *wwin, int req_x, int req_y);
void wWindowSynthConfigureNotify(WWindow *wwin);
WWindow *wWindowFor(Window window);
void wWindowConfigureBorders(WWindow *wwin);
void wWindowUpdateButtonImages(WWindow *wwin);
void wWindowSaveState(WWindow *wwin);
void wWindowChangeWorkspace(WWindow *wwin, int workspace);
void wWindowSetKeyGrabs(WWindow *wwin);
void wWindowResetMouseGrabs(WWindow *wwin);
WWindow *wManageInternalWindow(WScreen *scr, Window window, Window owner,
char *title, int x, int y,
int width, int height);
void wWindowCheckAttributeSanity(WWindow *wwin, WWindowAttributes *flags);
void wWindowUpdateGNUstepAttr(WWindow *wwin, GNUstepWMAttributes *attr);
void wWindowMap(WWindow *wwin);
Bool wWindowCanReceiveFocus(WWindow *wwin);
#endif

339
src/winmenu.c Normal file
View File

@@ -0,0 +1,339 @@
/* winmenu.c - command menu for windows
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "WindowMaker.h"
#include "actions.h"
#include "menu.h"
#include "funcs.h"
#include "window.h"
#include "client.h"
#include "application.h"
#include "keybind.h"
#include "framewin.h"
#include "workspace.h"
#include "winspector.h"
#include "dialog.h"
#define MC_MAXIMIZE 0
#define MC_MINIATURIZE 1
#define MC_SHADE 2
#define MC_HIDE 3
#define MC_HIDE_OTHERS 4
#define MC_SELECT 5
#define MC_DUMMY_MOVETO 6
#define MC_PROPERTIES 7
#define MC_CLOSE 8
#define MC_KILL 9
/**** Global data ***/
extern Time LastTimestamp;
extern Atom _XA_WM_DELETE_WINDOW;
extern Atom _XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW;
extern WShortKey wKeyBindings[WKBD_LAST];
extern WPreferences wPreferences;
static void
execMenuCommand(WMenu *menu, WMenuEntry *entry)
{
WWindow *wwin = (WWindow*)entry->clientdata;
WApplication *wapp;
CloseWindowMenu(menu->frame->screen_ptr);
switch (entry->order) {
case MC_CLOSE:
/* send delete message */
wClientSendProtocol(wwin, _XA_WM_DELETE_WINDOW, LastTimestamp);
break;
case MC_KILL:
wretain(wwin);
if (wPreferences.dont_confirm_kill
|| wMessageDialog(menu->frame->screen_ptr, _("Kill Application"),
_("This will kill the application.\nAny unsaved changes will be lost.\nPlease confirm."),
_("Yes"), _("No"), NULL)==WAPRDefault) {
if (!wwin->flags.destroyed)
wClientKill(wwin);
}
wrelease(wwin);
break;
case MC_MINIATURIZE:
if (wwin->protocols.MINIATURIZE_WINDOW) {
wClientSendProtocol(wwin, _XA_WINDOWMAKER_WM_MINIATURIZE_WINDOW,
LastTimestamp);
} else {
wIconifyWindow(wwin);
}
break;
case MC_MAXIMIZE:
if (wwin->flags.maximized)
wUnmaximizeWindow(wwin);
else
wMaximizeWindow(wwin, MAX_VERTICAL|MAX_HORIZONTAL);
break;
case MC_SHADE:
if (wwin->flags.shaded)
wUnshadeWindow(wwin);
else
wShadeWindow(wwin);
break;
case MC_SELECT:
wSelectWindow(wwin);
break;
case MC_PROPERTIES:
if (wwin->wm_class || wwin->wm_instance)
wShowInspectorForWindow(wwin);
break;
case MC_HIDE:
wapp = wApplicationOf(wwin->main_window);
wHideApplication(wapp);
break;
case MC_HIDE_OTHERS:
wHideOtherApplications(wwin);
break;
}
}
static void
switchWSCommand(WMenu *menu, WMenuEntry *entry)
{
WWindow *wwin = (WWindow*)entry->clientdata;
if (wwin->flags.selected)
wSelectWindow(wwin);
wWindowChangeWorkspace(wwin, entry->order);
}
static void
updateWorkspaceMenu(WMenu *menu)
{
WScreen *scr = menu->frame->screen_ptr;
char title[MAX_WORKSPACENAME_WIDTH+1];
int i;
if (!menu)
return;
for (i=0; i<scr->workspace_count; i++) {
if (i < menu->entry_no) {
if (strcmp(menu->entries[i]->text,scr->workspaces[i]->name)!=0) {
free(menu->entries[i]->text);
strcpy(title, scr->workspaces[i]->name);
menu->entries[i]->text = wstrdup(title);
menu->flags.realized = 0;
}
} else {
strcpy(title, scr->workspaces[i]->name);
wMenuAddCallback(menu, title, switchWSCommand, NULL);
menu->flags.realized = 0;
}
}
if (!menu->flags.realized)
wMenuRealize(menu);
}
static WMenu*
makeWorkspaceMenu(WScreen *scr)
{
WMenu *menu;
menu = wMenuCreate(scr, NULL, False);
if (!menu)
wwarning(_("could not create workspace submenu for window menu"));
updateWorkspaceMenu(menu);
return menu;
}
static WMenu*
createWindowMenu(WScreen *scr)
{
WMenu *menu;
KeyCode kcode;
WMenuEntry *entry;
char *tmp;
menu = wMenuCreate(scr, NULL, False);
/*
* Warning: If you make some change that affects the order of the
* entries, you must update the command #defines in the top of
* this file.
*/
entry = wMenuAddCallback(menu, _("(Un)Maximize"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_MAXIMIZE].keycode!=0) {
kcode = wKeyBindings[WKBD_MAXIMIZE].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("Miniaturize"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_MINIATURIZE].keycode!=0) {
kcode = wKeyBindings[WKBD_MINIATURIZE].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("(Un)Shade"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_SHADE].keycode!=0) {
kcode = wKeyBindings[WKBD_SHADE].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("Hide"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_HIDE].keycode!=0) {
kcode = wKeyBindings[WKBD_HIDE].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("Hide Others"), execMenuCommand, NULL);
entry = wMenuAddCallback(menu, _("Select"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_SELECT].keycode!=0) {
kcode = wKeyBindings[WKBD_SELECT].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("Move To"), NULL, NULL);
scr->workspace_submenu = makeWorkspaceMenu(scr);
if (scr->workspace_submenu)
wMenuEntrySetCascade(menu, entry, scr->workspace_submenu);
entry = wMenuAddCallback(menu, _("Attributes..."), execMenuCommand, NULL);
entry = wMenuAddCallback(menu, _("Close"), execMenuCommand, NULL);
if (wKeyBindings[WKBD_CLOSE].keycode!=0) {
kcode = wKeyBindings[WKBD_CLOSE].keycode;
if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))))
entry->rtext = wstrdup(tmp);
}
entry = wMenuAddCallback(menu, _("Kill"), execMenuCommand, NULL);
return menu;
}
void
CloseWindowMenu(WScreen *scr)
{
if (scr->window_menu && scr->window_menu->flags.mapped)
wMenuUnmap(scr->window_menu);
}
void
OpenWindowMenu(WWindow *wwin, int x, int y, int keyboard)
{
WMenu *menu;
WApplication *wapp = wApplicationOf(wwin->main_window);
WScreen *scr = wwin->screen_ptr;
int i;
if (!scr->window_menu) {
scr->window_menu = createWindowMenu(scr);
} else {
updateWorkspaceMenu(scr->workspace_submenu);
}
menu = scr->window_menu;
if (menu->flags.mapped) {
wMenuUnmap(menu);
if (menu->entries[0]->clientdata==wwin) {
return;
}
}
wMenuSetEnabled(menu, MC_HIDE, wapp!=NULL
&& !wapp->main_window_desc->window_flags.no_appicon);
wMenuSetEnabled(menu, MC_CLOSE,
(wwin->protocols.DELETE_WINDOW
&& !wwin->window_flags.no_closable));
wMenuSetEnabled(menu, MC_MINIATURIZE, !wwin->window_flags.no_miniaturizable);
wMenuSetEnabled(menu, MC_SHADE, !wwin->window_flags.no_shadeable);
wMenuSetEnabled(menu, MC_DUMMY_MOVETO, !wwin->window_flags.omnipresent);
if ((wwin->wm_class || wwin->wm_instance) && !wwin->flags.inspector_open) {
wMenuSetEnabled(menu, MC_PROPERTIES, True);
} else {
wMenuSetEnabled(menu, MC_PROPERTIES, False);
}
/* set the client data of the entries to the window */
for (i = 0; i < menu->entry_no; i++) {
menu->entries[i]->clientdata = wwin;
}
for (i = 0; i < scr->workspace_submenu->entry_no; i++) {
scr->workspace_submenu->entries[i]->clientdata = wwin;
if (i == scr->current_workspace) {
wMenuSetEnabled(scr->workspace_submenu, i, False);
} else {
wMenuSetEnabled(scr->workspace_submenu, i, True);
}
}
if (!menu->flags.realized)
wMenuRealize(menu);
x -= menu->frame->core->width/2;
if (x + menu->frame->core->width > wwin->frame_x+wwin->frame->core->width)
x = wwin->frame_x+wwin->frame->core->width - menu->frame->core->width;
if (x < wwin->frame_x)
x = wwin->frame_x;
if (!wwin->flags.internal_window)
wMenuMapAt(menu, x, y, keyboard);
}

1370
src/winspector.c Normal file

File diff suppressed because it is too large Load Diff

97
src/winspector.h Normal file
View File

@@ -0,0 +1,97 @@
/* winspector.h - window attribute inspector header file
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WINSPECTOR_H_
#define WINSPECTOR_H_
#include "window.h"
typedef struct InspectorPanel {
struct InspectorPanel *nextPtr;
WWindow *frame;
WWindow *inspected; /* the window that's being inspected */
WMWindow *win;
Window parent;
/* common stuff */
WMButton *revertBtn;
WMButton *applyBtn;
WMButton *saveBtn;
WMPopUpButton *pagePopUp;
/* first page. general stuff */
WMFrame *specFrm;
WMButton *instRb;
WMButton *clsRb;
WMButton *bothRb;
WMButton *defaultRb;
WMLabel *specLbl;
/* second page. attributes */
WMFrame *attrFrm;
WMButton *attrChk[8];
/* 3rd page. more attributes */
WMFrame *moreFrm;
WMButton *moreChk[7];
WMLabel *moreLbl;
/* 4th page. icon and workspace */
WMFrame *iconFrm;
WMLabel *iconLbl;
WMLabel *fileLbl;
WMTextField *fileText;
WMButton *alwChk;
/*
WMButton *updateIconBtn;
*/
WMButton *browseIconBtn;
WMFrame *wsFrm;
WMButton *curRb;
WMButton *setRb;
WMTextField *wsText;
/* 5th page. application wide attributes */
WMFrame *appFrm;
WMButton *appChk[2];
unsigned int done:1;
unsigned int destroyed:1;
unsigned int choosingIcon:1;
} InspectorPanel;
void wShowInspectorForWindow(WWindow *wwin);
void wDestroyInspectorPanels();
#endif

80
src/wmnotdef.h Normal file
View File

@@ -0,0 +1,80 @@
/*
* WindowMaker external notification definitions
*
* Copyright (c) 1998 Peter Bentley (pete@sorted.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMNOTDEF_H_
#define WMNOTDEF_H_
/* Make a notification ID from a category and an 'event' */
#define WMN_MAKE_ID(cat, ev) ( ((cat)<<4) | (ev) )
/* Split an ID into category and 'event' */
#define WMN_CATEGORY_OF( id ) ( ((id) & 0x00f0) >> 4 )
#define WMN_EVENT_OF( id ) ( (id) & 0x000f )
/* Make notification mask from categories or ids */
#define WMN_CATEGORY_TO_MASK( cat ) ( 0x0001 << ( cat ))
#define WMN_ID_TO_MASK( id ) WMN_CATEGORY_TO_MASK( WMN_CATEGORY_OF( id ))
/* Constant and mask for "all events in all categories" */
#define WMN_NOTIFY_ALL 0x0000
#define WMN_MASK_ALL 0x00ff
/* Extract the notify type from an int or long which may have other data */
#define WMN_GET_VALUE( val ) ( (val) & 0x00ff )
/* Notification categories */
#define WMN_CAT_SYSTEM 0x0001
#define WMN_CAT_WORKSPACE 0x0002
#define WMN_CAT_APPLICATION 0x0003
#define WMN_CAT_WINOP 0x0004
/* System notifications */
#define WMN_SYS_START WMN_MAKE_ID( WMN_CAT_SYSTEM, 0x0001 )
#define WMN_SYS_QUIT WMN_MAKE_ID( WMN_CAT_SYSTEM, 0x0002 )
#define WMN_SYS_RESTART WMN_MAKE_ID( WMN_CAT_SYSTEM, 0x0003 )
#define WMN_SYS_DEFLOAD WMN_MAKE_ID( WMN_CAT_SYSTEM, 0x0004 )
/* Workspace notifications */
#define WMN_WS_CHANGE WMN_MAKE_ID( WMN_CAT_WORKSPACE, 0x0001 )
#define WMN_WS_CREATE WMN_MAKE_ID( WMN_CAT_WORKSPACE, 0x0002 )
#define WMN_WS_DESTROY WMN_MAKE_ID( WMN_CAT_WORKSPACE, 0x0003 )
#define WMN_WS_RENAME WMN_MAKE_ID( WMN_CAT_WORKSPACE, 0x0004 )
/* Application notifications */
#define WMN_APP_START WMN_MAKE_ID( WMN_CAT_APPLICATION, 0x0001 )
#define WMN_APP_EXIT WMN_MAKE_ID( WMN_CAT_APPLICATION, 0x0002 )
/* Window operation notifications */
#define WMN_WIN_MAXIMIZE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0001 )
#define WMN_WIN_UNMAXIMIZE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0002 )
#define WMN_WIN_SHADE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0003 )
#define WMN_WIN_UNSHADE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0004 )
#define WMN_WIN_ICONIFY WMN_MAKE_ID( WMN_CAT_WINOP, 0x0005 )
#define WMN_WIN_DEICONIFY WMN_MAKE_ID( WMN_CAT_WINOP, 0x0006 )
#define WMN_WIN_MOVE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0007 )
#define WMN_WIN_RESIZE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0008 )
#define WMN_WIN_HIDE WMN_MAKE_ID( WMN_CAT_WINOP, 0x0009 )
#define WMN_WIN_UNHIDE WMN_MAKE_ID( WMN_CAT_WINOP, 0x000a )
#define WMN_WIN_FOCUS WMN_MAKE_ID( WMN_CAT_WINOP, 0x000a )
#define WMN_WIN_UNFOCUS WMN_MAKE_ID( WMN_CAT_WINOP, 0x000b )
#endif /*WMNOTDEF_H_*/

139
src/wmnotify.c Normal file
View File

@@ -0,0 +1,139 @@
/*
* WindowMaker external notification support
*
* Copyright (c) 1998 Peter Bentley (pete@sorted.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
#include "properties.h"
#include "wmnotify.h"
#ifdef WMNOTIFY
#define DEBUG
extern Atom _XA_WINDOWMAKER_NOTIFY;
static LinkedList *wNotifyWindows=NULL;
typedef struct WNotifyClient
{
Window not_win; /* Id of window to send notify events to */
int not_mask; /* Mask of desired notifications */
} WNotifyClient;
void wNotify( int id, int a1, int a2 )
{
}
void wNotifyWin( int id, WWindow *wwin )
{
XEvent event;
LinkedList *list;
WNotifyClient *clnt;
int count = 0, mask = WMN_ID_TO_MASK( id );
event.xclient.type = ClientMessage;
event.xclient.message_type = _XA_WINDOWMAKER_NOTIFY;
event.xclient.format = 32;
event.xclient.display = dpy;
event.xclient.data.l[0] = id;
if( wwin )
event.xclient.data.l[1] = wwin->client_win; /* XXX */
else
event.xclient.data.l[1] = 0;
event.xclient.data.l[2] = 0;
event.xclient.data.l[3] = 0;
for( list = wNotifyWindows; list; list = list->tail )
{
clnt = list->head;
if( clnt->not_mask & mask )
{
#ifdef DEBUG
printf( "Send event %d to 0x%x\n", id, (int) clnt->not_win );
#endif
event.xclient.window = clnt->not_win;
XSendEvent(dpy, clnt->not_win, False, NoEventMask, &event);
count++;
}
}
if( count )
XFlush(dpy);
}
int wNotifySet(Window window)
{
int mask;
WNotifyClient *clnt;
if( PropGetNotifyMask( window, &mask )) {
wNotifyClear( window ); /* Remove any current mask */
#ifdef DEBUG
printf( "Setting notify mask for window 0x%x to 0x%02x\n",
(int) window, mask );
#endif
clnt = wmalloc( sizeof( WNotifyClient ));
if( clnt )
{
clnt->not_win = window;
clnt->not_mask = mask;
wNotifyWindows = list_cons( clnt, wNotifyWindows );
return True;
}
}
return False;
}
int wNotifyClear(Window window)
{
LinkedList *list;
WNotifyClient *clnt;
for( list = wNotifyWindows; list; list = list->tail )
{
clnt = list->head;
if( clnt->not_win == window )
{
#ifdef DEBUG
printf( "Clearing notify mask for window 0x%x (was 0x%02x)\n",
(int) clnt->not_win, clnt->not_mask );
#endif
wNotifyWindows = list_remove_elem( wNotifyWindows, clnt );
free( clnt );
return True;
}
}
return False;
}
#endif /* WMNOTIFY */

40
src/wmnotify.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* WindowMaker external notification support
*
* Copyright (c) 1998 Peter Bentley (pete@sorted.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMNOTIFY_H_
#define WMNOTIFY_H_
#ifndef WMNOTIFY
#define wNotify( id, a1, a2 )
#define wNotifyWin( id, wwin )
#else /* WMNOTIFY */
#include "wmnotdef.h"
void wNotify( int id, int a1, int a2 );
void wNotifyWin( int id, WWindow *wwin );
int wNotifySet(Window window);
int wNotifyClear(Window window);
#endif /* WMNOTIFY */
#endif /*WMNOTIFY_H_*/

58
src/wmsound.c Normal file
View File

@@ -0,0 +1,58 @@
#include "wconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xproto.h>
#include "WindowMaker.h"
#include "wmsound.h"
#ifdef WMSOUND
Window soundServer;
XEvent sound_event;
extern WPreferences wPreferences;
extern Atom _XA_WINDOWMAKER_WM_FUNCTION;
void
wSoundServerGrab(char *name, Window window)
{
if(soundServer==None && name!=NULL && strcmp(name,"WMSoundServer")==0) {
soundServer = window;
}
}
void
wSoundInit(Display *dpy)
{
soundServer = 0;
sound_event.xclient.type = ClientMessage;
sound_event.xclient.message_type = _XA_WINDOWMAKER_WM_FUNCTION;
sound_event.xclient.format = 32;
sound_event.xclient.display = dpy;
}
void
wSoundPlay(long event_sound)
{
if(soundServer!=None && !wPreferences.no_sound) {
sound_event.xclient.window = soundServer;
sound_event.xclient.data.l[0] = event_sound;
if (XSendEvent(dpy, soundServer, False,
NoEventMask, &sound_event)==BadWindow) {
soundServer = None;
return;
} else {
XFlush(dpy);
}
}
}
#endif /* WMSOUND */

51
src/wmsound.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* WMSound Server
*
* Copyright (c) 1997 Anthony P. Quinn
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMSOUND_H_
#define WMSOUND_H_
#define WMSOUND_SHADE 1001
#define WMSOUND_UNSHADE 1002
#define WMSOUND_MAXIMIZE 1003
#define WMSOUND_UNMAXIMIZE 1004
#define WMSOUND_ICONIFY 1005
#define WMSOUND_DEICONIFY 1006
#define WMSOUND_HIDE 1007
#define WMSOUND_UNHIDE 1008
#define WMSOUND_APPSTART 1009
#define WMSOUND_APPEXIT 1010
#if 0
/* don't delete this */
extern WWindow *wSoundServer;
extern Atom WSStartup, WSShade, WSUnshade, WSShutdown;
extern Atom WSMaximize, WSUnmaximize, WSIconify, WSUniconify, WSAppStart;
extern Atom WSHide, WSUnhide, WSAppExit;
extern WApplication *wSoundApp;
#endif
void wSoundPlay(long event_sound);
void wSoundInit(Display *dpy);
void wSoundServerGrab(char *name, Window window);
#endif /*WMSOUND_H_*/

615
src/workspace.c Normal file
View File

@@ -0,0 +1,615 @@
/* workspace.c- Workspace management
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include "WindowMaker.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
#include "icon.h"
#include "funcs.h"
#include "menu.h"
#include "application.h"
#include "dock.h"
#include "actions.h"
#include "workspace.h"
#include "appicon.h"
#include <proplist.h>
extern WPreferences wPreferences;
extern XContext wWinContext;
static proplist_t dWorkspaces=NULL;
static proplist_t dClip, dName;
static void
make_keys()
{
if (dWorkspaces!=NULL)
return;
dWorkspaces = PLMakeString("Workspaces");
dName = PLMakeString("Name");
dClip = PLMakeString("Clip");
}
void
wWorkspaceMake(WScreen *scr, int count)
{
while (count>0) {
wWorkspaceNew(scr);
count--;
}
}
int
wWorkspaceNew(WScreen *scr)
{
WWorkspace *wspace, **list;
int i;
if (scr->workspace_count < MAX_WORKSPACES) {
scr->workspace_count++;
wspace = wmalloc(sizeof(WWorkspace));
wspace->name = wmalloc(strlen(_("Workspace %i"))+8);
sprintf(wspace->name, _("Workspace %i"), scr->workspace_count);
if (!wPreferences.flags.noclip) {
wspace->clip = wDockCreate(scr, WM_CLIP);
} else
wspace->clip = NULL;
list = wmalloc(sizeof(WWorkspace*)*scr->workspace_count);
for (i=0; i<scr->workspace_count-1; i++) {
list[i] = scr->workspaces[i];
}
list[i] = wspace;
free(scr->workspaces);
scr->workspaces = list;
wWorkspaceMenuUpdate(scr, scr->workspace_menu);
wWorkspaceMenuUpdate(scr, scr->clip_ws_menu);
return scr->workspace_count-1;
}
return -1;
}
void
wWorkspaceDelete(WScreen *scr, int workspace)
{
WWindow *tmp;
WWorkspace **list;
int i, j;
if (workspace<=0)
return;
/* verify if workspace is in use by some window */
tmp = scr->focused_window;
while (tmp) {
if (tmp->frame->workspace==workspace)
return;
tmp = tmp->prev;
}
if (!wPreferences.flags.noclip) {
wDockDestroy(scr->workspaces[workspace]->clip);
scr->workspaces[workspace]->clip = NULL;
}
list = wmalloc(sizeof(WWorkspace*)*(scr->workspace_count-1));
j = 0;
for (i=0; i<scr->workspace_count; i++) {
if (i!=workspace)
list[j++] = scr->workspaces[i];
else {
if (scr->workspaces[i]->name)
free(scr->workspaces[i]->name);
free(scr->workspaces[i]);
}
}
free(scr->workspaces);
scr->workspaces = list;
scr->workspace_count--;
/* update menu */
wWorkspaceMenuUpdate(scr, scr->workspace_menu);
/* clip workspace menu */
wWorkspaceMenuUpdate(scr, scr->clip_ws_menu);
/* update also window menu */
if (scr->workspace_submenu) {
WMenu *menu = scr->workspace_submenu;
i = menu->entry_no;
while (i>scr->workspace_count)
wMenuRemoveItem(menu, --i);
wMenuRealize(menu);
}
/* and clip menu */
if (scr->clip_submenu) {
WMenu *menu = scr->clip_submenu;
i = menu->entry_no;
while (i>scr->workspace_count)
wMenuRemoveItem(menu, --i);
wMenuRealize(menu);
}
}
void
wWorkspaceChange(WScreen *scr, int workspace)
{
if (workspace != scr->current_workspace) {
wWorkspaceForceChange(scr, workspace);
}
}
void
wWorkspaceForceChange(WScreen *scr, int workspace)
{
WWindow *tmp, *foc=NULL;
#ifdef EXPERIMENTAL
WWorkspaceTexture *wsback;
#endif
if (workspace >= MAX_WORKSPACES || workspace < 0)
return;
#ifdef EXPERIMENTAL
/* update the background for the workspace */
if (workspace < scr->wspaceTextureCount
&& scr->wspaceTextures[workspace]) {
wsback = scr->wspaceTextures[workspace];
} else {
/* check if the previous workspace used the default background */
if (scr->current_workspace < 0
|| scr->current_workspace >= scr->wspaceTextureCount
|| scr->wspaceTextures[scr->current_workspace]==NULL) {
wsback = NULL;
} else {
wsback = scr->defaultTexure;
}
}
if (wsback) {
if (wsback->pixmap!=None) {
XSetWindowBackgroundPixmap(dpy, scr->root_win, wsback->pixmap);
} else {
XSetWindowBackground(dpy, scr->root_win, wsback->solid);
}
XClearWindow(dpy, scr->root_win);
XFlush(dpy);
}
#endif /* EXPERIMENTAL */
if (workspace > scr->workspace_count-1) {
wWorkspaceMake(scr, workspace - scr->workspace_count + 1);
}
wClipUpdateForWorkspaceChange(scr, workspace);
scr->current_workspace = workspace;
wWorkspaceMenuUpdate(scr, scr->workspace_menu);
wWorkspaceMenuUpdate(scr, scr->clip_ws_menu);
if ((tmp = scr->focused_window)!= NULL) {
while (tmp) {
if (tmp->frame->workspace!=workspace && !tmp->flags.selected) {
/* unmap windows not on this workspace */
if ((tmp->flags.mapped||tmp->flags.shaded)
&& !tmp->window_flags.omnipresent
&& !tmp->flags.changing_workspace) {
XUnmapWindow(dpy, tmp->frame->core->window);
tmp->flags.mapped = 0;
}
/* also unmap miniwindows not on this workspace */
if (tmp->flags.miniaturized &&
!tmp->window_flags.omnipresent && tmp->icon) {
if (!wPreferences.sticky_icons) {
XUnmapWindow(dpy, tmp->icon->core->window);
tmp->icon->mapped = 0;
} else {
tmp->icon->mapped = 1;
/* Why is this here? -Alfredo */
XMapWindow(dpy, tmp->icon->core->window);
}
}
/* update current workspace of omnipresent windows */
if (tmp->window_flags.omnipresent) {
WApplication *wapp = wApplicationOf(tmp->main_window);
tmp->frame->workspace = workspace;
if (wapp) {
wapp->last_workspace = workspace;
}
}
} else {
/* change selected windows' workspace */
if (tmp->flags.selected) {
wWindowChangeWorkspace(tmp, workspace);
if (!tmp->flags.miniaturized) {
foc = tmp;
}
} else {
if (!tmp->flags.hidden) {
if (!(tmp->flags.mapped || tmp->flags.miniaturized)) {
/* remap windows that are on this workspace */
XMapWindow(dpy, tmp->frame->core->window);
if (!foc)
foc = tmp;
if (!tmp->flags.shaded)
tmp->flags.mapped = 1;
}
/* Also map miniwindow if not omnipresent */
if (!wPreferences.sticky_icons &&
tmp->flags.miniaturized &&
!tmp->window_flags.omnipresent && tmp->icon) {
tmp->icon->mapped = 1;
XMapWindow(dpy, tmp->icon->core->window);
}
}
}
}
tmp = tmp->prev;
}
if (scr->focused_window->flags.mapped) {
foc = scr->focused_window;
}
if (wPreferences.focus_mode == WKF_CLICK) {
wSetFocusTo(scr, foc);
} else {
unsigned int mask;
int foo;
Window bar, win;
WWindow *tmp;
tmp = NULL;
if (XQueryPointer(dpy, scr->root_win, &bar, &win,
&foo, &foo, &foo, &foo, &mask)) {
tmp = wWindowFor(win);
}
if (!tmp && wPreferences.focus_mode == WKF_SLOPPY) {
wSetFocusTo(scr, foc);
} else {
wSetFocusTo(scr, tmp);
}
}
}
/* We need to always arrange icons when changing workspace, even if
* no autoarrange icons, because else the icons in different workspaces
* can be superposed.
* This can be avoided if appicons are also workspace specific.
*/
if (!wPreferences.sticky_icons)
wArrangeIcons(scr, False);
if (scr->dock)
wAppIconPaint(scr->dock->icon_array[0]);
if (scr->clip_icon) {
if (scr->workspaces[workspace]->clip->auto_collapse) {
/* to handle enter notify. This will also */
XUnmapWindow(dpy, scr->clip_icon->icon->core->window);
XMapWindow(dpy, scr->clip_icon->icon->core->window);
} else {
wClipIconPaint(scr->clip_icon);
}
}
}
static void
switchWSCommand(WMenu *menu, WMenuEntry *entry)
{
wWorkspaceChange(menu->frame->screen_ptr, (int)entry->clientdata);
}
static void
deleteWSCommand(WMenu *menu, WMenuEntry *entry)
{
wWorkspaceDelete(menu->frame->screen_ptr,
menu->frame->screen_ptr->workspace_count-1);
}
static void
newWSCommand(WMenu *menu, WMenuEntry *foo)
{
int ws;
ws = wWorkspaceNew(menu->frame->screen_ptr);
/* autochange workspace*/
if (ws>=0)
wWorkspaceChange(menu->frame->screen_ptr, ws);
/*
if (ws<9) {
int kcode;
if (wKeyBindings[WKBD_WORKSPACE1+ws]) {
kcode = wKeyBindings[WKBD_WORKSPACE1+ws]->keycode;
entry->rtext =
wstrdup(XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)));
}
}*/
}
static char*
cropline(char *line)
{
char *start, *end;
if (strlen(line)==0)
return line;
start = line;
end = &(line[strlen(line)])-1;
while (isspace(*line) && *line!=0) line++;
while (isspace(*end) && end!=line) {
*end=0;
end--;
}
return line;
}
void
wWorkspaceRename(WScreen *scr, int workspace, char *name)
{
char buf[MAX_WORKSPACENAME_WIDTH+1];
char *tmp;
if (workspace >= scr->workspace_count)
return;
/* trim white spaces */
tmp = cropline(name);
if (strlen(tmp)==0) {
sprintf(buf, _("Workspace %i"), workspace+1);
} else {
strncpy(buf, tmp, MAX_WORKSPACENAME_WIDTH);
}
buf[MAX_WORKSPACENAME_WIDTH] = 0;
/* update workspace */
free(scr->workspaces[workspace]->name);
scr->workspaces[workspace]->name = wstrdup(buf);
if (scr->clip_ws_menu) {
if (strcmp(scr->clip_ws_menu->entries[workspace+2]->text, buf)!=0) {
free(scr->clip_ws_menu->entries[workspace+2]->text);
scr->clip_ws_menu->entries[workspace+2]->text = wstrdup(buf);
wMenuRealize(scr->clip_ws_menu);
}
}
if (scr->workspace_menu) {
if (strcmp(scr->workspace_menu->entries[workspace+2]->text, buf)!=0) {
free(scr->workspace_menu->entries[workspace+2]->text);
scr->workspace_menu->entries[workspace+2]->text = wstrdup(buf);
wMenuRealize(scr->workspace_menu);
}
}
UpdateSwitchMenuWorkspace(scr, workspace);
if (scr->clip_icon)
wClipIconPaint(scr->clip_icon);
}
/* callback for when menu entry is edited */
static void
onMenuEntryEdited(WMenu *menu, WMenuEntry *entry)
{
char *tmp;
tmp = entry->text;
wWorkspaceRename(menu->frame->screen_ptr, (int)entry->clientdata, tmp);
}
WMenu*
wWorkspaceMenuMake(WScreen *scr, Bool titled)
{
WMenu *wsmenu;
wsmenu = wMenuCreate(scr, titled ? _("Workspaces") : NULL, False);
if (!wsmenu) {
wwarning(_("could not create Workspace menu"));
return NULL;
}
/* callback to be called when an entry is edited */
wsmenu->on_edit = onMenuEntryEdited;
wMenuAddCallback(wsmenu, _("New"), newWSCommand, NULL);
wMenuAddCallback(wsmenu, _("Destroy Last"), deleteWSCommand, NULL);
return wsmenu;
}
void
wWorkspaceMenuUpdate(WScreen *scr, WMenu *menu)
{
int i, ws;
char title[MAX_WORKSPACENAME_WIDTH+1];
WMenuEntry *entry;
int tmp;
if (!menu)
return;
if (menu->entry_no < scr->workspace_count+2) {
/* new workspace(s) added */
i = scr->workspace_count-(menu->entry_no-2);
ws = menu->entry_no - 2;
while (i>0) {
strcpy(title, scr->workspaces[ws]->name);
entry = wMenuAddCallback(menu, title, switchWSCommand, (void*)ws);
entry->flags.indicator = 1;
entry->flags.editable = 1;
i--;
ws++;
}
} else if (menu->entry_no > scr->workspace_count+2) {
/* removed workspace(s) */
for (i = menu->entry_no-1; i >= scr->workspace_count+2; i--) {
wMenuRemoveItem(menu, i);
}
}
wMenuRealize(menu);
for (i=0; i<scr->workspace_count; i++) {
menu->entries[i+2]->flags.indicator_on = 0;
}
menu->entries[scr->current_workspace+2]->flags.indicator_on = 1;
/* don't let user destroy current workspace */
if (scr->current_workspace == scr->workspace_count-1) {
wMenuSetEnabled(menu, 1, False);
} else {
wMenuSetEnabled(menu, 1, True);
}
tmp = menu->frame->top_width + 5;
/* if menu got unreachable, bring it to a visible place */
if (menu->frame_x < tmp - (int)menu->frame->core->width)
wMenuMove(menu, tmp - (int)menu->frame->core->width, menu->frame_y, False);
wMenuPaint(menu);
}
void
wWorkspaceSaveState(WScreen *scr, proplist_t old_state)
{
proplist_t parr, pstr;
proplist_t wks_state, old_wks_state;
proplist_t foo, bar;
int i;
make_keys();
old_wks_state = PLGetDictionaryEntry(old_state, dWorkspaces);
parr = PLMakeArrayFromElements(NULL);
for (i=0; i < scr->workspace_count; i++) {
pstr = PLMakeString(scr->workspaces[i]->name);
wks_state = PLMakeDictionaryFromEntries(dName, pstr, NULL);
PLRelease(pstr);
if (!wPreferences.flags.noclip) {
pstr = wClipSaveWorkspaceState(scr, i);
PLInsertDictionaryEntry(wks_state, dClip, pstr);
PLRelease(pstr);
} else if (old_wks_state!=NULL) {
if ((foo = PLGetArrayElement(old_wks_state, i))!=NULL) {
if ((bar = PLGetDictionaryEntry(foo, dClip))!=NULL) {
PLInsertDictionaryEntry(wks_state, dClip, bar);
}
}
}
PLAppendArrayElement(parr, wks_state);
PLRelease(wks_state);
}
PLInsertDictionaryEntry(scr->session_state, dWorkspaces, parr);
PLRelease(parr);
}
void
wWorkspaceRestoreState(WScreen *scr)
{
proplist_t parr, pstr, wks_state;
proplist_t clip_state;
int i, wscount;
make_keys();
parr = PLGetDictionaryEntry(scr->session_state, dWorkspaces);
if (!parr)
return;
wscount = scr->workspace_count;
for (i=0; i < PLGetNumberOfElements(parr); i++) {
wks_state = PLGetArrayElement(parr, i);
if (PLIsDictionary(wks_state))
pstr = PLGetDictionaryEntry(wks_state, dName);
else
pstr = wks_state;
if (i >= scr->workspace_count)
wWorkspaceNew(scr);
if (scr->workspace_menu) {
free(scr->workspace_menu->entries[i+2]->text);
scr->workspace_menu->entries[i+2]->text = wstrdup(PLGetString(pstr));
scr->workspace_menu->flags.realized = 0;
}
free(scr->workspaces[i]->name);
scr->workspaces[i]->name = wstrdup(PLGetString(pstr));
if (!wPreferences.flags.noclip) {
clip_state = PLGetDictionaryEntry(wks_state, dClip);
if (scr->workspaces[i]->clip)
wDockDestroy(scr->workspaces[i]->clip);
scr->workspaces[i]->clip = wDockRestoreState(scr, clip_state,
WM_CLIP);
if (i>0)
wDockHideIcons(scr->workspaces[i]->clip);
}
}
}

50
src/workspace.h Normal file
View File

@@ -0,0 +1,50 @@
/* workspace.c- Workspace management
*
* WindowMaker window manager
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef WMWORKSPACE_H_
#define WMWORKSPACE_H_
typedef struct WWorkspace {
char *name;
struct WDock *clip;
} WWorkspace;
void wWorkspaceMake(WScreen *scr, int count);
int wWorkspaceNew(WScreen *scr);
void wWorkspaceDeleteLast(WScreen *scr);
void wWorkspaceChange(WScreen *scr, int workspace);
void wWorkspaceForceChange(WScreen *scr, int workspace);
WMenu *wWorkspaceMenuMake(WScreen *scr, Bool titled);
void wWorkspaceMenuUpdate(WScreen *scr, WMenu *menu);
void wWorkspaceMenuEdit(WScreen *scr);
void wWorkspaceSaveState(WScreen *scr, proplist_t old_state);
void wWorkspaceRestoreState(WScreen *scr);
void wWorkspaceRename(WScreen *scr, int workspace, char *name);
#endif

297
src/xmodifier.c Normal file
View File

@@ -0,0 +1,297 @@
/* Grok X modifier mappings for shortcuts.
Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
The copyright(s) from the original XEmacs code are included below.
Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
/* The event_stream interface for X11 with Xt, and/or tty frames.
Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Copyright (C) 1995 Sun Microsystems, Inc.
Copyright (C) 1996 Ben Wing.
This file is part of XEmacs.
XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "wconfig.h"
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include "WUtil.h"
extern Display *dpy;
/************************************************************************/
/* keymap handling */
/************************************************************************/
/* X bogusly doesn't define the interpretations of any bits besides
ModControl, ModShift, and ModLock; so the Interclient Communication
Conventions Manual says that we have to bend over backwards to figure
out what the other modifier bits mean. According to ICCCM:
- Any keycode which is assigned ModControl is a "control" key.
- Any modifier bit which is assigned to a keycode which generates Meta_L
or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
etc.
- Any keypress event which contains ModControl in its state should be
interpreted as a "control" character.
- Any keypress event which contains a modifier bit in its state which is
generated by a keycode whose corresponding keysym is Meta_L or Meta_R
should be interpreted as a "meta" character. Likewise for Super, Hyper,
etc.
- It is illegal for a keysym to be associated with more than one modifier
bit.
This means that the only thing that emacs can reasonably interpret as a
"meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
one of the modifier bits Mod1-Mod5.
Unfortunately, many keyboards don't have Meta keys in their default
configuration. So, if there are no Meta keys, but there are "Alt" keys,
emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
mean "Symbol," but that just confused the hell out of way too many people).
This works with the default configurations of the 19 keyboard-types I've
checked.
Emacs detects keyboard configurations which violate the above rules, and
prints an error message on the standard-error-output. (Perhaps it should
use a pop-up-window instead.)
*/
static int MetaMask, HyperMask, SuperMask, AltMask, ModeMask;
static const char *
index_to_name (int indice)
{
switch (indice)
{
case ShiftMapIndex: return "ModShift";
case LockMapIndex: return "ModLock";
case ControlMapIndex: return "ModControl";
case Mod1MapIndex: return "Mod1";
case Mod2MapIndex: return "Mod2";
case Mod3MapIndex: return "Mod3";
case Mod4MapIndex: return "Mod4";
case Mod5MapIndex: return "Mod5";
default: return "???";
}
}
static void
x_reset_modifier_mapping (Display *display)
{
int modifier_index, modifier_key, column, mkpm;
int warned_about_overlapping_modifiers = 0;
int warned_about_predefined_modifiers = 0;
int warned_about_duplicate_modifiers = 0;
int meta_bit = 0;
int hyper_bit = 0;
int super_bit = 0;
int alt_bit = 0;
int mode_bit = 0;
XModifierKeymap *x_modifier_keymap = XGetModifierMapping (display);
#define modwarn(name,old,other) \
wwarning ("%s (0x%x) generates %s, which is generated by %s.\n\n", \
name, code, index_to_name (old), other), \
warned_about_overlapping_modifiers = 1
#define modbarf(name,other) \
wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n", \
name, code, other), \
warned_about_predefined_modifiers = 1
#define check_modifier(name,mask) \
if ((1<<modifier_index) != mask) \
wwarning ("%s (0x%x) generates %s, which is nonsensical.\n\n", \
name, code, index_to_name (modifier_index)), \
warned_about_predefined_modifiers = 1
#define store_modifier(name,old) \
if (old && old != modifier_index) \
wwarning ("%s (0x%x) generates both %s and %s, which is nonsensical.\n\n",\
name, code, index_to_name (old), \
index_to_name (modifier_index)), \
warned_about_duplicate_modifiers = 1; \
if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
else if (sym == XK_Mode_switch) \
mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
else if (modifier_index == meta_bit && old != meta_bit) \
modwarn (name, meta_bit, "Meta"); \
else if (modifier_index == super_bit && old != super_bit) \
modwarn (name, super_bit, "Super"); \
else if (modifier_index == hyper_bit && old != hyper_bit) \
modwarn (name, hyper_bit, "Hyper"); \
else if (modifier_index == alt_bit && old != alt_bit) \
modwarn (name, alt_bit, "Alt"); \
else \
old = modifier_index;
mkpm = x_modifier_keymap->max_keypermod;
for (modifier_index = 0; modifier_index < 8; modifier_index++)
for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
KeySym last_sym = 0;
for (column = 0; column < 4; column += 2) {
KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm
+ modifier_key];
KeySym sym = (code ? XKeycodeToKeysym (display, code, column) : 0);
if (sym == last_sym) continue;
last_sym = sym;
switch (sym) {
case XK_Mode_switch:store_modifier ("Mode_switch", mode_bit); break;
case XK_Meta_L: store_modifier ("Meta_L", meta_bit); break;
case XK_Meta_R: store_modifier ("Meta_R", meta_bit); break;
case XK_Super_L: store_modifier ("Super_L", super_bit); break;
case XK_Super_R: store_modifier ("Super_R", super_bit); break;
case XK_Hyper_L: store_modifier ("Hyper_L", hyper_bit); break;
case XK_Hyper_R: store_modifier ("Hyper_R", hyper_bit); break;
case XK_Alt_L: store_modifier ("Alt_L", alt_bit); break;
case XK_Alt_R: store_modifier ("Alt_R", alt_bit); break;
case XK_Control_L: check_modifier ("Control_L", ControlMask); break;
case XK_Control_R: check_modifier ("Control_R", ControlMask); break;
case XK_Shift_L: check_modifier ("Shift_L", ShiftMask); break;
case XK_Shift_R: check_modifier ("Shift_R", ShiftMask); break;
case XK_Shift_Lock: check_modifier ("Shift_Lock", LockMask); break;
case XK_Caps_Lock: check_modifier ("Caps_Lock", LockMask); break;
/* It probably doesn't make any sense for a modifier bit to be
assigned to a key that is not one of the above, but OpenWindows
assigns modifier bits to a couple of random function keys for
no reason that I can discern, so printing a warning here would
be annoying. */
}
}
}
#undef store_modifier
#undef check_modifier
#undef modwarn
#undef modbarf
/* If there was no Meta key, then try using the Alt key instead.
If there is both a Meta key and an Alt key, then the Alt key
is not disturbed and remains an Alt key. */
if (! meta_bit && alt_bit)
meta_bit = alt_bit, alt_bit = 0;
/* mode_bit overrides everything, since it's processed down inside of
XLookupString() instead of by us. If Meta and Mode_switch both
generate the same modifier bit (which is an error), then we don't
interpret that bit as Meta, because we can't make XLookupString()
not interpret it as Mode_switch; and interpreting it as both would
be totally wrong. */
if (mode_bit)
{
const char *warn = 0;
if (mode_bit == meta_bit) warn = "Meta", meta_bit = 0;
else if (mode_bit == hyper_bit) warn = "Hyper", hyper_bit = 0;
else if (mode_bit == super_bit) warn = "Super", super_bit = 0;
else if (mode_bit == alt_bit) warn = "Alt", alt_bit = 0;
if (warn)
{
wwarning
("%s is being used for both Mode_switch and %s.\n\n",
index_to_name (mode_bit), warn),
warned_about_overlapping_modifiers = 1;
}
}
MetaMask = (meta_bit ? (1 << meta_bit) : 0);
HyperMask = (hyper_bit ? (1 << hyper_bit) : 0);
SuperMask = (super_bit ? (1 << super_bit) : 0);
AltMask = (alt_bit ? (1 << alt_bit) : 0);
ModeMask = (mode_bit ? (1 << mode_bit) : 0); /* unused */
#if 0
if (warned_about_overlapping_modifiers)
wwarning ("\n"
" Two distinct modifier keys (such as Meta and Hyper) cannot generate\n"
" the same modifier bit, because Emacs won't be able to tell which\n"
" modifier was actually held down when some other key is pressed. It\n"
" won't be able to tell Meta-x and Hyper-x apart, for example. Change\n"
" one of these keys to use some other modifier bit. If you intend for\n"
" these keys to have the same behavior, then change them to have the\n"
" same keysym as well as the same modifier bit.\n");
if (warned_about_predefined_modifiers)
wwarning ("\n"
" The semantics of the modifier bits ModShift, ModLock, and ModControl\n"
" are predefined. It does not make sense to assign ModControl to any\n"
" keysym other than Control_L or Control_R, or to assign any modifier\n"
" bits to the \"control\" keysyms other than ModControl. You can't\n"
" turn a \"control\" key into a \"meta\" key (or vice versa) by simply\n"
" assigning the key a different modifier bit. You must also make that\n"
" key generate an appropriate keysym (Control_L, Meta_L, etc).\n");
/* No need to say anything more for warned_about_duplicate_modifiers. */
if (warned_about_overlapping_modifiers || warned_about_predefined_modifiers)
wwarning ("\n"
" The meanings of the modifier bits Mod1 through Mod5 are determined\n"
" by the keysyms used to control those bits. Mod1 does NOT always\n"
" mean Meta, although some non-ICCCM-compliant programs assume that.\n");
#endif
}
int
wXModifierFromKey(char *key)
{
if (strcasecmp(key, "SHIFT")==0 && ShiftMask!=0)
return ShiftMask;
else if (strcasecmp(key, "CONTROL")==0 && ControlMask!=0)
return ControlMask;
else if (strcasecmp(key, "ALT")==0 && AltMask!=0)
return AltMask;
else if (strcasecmp(key, "META")==0 && MetaMask!=0)
return MetaMask;
else if (strcasecmp(key, "SUPER")==0 && SuperMask!=0)
return SuperMask;
else if (strcasecmp(key, "HYPER")==0 && HyperMask!=0)
return HyperMask;
else if (strcasecmp(key, "MOD1")==0 && Mod1Mask!=0)
return Mod1Mask;
else if (strcasecmp(key, "MOD2")==0 && Mod2Mask!=0)
return Mod2Mask;
else if (strcasecmp(key, "MOD3")==0 && Mod3Mask!=0)
return Mod3Mask;
else if (strcasecmp(key, "MOD4")==0 && Mod4Mask!=0)
return Mod4Mask;
else if (strcasecmp(key, "MOD5")==0 && Mod5Mask!=0)
return Mod5Mask;
else
return -1;
}
/* Wrapper so that we may fit the WM naming conventions, yet leave the
original XEmacs function name in place. */
void
wXModifierInitialize(void)
{
x_reset_modifier_mapping(dpy);
}

27
src/xmodifier.h Normal file
View File

@@ -0,0 +1,27 @@
/* xmodifier.h
*
* Sudish Joseph <sj@vild.mindspring.com>, Sept. 1997
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifndef _XMODIFIER_H_INCLUDED
#define _XMODIFIER_H_INCLUDED
void wXModifierInitialize(void);
int wXModifierFromKey(char *key);
#endif /* _XMODIFIER_H_INCLUDED */

233
src/xutil.c Normal file
View File

@@ -0,0 +1,233 @@
/*
* WindowMaker miscelaneous functions
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <X11/Xlib.h>
#include <stdlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include "wconfig.h"
#include "xutil.h"
#include <WUtil.h>
static Atom Clipboard=0;
static char *requestCodes[] = {
"DUMMY",
"X_CreateWindow",
"X_ChangeWindowAttributes",
"X_GetWindowAttributes",
"X_DestroyWindow",
"X_DestroySubwindows",
"X_ChangeSaveSet",
"X_ReparentWindow",
"X_MapWindow",
"X_MapSubwindows",
"X_UnmapWindow",
"X_UnmapSubwindows",
"X_ConfigureWindow",
"X_CirculateWindow",
"X_GetGeometry",
"X_QueryTree",
"X_InternAtom",
"X_GetAtomName",
"X_ChangeProperty",
"X_DeleteProperty",
"X_GetProperty",
"X_ListProperties",
"X_SetSelectionOwner",
"X_GetSelectionOwner",
"X_ConvertSelection",
"X_SendEvent",
"X_GrabPointer",
"X_UngrabPointer",
"X_GrabButton",
"X_UngrabButton",
"X_ChangeActivePointerGrab",
"X_GrabKeyboard",
"X_UngrabKeyboard",
"X_GrabKey",
"X_UngrabKey",
"X_AllowEvents",
"X_GrabServer",
"X_UngrabServer",
"X_QueryPointer",
"X_GetMotionEvents",
"X_TranslateCoords",
"X_WarpPointer",
"X_SetInputFocus",
"X_GetInputFocus",
"X_QueryKeymap",
"X_OpenFont",
"X_CloseFont",
"X_QueryFont",
"X_QueryTextExtents",
"X_ListFonts",
"X_ListFontsWithInfo",
"X_SetFontPath",
"X_GetFontPath",
"X_CreatePixmap",
"X_FreePixmap",
"X_CreateGC",
"X_ChangeGC",
"X_CopyGC",
"X_SetDashes",
"X_SetClipRectangles",
"X_FreeGC",
"X_ClearArea",
"X_CopyArea",
"X_CopyPlane",
"X_PolyPoint",
"X_PolyLine",
"X_PolySegment",
"X_PolyRectangle",
"X_PolyArc",
"X_FillPoly",
"X_PolyFillRectangle",
"X_PolyFillArc",
"X_PutImage",
"X_GetImage",
"X_PolyText8",
"X_PolyText16",
"X_ImageText8",
"X_ImageText16",
"X_CreateColormap",
"X_FreeColormap",
"X_CopyColormapAndFree",
"X_InstallColormap",
"X_UninstallColormap",
"X_ListInstalledColormaps",
"X_AllocColor",
"X_AllocNamedColor",
"X_AllocColorCells",
"X_AllocColorPlanes",
"X_FreeColors",
"X_StoreColors",
"X_StoreNamedColor",
"X_QueryColors",
"X_LookupColor",
"X_CreateCursor",
"X_CreateGlyphCursor",
"X_FreeCursor",
"X_RecolorCursor",
"X_QueryBestSize",
"X_QueryExtension",
"X_ListExtensions",
"X_ChangeKeyboardMapping",
"X_GetKeyboardMapping",
"X_ChangeKeyboardControl",
"X_GetKeyboardControl",
"X_Bell",
"X_ChangePointerControl",
"X_GetPointerControl",
"X_SetScreenSaver",
"X_GetScreenSaver",
"X_ChangeHosts",
"X_ListHosts",
"X_SetAccessControl",
"X_SetCloseDownMode",
"X_KillClient",
"X_RotateProperties",
"X_ForceScreenSaver",
"X_SetPointerMapping",
"X_GetPointerMapping",
"X_SetModifierMapping",
"X_GetModifierMapping",
"X_NoOperation"
};
void
FormatXError(Display *dpy, XErrorEvent *error, char *buffer, int size)
{
int i, p;
XGetErrorText(dpy, error->error_code, buffer, size);
i = strlen(buffer);
if (i > size-100)
return;
buffer += i;
if (error->request_code >= sizeof(requestCodes)/sizeof(char*)) {
sprintf(buffer, "\n Unknown request code: %i\n",
error->request_code);
} else {
sprintf(buffer, "\n Request code: %i %s\n", error->request_code,
requestCodes[error->request_code]);
}
i += p = strlen(buffer);
if (i > size - 40)
return;
buffer += p;
sprintf(buffer, " Request minor code: %i\n", error->minor_code);
i += p = strlen(buffer);
if (i > size - 30)
return;
buffer += p;
sprintf(buffer, " Resource ID: 0x%x\n", (unsigned int)error->resourceid);
i += p = strlen(buffer);
if (i > size - 30)
return;
buffer += p;
sprintf(buffer, " Error serial: %li\n", error->serial);
return;
}
/*
*----------------------------------------------------------------------
* GetSelection--
* Request for the current primary selection.
*----------------------------------------------------------------------
*/
void
RequestSelection(Display *dpy, Window requestor, Time timestamp)
{
if (!Clipboard)
Clipboard = XInternAtom(dpy, "CLIPBOARD", False);
XConvertSelection(dpy, XA_PRIMARY, XA_STRING, Clipboard, requestor,
timestamp);
}
char*
GetSelection(Display *dpy, Window requestor)
{
Atom rtype;
int bits;
unsigned long len, bytes;
unsigned char *data;
XGetWindowProperty(dpy, requestor, Clipboard,
0, MAXLINE/4, False, XA_STRING,
&rtype, &bits, &len, &bytes, &data);
if ((rtype!=XA_STRING) || (bits!=8)) {
wwarning(_("invalid data in selection"));
if (data) XFree(data);
return NULL;
} else {
return (char*)data;
}
}

15
src/xutil.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _WM_XUTIL_H_
#define _WM_XUTIL_H_
void FormatXError(Display *dpy, XErrorEvent *error, char *buffer, int size);
void RequestSelection(Display *dpy, Window requestor, Time timestamp);
char *GetSelection(Display *dpy, Window requestor);
#endif