mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-24 23:22:30 +01:00
Initial revision
This commit is contained in:
101
src/GNUstep.h
Normal file
101
src/GNUstep.h
Normal 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
121
src/Makefile.am
Normal 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
432
src/Makefile.in
Normal 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
328
src/WindowMaker.h
Normal 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
1740
src/actions.c
Normal file
File diff suppressed because it is too large
Load Diff
63
src/actions.h
Normal file
63
src/actions.h
Normal 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
855
src/appicon.c
Normal 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
114
src/appicon.h
Normal 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
486
src/application.c
Normal 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
74
src/application.h
Normal 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
337
src/appmenu.c
Normal 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
33
src/appmenu.h
Normal 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
482
src/balloon.c
Normal 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
31
src/balloon.h
Normal 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
702
src/client.c
Normal 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
38
src/client.h
Normal 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
111
src/colormap.c
Normal 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
111
src/config.h
Normal 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
110
src/config.h.in
Normal 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
100
src/def_pixmaps.h
Normal 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
3250
src/defaults.c
Normal file
File diff suppressed because it is too large
Load Diff
63
src/defaults.h
Normal file
63
src/defaults.h
Normal 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
888
src/dialog.c
Normal 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
43
src/dialog.h
Normal 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
3869
src/dock.c
Normal file
File diff suppressed because it is too large
Load Diff
106
src/dock.h
Normal file
106
src/dock.h
Normal 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
429
src/dockedapp.c
Normal 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
1574
src/event.c
Normal file
File diff suppressed because it is too large
Load Diff
1167
src/framewin.c
Normal file
1167
src/framewin.c
Normal file
File diff suppressed because it is too large
Load Diff
141
src/framewin.h
Normal file
141
src/framewin.h
Normal 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
162
src/funcs.h
Normal 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
801
src/icon.c
Normal 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
74
src/icon.h
Normal 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
71
src/keybind.h
Normal 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
225
src/list.c
Normal 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
60
src/list.h
Normal 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
457
src/main.c
Normal 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
2374
src/menu.c
Normal file
File diff suppressed because it is too large
Load Diff
136
src/menu.h
Normal file
136
src/menu.h
Normal 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
1171
src/misc.c
Normal file
File diff suppressed because it is too large
Load Diff
65
src/motif.h
Normal file
65
src/motif.h
Normal 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
1337
src/moveres.c
Normal file
File diff suppressed because it is too large
Load Diff
271
src/pixmap.c
Normal file
271
src/pixmap.c
Normal 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
53
src/pixmap.h
Normal 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
522
src/placement.c
Normal 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
243
src/properties.c
Normal 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
47
src/properties.h
Normal 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
491
src/proplist.c
Normal 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
156
src/resources.c
Normal 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
29
src/resources.h
Normal 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
1682
src/rootmenu.c
Normal file
File diff suppressed because it is too large
Load Diff
821
src/screen.c
Normal file
821
src/screen.c
Normal 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
281
src/screen.h
Normal 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
508
src/session.c
Normal 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
34
src/session.h
Normal 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
121
src/shutdown.c
Normal 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
602
src/stacking.c
Normal 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
46
src/stacking.h
Normal 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
1
src/stamp-h.in
Normal file
@@ -0,0 +1 @@
|
||||
timestamp
|
||||
898
src/startup.c
Normal file
898
src/startup.c
Normal 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
310
src/superfluous.c
Normal 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
30
src/superfluous.h
Normal 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
306
src/switchmenu.c
Normal 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
674
src/text.c
Normal 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
66
src/text.h
Normal 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
566
src/texture.c
Normal 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
156
src/texture.h
Normal 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
444
src/wconfig.h
Normal 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
444
src/wconfig.h.in
Normal 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
185
src/wcore.c
Normal 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
57
src/wcore.h
Normal 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
586
src/wdefaults.c
Normal 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
43
src/wdefaults.h
Normal 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
2212
src/window.c
Normal file
File diff suppressed because it is too large
Load Diff
296
src/window.h
Normal file
296
src/window.h
Normal 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
339
src/winmenu.c
Normal 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
1370
src/winspector.c
Normal file
File diff suppressed because it is too large
Load Diff
97
src/winspector.h
Normal file
97
src/winspector.h
Normal 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
80
src/wmnotdef.h
Normal 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
139
src/wmnotify.c
Normal 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
40
src/wmnotify.h
Normal 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
58
src/wmsound.c
Normal 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
51
src/wmsound.h
Normal 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
615
src/workspace.c
Normal 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
50
src/workspace.h
Normal 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
297
src/xmodifier.c
Normal 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
27
src/xmodifier.h
Normal 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
233
src/xutil.c
Normal 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
15
src/xutil.h
Normal 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
|
||||
Reference in New Issue
Block a user