home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume15
/
olvwm-3.0
/
part10
< prev
next >
Wrap
Text File
|
1992-02-03
|
56KB
|
2,107 lines
Newsgroups: comp.sources.x
Path: uunet!elroy.jpl.nasa.gov!ames!pasteur!nntp
From: scott.oaks@East.Sun.COM (Scott Oaks)
Subject: v15i156: OpenLook Virtual Window Mgr (3.0), Part10/21
Message-ID: <1992Feb4.135728.7486@pasteur.Berkeley.EDU>
Sender: dcmartin@msi.com (David C. Martin - Moderator)
Nntp-Posting-Host: postgres.berkeley.edu
Organization: University of California, at Berkeley
References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
Date: Tue, 4 Feb 1992 13:57:28 GMT
Approved: dcmartin@msi.com
Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
Posting-number: Volume 15, Issue 156
Archive-name: olvwm-3.0/part10
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
# "End of archive 10 (of 21)."
# Contents: olwm.c states.c
# Wrapped by dcmartin@fascet on Tue Jan 14 05:54:44 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'olwm.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'olwm.c'\"
else
echo shar: Extracting \"'olwm.c'\" \(18395 characters\)
sed "s/^X//" >'olwm.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
X * file for terms of the license.
X */
X
X#ident "@(#)olwm.c 1.1 olvwm version 1/3/92"
X
X/*
X * Based on
X#ident "@(#)olwm.c 26.42 91/09/14 SMI"
X *
X */
X
X#include <errno.h>
X#include <memory.h>
X#include <signal.h>
X#include <stdio.h>
X#include <string.h>
X
X#include <sys/time.h>
X#include <sys/types.h>
X
X#include <sys/param.h>
X#include <sys/resource.h>
X#include <sys/stat.h>
X#include <sys/wait.h>
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X#include <X11/Xresource.h>
X
X#include "i18n.h"
X#include "ollocale.h"
X#include "events.h"
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "defaults.h"
X#include "resources.h"
X#include "globals.h"
X#include "group.h"
X#include "slots.h"
X
X#include "patchlevel.h"
X
Xtypedef void (*VoidFunc)();
X
X/*
X * Globals
X */
Xchar *ProgramName;
Xchar *AppName; /* strictly last component of ProgramName */
XGlobalResourceVariables GRV;
XXrmDatabase OlwmDB;
X
X
X/*
X * Global Quarks. "Top" refers to the root of the resource name/instance
X * hierarchy.
X */
XXrmQuark TopClassQ;
XXrmQuark TopInstanceQ;
XXrmQuark OpenWinQ;
X/*
X * Quark for olwm instance -- we read resources with an instance name of
X * olwm for backwards compatibility
X */
XXrmQuark OlwmQ;
X
X/* Current Display */
XDisplay *DefDpy;
X
X
Xstatic Display *openDisplay();
Xstatic void parseCommandline();
Xstatic void sendSyncSignal();
X
X
X/* Note that changes to RMTable instance names must also be made here !! */
Xstatic XrmOptionDescRec optionTable[] = {
X { "-display", ".display",
X XrmoptionSepArg, (caddr_t) NULL },
X { "-f", ".setInput",
X XrmoptionNoArg, (caddr_t) "follow" },
X { "-follow", ".setInput",
X XrmoptionNoArg, (caddr_t) "follow" },
X { "-c", ".setInput",
X XrmoptionNoArg, (caddr_t) "select" },
X { "-click", ".setInput",
X XrmoptionNoArg, (caddr_t) "select" },
X { "-2d", ".use3D",
X XrmoptionNoArg, (caddr_t) "False" },
X { "-3d", ".use3D",
X XrmoptionNoArg, (caddr_t) "True" },
X { "-parent", ".reparentOK",
X XrmoptionNoArg, (caddr_t) "False" },
X { "-orphans", ".printOrphans",
X XrmoptionNoArg, (caddr_t) "True" },
X { "-all", ".printAll",
X XrmoptionNoArg, (caddr_t) "True" },
X { "-synchronize", ".synchronize",
X XrmoptionNoArg, (caddr_t) "True" },
X { "-debug", ".printOrphans", XrmoptionNoArg, (caddr_t) "True" },
X { "-name", ".name",
X XrmoptionSepArg, (caddr_t) NULL },
X { "-bg", "*Background", XrmoptionSepArg, (caddr_t) NULL },
X { "-background", "*Background", XrmoptionSepArg, (caddr_t) NULL },
X { "-fg", "*Foreground", XrmoptionSepArg, (caddr_t) NULL },
X { "-foreground","*Foreground", XrmoptionSepArg, (caddr_t) NULL },
X { "-bd", "*Background",
X XrmoptionSepArg, (caddr_t) NULL },
X { "-bordercolor", "*Background",
X XrmoptionSepArg, (caddr_t) NULL },
X { "-fn", "*TitleFont", XrmoptionSepArg, (caddr_t) NULL },
X { "-font", "*TitleFont", XrmoptionSepArg, (caddr_t) NULL },
X { "-xrm", NULL, XrmoptionResArg, (caddr_t) NULL },
X { "-single", ".singleScreen",XrmoptionNoArg, (caddr_t) "True" },
X { "-multi", ".singleScreen",XrmoptionNoArg, (caddr_t) "False" },
X { "-syncpid", ".syncPid", XrmoptionSepArg, (caddr_t) NULL },
X { "-syncsignal",".syncSignal", XrmoptionSepArg, (caddr_t) NULL },
X { "-depth", "*depth", XrmoptionSepArg, (caddr_t) NULL },
X { "-visual", "*visual", XrmoptionSepArg, (caddr_t) NULL },
X#ifdef OW_I18N_L3
X { "-basiclocale", "*basicLocaleCL", XrmoptionSepArg, (caddr_t) NULL },
X { "-displaylang", "*displayLangCL", XrmoptionSepArg, (caddr_t) NULL },
X { "-inputlang", "*inputLangCL", XrmoptionSepArg, (caddr_t) NULL },
X { "-numeric", "*numericCL", XrmoptionSepArg, (caddr_t) NULL },
X { "-dateFormat", "*dateFormatCL", XrmoptionSepArg, (caddr_t) NULL },
X#endif /* OW_I18N_L3 */
X};
X#define OPTION_TABLE_ENTRIES (sizeof(optionTable)/sizeof(XrmOptionDescRec))
X
Xstatic void initWinClasses();
X
X/* Child Process Handling */
Xvoid HandleChildSignal();
Xvoid ReapChildren();
Xint DeadChildren = 0;
Xint SlavePid;
X
X#ifdef ALLPLANES
Xint allplanes; /* server supports the ALLPLANES extension */
X#endif
X
X#ifdef SHAPE
XBool ShapeSupported; /* server supports the SHAPE extension */
Xint ShapeEventBase;
Xint ShapeErrorBase;
X#endif
X
X
Xstatic char **argVec;
X
X/*
X * main -- parse arguments, perform initialization, call event-loop
X *
X * The OpenLook window manager was written before the OpenLook
X * spec. was completed. Because of this, some of it works in
X * an awkward way. Specifically, the way a window's focus and
X * select state is shown.
X *
X * For example, when a window is focused in click-to-focus mode
X * the header gets highlighted, (black background, white text).
X * As it was written, the titlebar window sits just inside of the
X * resize corners. Because the OpenLook spec. requires the header to
X * be highlighted in line with the resize corners, blacking in the
X * the background of the titlebar window is one pixel short in each
X * direction of being a big enough highlighted area. We can't make
X * the titlebar bigger because it would then overlap the resize corners.
X * Now that the spec. is complete, OLWM should be restructured.
X *
X * Overview:
X *
X * Upon startup OLWM reparents all the client windows unless
X * the user has told it otherwise (-p option).
X * OLWM creates a frame which will contain the client window (the pane)
X * and the decoration windows (resize corners, titlebar). The
X * titlebar window contains the pushpin, if any.
X *
X * After creating the decorations for the windows OLWM sits
X * in a forever loop getting the next event and calling the
X * corresponding window's event handling routine.
X *
X * Each window has associated with it an event handling
X * routine (EventFrame, EventPushPin) which the main EventLoop
X * will call when an event happens in that window. The event
X * handling routine will call the proper routines to move a
X * window, create a menu, etc.
X */
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X int ErrorHandler();
X int ExitOLWM();
X XrmDatabase commandlineDB = NULL;
X char *dpystr;
X
X#ifdef OW_I18N_L3
X#ifndef MAXPATHLEN
X#define MAXPATHLEN 256
X#endif
X char *OpenWinHome;
X char locale_dir[MAXPATHLEN+1];
X extern char *getenv();
X#endif /* OW_I18N_L3 */
X
X#ifdef MALLOCDEBUG
X malloc_debug(MALLOCDEBUG);
X#endif /* MALLOCDEBUG */
X#ifdef GPROF_HOOKS
X moncontrol(0);
X#endif /* GPROF_HOOKS */
X
X#ifdef OW_I18N_L3
X /*
X * Even in the SUNDAE1.0 (first release) we might need the
X * dynamic locale change for window manager, since window
X * manager is usually never re-start again in one sesstion.
X * But leave static for now.
X */
X /*
X * We are setting the locale (issuing the setlocale) by
X * EffectOLLC() function, but we need to call setlocale here
X * to handle command line argument with certain locale.
X * FIX_ME! But may not work well, because we did not touch the
X * Xlib function XrmParseCommand().
X */
X if (setlocale(LC_ALL, "") == NULL) {
X /*
X * FIX_ME: Following message may be misleading,
X * because setlocale will retrieve more than just a
X * $LANG environment variable (such as $LC_CTYPE).
X * Also, later if the resource DB has a locale
X * infomation, we will use it. Hence, this setting is
X * may be only for the command line processing.
X */
X fprintf(stderr, gettext("\
X olwm: Warning: '%s' is invalid locale, using 'C' locale.\n"),
X getenv("LANG"));
X (void)setlocale(LC_ALL,"C");
X }
X if ((OpenWinHome = getenv("OPENWINHOME")) != 0)
X (void)strcpy(locale_dir,OpenWinHome);
X else
X (void)strcpy(locale_dir,"/usr");
X (void)strcat(locale_dir,"/lib/locale");
X bindtextdomain("olwm_messages",locale_dir);
X textdomain("olwm_messages");
X#endif /* OW_I18N_L3 */
X
X ProgramName = argv[0];
X argVec = argv;
X
X /* Set up a signal handler so that if we are killed we put
X * the windows back into a usable state. Specifically we
X * need to reset the focus so they will be able to get input.
X */
X signal(SIGHUP, (VoidFunc)ExitOLWM);
X signal(SIGINT, (VoidFunc)ExitOLWM);
X signal(SIGTERM, (VoidFunc)ExitOLWM);
X signal(SIGCHLD, HandleChildSignal);
X
X /* initialize the resource manager */
X XrmInitialize();
X
X /* parse the command line arguments into local tmp DB */
X parseCommandline( &argc, argv, &commandlineDB );
X
X DefDpy = openDisplay(commandlineDB);
X
X#ifdef ALLPLANES
X {
X int tmp;
X allplanes = XAllPlanesQueryExtension(DefDpy, &tmp, &tmp);
X }
X#endif /* ALLPLANES */
X
X
X#ifdef SHAPE
X ShapeSupported = XShapeQueryExtension(DefDpy, &ShapeEventBase,
X &ShapeErrorBase);
X#endif /* SHAPE */
X
X /* put all resources into global OlwmDB and set olwm variables */
X GetDefaults(DefDpy, commandlineDB);
X
X /* Initialize the event handling system. */
X InitEvents(DefDpy);
X InitBindings(DefDpy);
X
X /* Set up the error handling function. */
X XSetErrorHandler(ErrorHandler);
X
X /* this can be useful for debuging strange client behaivior */
X if (GRV.Synchronize)
X XSynchronize(DefDpy, True);
X
X /* Initialize the atoms we will need to communicate with
X * Open Look clients.
X */
X InitAtoms(DefDpy);
X
X /* Initialize the database. */
X WIInit( DefDpy );
X
X /* Initialise all types of window classes */
X initWinClasses(DefDpy);
X
X /* Initialize client led state */
X InitClientState(DefDpy);
X
X /* initialise the group module */
X GroupInit();
X
X /*
X * Force child processes to disinherit the TCP file descriptor.
X * This helps shell commands forked and exec'ed from menus
X * to work properly.
X */
X if (fcntl(ConnectionNumber(DefDpy), F_SETFD, 1) == -1)
X {
X perror( gettext("olvwm: child cannot disinherit TCP fd") );
X exit( -1 );
X }
X
X#ifdef OW_I18N_L3
X EffectOLLC(DefDpy);
X#endif /* OW_I18N_L3 */
X /* Init the global menus -- No more global menus; done in InitScreens
X InitMenus(DefDpy);
X */
X
X /* init region handling code */
X InitRegions();
X
X /* Init screen */
X InitScreens(DefDpy);
X InitOlvwmRC(DefDpy);
X GrabKeys(DefDpy, True);
X GrabButtons(DefDpy, True);
X ReparentScreens(DefDpy);
X if (!GRV.FocusFollowsMouse)
X ClientFocusTopmost(DefDpy, GetFirstScrInfo(), CurrentTime);
X CreateAutoRootMenu(DefDpy);
X
X /*
X * Start olwmslave - using the same args we got.
X */
X if (GRV.RunSlaveProcess)
X SlavePid = SlaveStart(argVec);
X
X if (GRV.Beep != BeepNever)
X XBell(DefDpy, 100);
X
X sendSyncSignal();
X
X EventLoop( DefDpy );
X
X /*NOTREACHED*/
X}
X
X
X/*
X * parseCommandline - parse the command line arguments into a resource
X * database
X */
Xstatic void
XparseCommandline( argc, argv, tmpDB )
Xint *argc;
Xchar *argv[];
XXrmDatabase *tmpDB;
X{
X char instName[MAX_NAME];
X char namestr[MAX_NAME];
X char *type, *p;
X XrmValue val;
X
X /* Extract trailing pathname component of argv[0] into AppName. */
X
X AppName = strrchr(argv[0], '/');
X if (AppName == NULL)
X AppName = argv[0];
X else
X ++AppName;
X
X XrmParseCommand(tmpDB, optionTable, OPTION_TABLE_ENTRIES,
X AppName, argc, argv );
X
X /*
X * Initialize root instance and class quarks. Create the instance
X * name by first looking up the "name" resource in the command line
X * database (for the -name option). If it's not present, use AppName
X * (the trailing pathname component of argv[0]). Then, scan it and
X * replace all illegal characters with underscores. Note: we don't
X * use the ctype functions here, because they are internationalized.
X * In some locales, isalpha() will return true for characters that are
X * not valid in resource component names. Thus, we must fall back to
X * standard character comparisions.
X *
X * REMIND: specifying the -name option changes the name with which
X * resources are looked up. But the command line options were put
X * into the database using AppName, which is based on argv[0]. Thus,
X * specifying -name causes all command-line args to be ignored, which
X * is wrong.
X */
X
X (void) strcpy(namestr, AppName);
X (void) strcat(namestr, ".name");
X if (XrmGetResource(*tmpDB, namestr, namestr, &type, &val)) {
X (void) strncpy(instName, (char *)val.addr, MAX_NAME);
X } else {
X (void) strncpy(instName, AppName, MAX_NAME);
X }
X
X instName[MAX_NAME-1] = '\0';
X for (p=instName; *p != '\0'; ++p) {
X if (!(*p >= 'a' && *p <= 'z' ||
X *p >= 'A' && *p <= 'Z' ||
X *p >= '0' && *p <= '9' ||
X *p == '_' || *p == '-')) {
X *p = '_';
X }
X }
X TopInstanceQ = XrmStringToQuark(instName);
X TopClassQ = XrmStringToQuark("Olwm");
X OpenWinQ = XrmStringToQuark("OpenWindows");
X OlwmQ = XrmStringToQuark("olwm");
X
X /* check to see if there are any arguments left unparsed */
X if ( *argc != 1 )
X {
X /* check to see if it's -help */
X if ( argv[1][0] == '-' && argv[1][1] == 'h' )
X usage(gettext("Command line arguments accepted"),gettext("are:"));
X else
X usage(gettext("Unknown argument(s)"), gettext("encountered"));
X }
X}
X
X
X/*
X * openDisplay
X */
Xstatic Display *
XopenDisplay(rdb)
X XrmDatabase rdb;
X{
X char namebuf[MAX_NAME];
X char *type;
X XrmValue value;
X char *dpystr = NULL;
X char *envstr;
X Display *dpy;
X
X (void) strcpy(namebuf, AppName);
X (void) strcat(namebuf, ".display");
X
X if (XrmGetResource(rdb, namebuf, namebuf, &type, &value)) {
X dpystr = (char *)value.addr;
X envstr = (char *)MemAlloc(8+strlen(dpystr)+1);
X sprintf(envstr, "DISPLAY=%s", dpystr);
X putenv(envstr);
X }
X
X dpy = XOpenDisplay(dpystr);
X if (dpy == NULL) {
X fprintf(stderr, gettext("%s: cannot connect to %s\n"),
X ProgramName, dpystr);
X exit(1);
X }
X return dpy;
X}
X
X
X/*
X * sendSyncSignal
X *
X * Send a signal to the process named on the command line (if any). Values
X * for the process id and signal to send are looked up in the resource
X * database; they are settable with command-line options. The resources are
X * looked up with the names
X *
X * <appname>.syncPid process id
X * <appname>.syncSignal signal to send (integer)
X *
X * where <appname> is the trailing pathname component of argv[0].
X */
Xstatic void
XsendSyncSignal()
X{
X char *type;
X XrmValue value;
X int pid;
X int sig = SIGALRM;
X int tmp;
X char namebuf[100];
X
X (void) strcpy(namebuf, AppName);
X (void) strcat(namebuf, ".syncPid");
X if (!XrmGetResource(OlwmDB, namebuf, namebuf, &type, &value))
X return;
X pid = atoi((char *)value.addr);
X if (pid <= 0 || pid > MAXPID)
X return;
X
X (void) strcpy(namebuf, AppName);
X (void) strcat(namebuf, ".syncSignal");
X if (XrmGetResource(OlwmDB, namebuf, namebuf, &type, &value)) {
X tmp = atoi((char *)value.addr);
X if (tmp > 0 && tmp <= SIGUSR2)
X sig = tmp;
X }
X (void) kill(pid, sig);
X}
X
X
Xstatic void
XinitWinClasses(dpy)
XDisplay *dpy;
X{
X FrameInit(dpy);
X IconInit(dpy);
X ResizeInit(dpy);
X ColormapInit(dpy);
X ButtonInit(dpy);
X BusyInit(dpy);
X MenuInit(dpy);
X PinMenuInit(dpy);
X RootInit(dpy);
X NoFocusInit(dpy);
X PushPinInit(dpy);
X PaneInit(dpy);
X IconPaneInit(dpy);
X VirtualInit(dpy);
X}
X
X
X/*
X * Exit -- exit routine called by menus.
X * Kill all running applications.
X */
XExit(dpy)
XDisplay *dpy;
X{
X extern void *ClientShutdown();
X
X SlaveStop();
X ListApply(ActiveClientList, ClientShutdown, (void *)0);
X XSync(dpy, True);
X exit(0);
X /*NOTREACHED*/
X}
X
X
Xstatic void
Xcleanup()
X{
X extern void *UnparentClient();
X
X /*
X * If DefDpy is NULL then we didn't get to the XOpenDisplay()
X * so basically there is nothing to clean up so return.
X */
X if (DefDpy == NULL)
X return;
X
X /*
X * Stop olwmslave
X */
X SlaveStop();
X
X /*
X * destroy all pinned menus
X */
X DestroyPinnedMenuClients();
X
X /*
X * Clean up the virtual desktop -- if we aren't left in the upper
X * left corner, nothing will start in the right place
X */
X VirtualCleanup(DefDpy);
X
X /*
X * Go through the list of windows. Unmap all icons that are on the
X * screen. Reparent all windows back to the root, suitably offset
X * according to their window-gravities. Also remap all non-withdrawn
X * windows, and remove all Withdrawn windows from the save-set (so
X * they don't get remapped. REMIND: We have to do this because
X * Withdrawn windows are still left reparented inside the frame; this
X * shouldn't be the case.
X */
X ListApply(ActiveClientList,UnparentClient,NULL);
X
X /* Destroy the screens - which will restore input focus, colormap,
X * and background, etc.
X */
X DestroyScreens(DefDpy);
X
X XSync(DefDpy, True);
X}
X
X
X/* Clean up and then re-exec argv. */
Xint
XRestartOLWM()
X{
X cleanup();
X execvp(argVec[0], argVec);
X ErrorGeneral("cannot restart");
X /*NOTREACHED*/
X}
X
X
X/* Clean up and then exit. */
Xint
XExitOLWM()
X{
X cleanup();
X exit(0);
X}
X
X
X/*
X * HandleChildSignal - keep track of children that have died
X */
Xstatic void
XHandleChildSignal()
X{
X /*
X * Following is only neede for SYSV but it doesn't hurt in BSD
X */
X signal(SIGCHLD, HandleChildSignal);
X ++DeadChildren;
X}
X
X/*
X * ReapChildren - wait() for all dead child processes
X */
Xvoid
XReapChildren()
X{
X#ifdef SYSV
X sigset_t newmask, oldmask;
X int status;
X pid_t pid;
X#else
X int oldmask;
X int pid;
X union wait status;
X#endif
X
X#ifdef SYSV
X sigemptyset(&newmask);
X sigemptyset(&oldmask);
X sigaddset(&newmask, SIGCHLD);
X sigprocmask(SIG_BLOCK, &newmask, &oldmask);
X#else
X oldmask = sigblock(sigmask(SIGCHLD));
X#endif
X while (DeadChildren>0)
X {
X#ifdef SYSV
X pid = waitpid(-1, &status, WNOHANG);
X#else
X pid = wait3(&status, WNOHANG, (struct rusage *)0);
X#endif
X /* if it's the slave process then stop its use */
X if (pid == SlavePid)
X SlaveStopped();
X
X if (pid == 0)
X {
X /* Removed error message - deemed not useful */
X DeadChildren = 0;
X break;
X }
X if (WIFSTOPPED(status))
X {
X kill(pid, SIGKILL);
X }
X --DeadChildren;
X }
X#ifdef SYSV
X sigprocmask(SIG_SETMASK, &oldmask, &oldmask);
X#else
X (void) sigsetmask(oldmask);
X#endif
X}
X
X/*
X * usage(s1, s2) -- print informative message regarding usage
X */
Xstatic
Xusage(s1, s2)
Xchar *s1, *s2;
X{
X fprintf(stderr, "%s %s\n", s1, s2);
X fprintf(stderr,
X "usage: %s [-2d] [-3d] [-click] [-follow] [-parent]\n", ProgramName);
X fputs(
X /* STRING_EXTRACTION - do not translate "-display" ,"-name"
X * and "-xrm", becuase those are namne of command line option.
X */
X gettext("\t[-display <display>] [-name <classname>] [-xrm <rsrcstring>]\n"),
X stderr);
X fputs("\t[-all] [-debug] [-orphans] [-synchronize] [-single]\n", stderr);
X fputs("\t[-syncpid pid] [-syncsignal signal]\n", stderr);
X exit(1);
X}
X
END_OF_FILE
if test 18395 -ne `wc -c <'olwm.c'`; then
echo shar: \"'olwm.c'\" unpacked with wrong size!
fi
# end of 'olwm.c'
fi
if test -f 'states.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'states.c'\"
else
echo shar: Extracting \"'states.c'\" \(33415 characters\)
sed "s/^X//" >'states.c' <<'END_OF_FILE'
X/* (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
X * file for terms of the license.
X */
X
X/* states.c - functions relating to changes in client state
X * (Normal, Iconic, Withdrawn)
X */
X
X#ident "@(#)states.c 1.1 olvwm version 1/3/92"
X
X/*
X * Based on
X#ident "@(#)states.c 26.50 91/09/14 SMI"
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xatom.h>
X
X#include "i18n.h"
X#include "ollocale.h"
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "group.h"
X#include "globals.h"
X#include "properties.h"
X#include "virtual.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
Xextern Atom AtomWMClass;
Xextern Atom AtomDecorAdd;
Xextern Atom AtomDecorClose;
Xextern Atom AtomDecorDel;
Xextern Atom AtomDecorFooter;
Xextern Atom AtomDecorHeader;
Xextern Atom AtomDecorIconName;
Xextern Atom AtomDecorPin;
Xextern Atom AtomDecorResize;
Xextern Atom AtomDeleteWindow;
Xextern Atom AtomMenuFull;
Xextern Atom AtomMenuLimited;
Xextern Atom AtomNone;
Xextern Atom AtomOlwmTimestamp;
Xextern Atom AtomPinIn;
Xextern Atom AtomPinOut;
Xextern Atom AtomProtocols;
Xextern Atom AtomSaveYourself;
Xextern Atom AtomTakeFocus;
Xextern Atom AtomWinAttr;
Xextern Atom AtomWTBase;
Xextern Atom AtomWTCmd;
Xextern Atom AtomWTHelp;
Xextern Atom AtomWTNotice;
Xextern Atom AtomWTOther;
X
Xextern Client *CurrentClient;
X
Xextern int WinDrawFunc();
Xextern void IconPaneSetPixmap();
Xextern void IconPaneSetMask();
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* sanity checks for getting stuff out of hints */
X#define IsCard16(x) ((x) == ((unsigned short)(x)) && (x) > 0 )
X#define IsInt16(x) ((x) == ((short) (x)))
X
Xstatic WMDecorations BaseWindow = {
X WMDecorationCloseButton | WMDecorationResizeable | WMDecorationHeader
X | WMDecorationIconName,
X MENU_FULL,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations CmdWindow = {
X WMDecorationPushPin | WMDecorationResizeable | WMDecorationHeader
X | WMDecorationIconName,
X MENU_LIMITED,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations NoticeWindow = {
X WMDecorationIconName,
X MENU_NONE,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations HelpWindow = {
X WMDecorationPushPin | WMDecorationHeader | WMDecorationIconName
X | WMDecorationWarpToPin,
X MENU_LIMITED,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations OtherWindow = {
X WMDecorationIconName,
X MENU_NONE,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations TransientWindow = {
X WMDecorationResizeable | WMDecorationIconName,
X MENU_LIMITED,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations MinimalWindow = {
X WMDecorationResizeable | WMDecorationIconName,
X MENU_FULL,
X 0,
X PIN_IN,
X 0
X};
X
Xstatic WMDecorations NoDecors = {
X WMNoDecor,
X MENU_NONE,
X 0,
X PIN_OUT,
X 0
X};
X
Xtypedef struct {
X char *class, *instance, *name;
X} minimalclosure;
X
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/*
X * Determine FocusMode from wmHints and protocols
X */
Xstatic FocusMode
XfocusModeFromHintsProtocols(wmHints,protocols)
X XWMHints *wmHints;
X int protocols;
X{
X FocusMode focusMode;
X
X if (wmHints && wmHints->input) {
X if (protocols & TAKE_FOCUS)
X focusMode = LocallyActive;
X else
X focusMode = Passive;
X } else { /* wmHints->input == False */
X if (protocols & TAKE_FOCUS)
X focusMode = GloballyActive;
X else
X focusMode = NoInput;
X }
X return focusMode;
X}
X
X/* matchInstClass -- run through the list of names to be minimally
X * decorated, and see if this window's class or instance match
X * any.
X *
X * In olvwm, we check the name as well as class/instance
X */
Xstatic Bool
XmatchInstClass(str,mc)
Xchar *str;
Xminimalclosure *mc;
X{
X if ((mc->class != NULL) && (!strcmp(str, mc->class)))
X return True;
X if ((mc->instance != NULL) && (!strcmp(str, mc->instance)))
X return True;
X if ((mc->name != NULL) && (!strncmp(str, mc->name, strlen(str))))
X return True;
X return False;
X}
X
X
X/*
X * getOlWinDecors - given the window attributes and decoration add/delete
X * requests, determine what kind of window (according to the OpenLook
X * kinds of windows) the client represents, and determine what sort of
X * decorations are appropriate.
X */
XWMDecorations *
XgetOLWinDecors(dpy, win, transient, cli)
XDisplay *dpy;
XWindow win;
XBool transient;
XClient *cli;
X{
X WMDecorations *decors;
X minimalclosure mc;
X XWMHints *wmHints = cli->wmHints;
X OLWinAttr *winAttrs;
X Bool oldVersion;
X int decorFlags;
X
X decors = MemNew(WMDecorations);
X
X /*
X * REMIND: there is no way for a program to
X * specify the default item, even if it should
X * specify the menu
X * so this get's initialized here
X * (one per window)
X */
X decors->def_item = 0;
X
X /* if the instance or class strings match any of the names
X * listed for minimal decoration, only provide resize corners
X * and a menu.
X */
X mc.class = cli->wmClass;
X mc.instance = cli->wmInstance;
X if (!XFetchName(dpy, win, &mc.name))
X mc.name = NULL;
X if (ListApply(GRV.Minimals,matchInstClass,&mc) != NULL)
X {
X *decors = MinimalWindow;
X return decors;
X }
X if (ListApply(GRV.NoDecors, matchInstClass, &mc) != NULL) {
X *decors = NoDecors;
X if (mc.name)
X XFree(mc.name);
X return decors;
X }
X if (mc.name)
X XFree(mc.name);
X
X#ifdef SHAPE
X if (cli->isShaped) {
X *decors = MinimalWindow;
X return decors;
X }
X#endif
X
X oldVersion = False;
X winAttrs = MemNew(OLWinAttr);
X
X /*
X * If the _OL_WIN_ATTR property is not present then make the
X * window into a base window unless is a transient window.
X */
X if (!PropGetOLWinAttr(dpy,win,winAttrs,&oldVersion)) {
X if (transient) {
X *decors = TransientWindow;
X if (GRV.TransientsTitled)
X decors->flags |= WMDecorationHeader;
X } else {
X *decors = BaseWindow;
X }
X /*
X * Else we do have that property; so interpret it
X */
X } else {
X /*
X * Choose the decor from win_type
X */
X if ((winAttrs->flags & WA_WINTYPE) == 0) {
X *decors = BaseWindow;
X } else if (winAttrs->win_type == AtomWTBase) {
X *decors = BaseWindow;
X } else if (winAttrs->win_type == AtomWTCmd) {
X *decors = CmdWindow;
X } else if (winAttrs->win_type == AtomWTHelp) {
X *decors = HelpWindow;
X } else if (winAttrs->win_type == AtomWTNotice) {
X *decors = NoticeWindow;
X } else if (winAttrs->win_type == AtomWTOther) {
X *decors = OtherWindow;
X
X /*
X * This is the only case where we look at menu type
X */
X if (winAttrs->flags & WA_MENUTYPE) {
X if (winAttrs->menu_type == AtomMenuFull)
X decors->menu_type = MENU_FULL;
X else if (winAttrs->menu_type == AtomMenuLimited)
X decors->menu_type = MENU_LIMITED;
X else if (winAttrs->menu_type == AtomNone)
X decors->menu_type = MENU_NONE;
X }
X }
X
X /*
X * Backward compatibility. If we had a old/short attribute
X * property, and the client specified an icon window, we're
X * probably dealing with an old XView client. These clients
X * assume the window manager doesn't put the icon name in
X * the icon, so they paint it into the icon window itself.
X * Turn off the painting of the icon name for icons of
X * these windows.
X */
X if (oldVersion && wmHints && (wmHints->flags & IconWindowHint))
X decors->flags &= ~WMDecorationIconName;
X
X /*
X * Set cancel if something specified
X */
X if (winAttrs->flags & WA_CANCEL)
X decors->cancel = (winAttrs->cancel != 0);
X
X /*
X * Set the pin state
X */
X if (winAttrs->flags & WA_PINSTATE) {
X decors->pushpin_initial_state =
X winAttrs->pin_initial_state;
X } else {
X decors->pushpin_initial_state = PIN_OUT;
X }
X }
X
X /*
X * Apply DecorAdd flags
X */
X if (PropGetOLDecorAdd(dpy,win,&decorFlags)) {
X decors->flags |= decorFlags;
X }
X
X /*
X * Apply DecorDel flags
X */
X if (PropGetOLDecorDel(dpy,win,&decorFlags)) {
X decors->flags &= ~decorFlags;
X }
X
X /*
X * If the window has no header it can't have any header
X * decorations; ie. pushpin or a close button.
X */
X if (!(decors->flags & WMDecorationHeader)) {
X decors->flags &= ~(WMDecorationHeaderDeco);
X }
X
X /*
X * If the window wants both a pushpin and a close button it
X * only can have a pushpin.
X */
X if ((decors->flags & WMDecorationCloseButton) &&
X (decors->flags & WMDecorationPushPin))
X decors->flags &= ~(WMDecorationCloseButton);
X
X /*
X * Don't warp to the pin if there's no pin.
X */
X if (!(decors->flags & WMDecorationPushPin))
X decors->flags &= ~WMDecorationWarpToPin;
X
X return decors;
X}
X
X
X/*
X * calcPosition
X *
X * Calculate the next position to place a new window. This function places
X * all new windows on the diagonal and makes sure that there is enough room on
X * the screen for the new window's size passed in w and h.
X */
Xstatic void
XcalcPosition(dpy, screen, attrs, frame)
X Display *dpy;
X int screen;
X XWindowAttributes *attrs;
X WinPaneFrame *frame;
X{
X int stepValue;
X ScreenInfo *scrInfo;
X
X if ((scrInfo = GetScrInfoOfScreen(screen)) == NULL) {
X attrs->x = attrs->y = 0;
X return;
X }
X
X /* if the height of the current window is too large ... */
X if ((scrInfo->framepos + frame->core.height
X > DisplayHeight(dpy, screen)) ||
X (scrInfo->framepos + frame->core.width
X > DisplayWidth(dpy, screen)))
X {
X scrInfo->framepos = 0;
X }
X
X /* REMIND this should really be based on the header height */
X stepValue = 30;
X
X /* we will return the current position */
X attrs->x = attrs->y = scrInfo->framepos;
X
X /* calculate the next return value */
X scrInfo->framepos = scrInfo->framepos + stepValue;
X if ((scrInfo->framepos > DisplayWidth(dpy, screen)) ||
X (scrInfo->framepos > DisplayHeight(dpy, screen)))
X {
X scrInfo->framepos = 0;
X }
X}
X
X
X/*
X * iconifyOne -- iconify one client
X */
Xstatic void *
XiconifyOne(cli, winIcon)
XClient *cli;
XWinGeneric *winIcon;
X{
X if (cli->groupmask == GROUP_DEPENDENT)
X RemoveSelection(cli); /* warp if necessary */
X else
X DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin);
X
X UnmapWindow(cli->framewin);
X XUnmapWindow(cli->dpy, PANEWINOFCLIENT(cli));
X cli->framewin->fcore.panewin->pcore.pendingUnmaps++;
X cli->wmState = IconicState;
X ClientSetWMState(cli);
X return NULL;
X}
X
X/* deiconifyOne -- deiconify one client
X */
Xstatic void *
XdeiconifyOne(cli, winIcon, raise)
XClient *cli;
XWinGeneric *winIcon;
XBool raise;
X{
X if (cli->groupmask != GROUP_DEPENDENT)
X DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin);
X
X if (raise)
X RaiseWindow(cli->framewin);
X
X MapWindow(cli->framewin);
X XMapRaised(cli->dpy, PANEWINOFCLIENT(cli));
X cli->wmState = NormalState;
X ClientSetWMState(cli);
X return NULL;
X}
X
X
X/*
X * markFrame
X *
X * Marks a client's frame window with a given value. Suitable for calling by
X * ListApply or GroupApply.
X */
Xstatic void *
XmarkFrame(cli, value)
X Client *cli;
X int value;
X{
X if (cli->framewin != NULL)
X cli->framewin->core.tag = value;
X return NULL;
X}
X
X
X/*
X * deiconifyGroup
X *
X * Deiconify a window group, preserving stacking order. Mark all the frames
X * that are to be deiconified, then query the server for all children-of-root.
X * Walk backward through this array (i.e. from top to bottom). For each group
X * member found, stack it just below the previous one (raise the first one to
X * the top) and deiconify it. Finally, unmark all the frames in the group.
X * Note: this algorithm depends on having the stacking order of windows
X * preserved when the group is iconified.
X */
Xstatic void
XdeiconifyGroup(cli, winIcon)
X Client *cli;
X WinIconFrame* winIcon;
X{
X Window root, parent;
X Window *children;
X Window prev = None;
X unsigned int nchildren;
X int i;
X WinGeneric *wi;
X XWindowChanges xwc;
X
X GroupApply(cli->groupid, markFrame, 1, GROUP_LEADER|GROUP_DEPENDENT);
X
X (void) XQueryTree(cli->dpy, cli->scrInfo->rootid, &root, &parent,
X &children, &nchildren);
X
X xwc.stack_mode = Below;
X for (i=nchildren-1; i>=0; --i) {
X wi = WIGetInfo(children[i]);
X if (wi != NULL && wi->core.tag == 1) {
X if (prev == None) {
X RaiseWindow(wi);
X } else {
X xwc.sibling = prev;
X ConfigureWindow(cli->dpy, wi,
X CWSibling|CWStackMode, &xwc);
X }
X prev = children[i];
X deiconifyOne(wi->core.client, winIcon, False);
X }
X }
X
X if (children != NULL)
X XFree((char *)children);
X
X GroupApply(cli->groupid, markFrame, 0, GROUP_LEADER|GROUP_DEPENDENT);
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X
X/*
X * StateNew -- A client is mapping a top-level window (either a new window
X * or a Withdrawn window). The window may become Iconic or Normal
X * depending on the hints. Check to see if this window needs to be mapped
X * and if so add the required adornments.
X * dpy -- display pointer
X * rootWin -- root window
X * if None will determine the root window
X * for the client window
X * window -- client's window
X * fexisting -- the window already exists and we
X * are starting olwm, so positioning should
X * be special-cased
X * ourWinInfo -- if is this one of our menu windows, this
X * will be its WinMenu structure; this window must
X * be a subclass of Pane
X * If this is a VDM, this will be a subclass of
X * VPane
X */
XClient *
XStateNew(dpy, rootWin, window, fexisting, ourWinInfo)
XDisplay *dpy;
XWindow rootWin;
XWindow window;
XBool fexisting;
XWinPane *ourWinInfo;
X{
X Client *cli;
X WinGeneric *winGeneric;
X WinPane *winPane;
X WinIconFrame *winIcon;
X WinPaneFrame *winFrame;
X WinIconPane *winIconPane;
X XSizeHints *normHints;
X Bool preICCCM;
X Bool transient = False;
X int status;
X int initstate;
X XWindowAttributes paneAttr;
X int screen;
X int tmpx, tmpy;
X ScreenInfo *scrInfo;
X int winState;
X Window iconWin;
X minimalclosure mc;
X int icon_x, icon_y;
X
X /*
X * If the window is thought to be new (i.e. if ourWinInfo is null, as
X * it is always except for the case of pinned menus and the VDM) and
X * the window * has already been registered in the WinInfo database
X * and it's anything other than colormap window, then return.
X *
X * This is to head off (a) clients that might be mapping the olwm
X * frame, (b) clients that map their top-level window (pane) more than
X * once before olwm can reparent it to a frame, and (c) olwm's own
X * popup menus.
X */
X if (!ourWinInfo &&
X (winGeneric = WIGetInfo(window)) != NULL &&
X winGeneric->core.kind != WIN_COLORMAP) {
X return NULL;
X }
X
X /* Find the screen the client window is on.
X * If ourWinInfo is valid, use it's screen
X * Else if know the root then use it's screen
X * Lastly QueryTree to find out from the server
X */
X if (ourWinInfo) {
X screen = ourWinInfo->core.client->scrInfo->screen;
X } else if (rootWin != None) {
X if ((scrInfo = GetScrInfoOfRoot(rootWin)) == NULL)
X return NULL;
X screen = scrInfo->screen;
X } else {
X Window root, parent, *children;
X unsigned int nChild;
X Status result;
X
X result = XQueryTree(dpy, window, &root, &parent,
X &children, &nChild);
X
X if (result == 0 || parent != root)
X return NULL;
X if ((scrInfo = GetScrInfoOfRoot(root)) == NULL)
X return NULL;
X screen = scrInfo->screen;
X }
X
X /*
X * Select for events on the pane right now (including StructureNotify)
X * so that we are guaranteed to get a DestroyNotify if the window goes
X * away. If the window has already gone away, the call to
X * XGetWindowAttributes below will tell us without race conditions.
X */
X if (!ourWinInfo)
X XSelectInput(dpy, window,
X PropertyChangeMask | StructureNotifyMask |
X ColormapChangeMask | EnterWindowMask);
X
X /* get all the info about the new pane */
X status = XGetWindowAttributes(dpy, window, &paneAttr);
X if ( status == 0 ) {
X return NULL;
X }
X
X /*
X * If it's an override-redirect window, or if already exists but is
X * unmapped, ignore it after first removing our StructureNotify
X * interest.
X */
X if (paneAttr.override_redirect ||
X (fexisting && paneAttr.map_state != IsViewable)) {
X if (!ourWinInfo)
X XSelectInput(dpy, window, NoEventMask);
X return NULL;
X }
X
X /* Create the client structure so we can start hooking things to it */
X if ((cli = ClientCreate(dpy,screen)) == NULL)
X {
X return NULL;
X }
X
X#ifdef SHAPE
X {
X Bool bshaped, cshaped;
X int bx, by, cx, cy;
X unsigned int bw, bh, cw, ch;
X
X if (ShapeSupported &&
X 0 != XShapeQueryExtents(dpy, window, &bshaped, &bx, &by,
X &bw, &bh, &cshaped, &cx, &cy,
X &cw, &ch))
X {
X XShapeSelectInput(dpy, window, ShapeNotifyMask);
X cli->isShaped = bshaped;
X } else {
X cli->isShaped = False;
X }
X }
X#endif /* SHAPE */
X
X /*
X * Turn on prop read filtering with set of available properties
X */
X PropSetAvailable(dpy,window);
X
X /*
X * Get the WM_TRANSIENT_FOR hint. If the property exists but has a
X * contents of zero, or the window itself, substitute the root's
X * window ID. This is because some (buggy) clients actually write
X * zero in the WM_TRANSIENT_FOR property, and we want to give them
X * transient window behavior.
X */
X if (!PropGetWMTransientFor(dpy,window,cli->scrInfo->rootid,
X &(cli->transientFor))) {
X cli->transientFor = 0;
X transient = False;
X } else {
X transient = True;
X }
X
X /*
X * Get the WM_NORMAL_HINTS property. If it's short, then we have a
X * pre-ICCCM client on our hands, so we interpret some values
X * specially.
X */
X normHints = MemNew(XSizeHints);
X
X if (!PropGetWMNormalHints(dpy,window,normHints,&preICCCM)) {
X normHints->win_gravity = NorthWestGravity;
X normHints->flags = PWinGravity;
X }
X
X /*
X * We got a short property. Assume that this is a pre-X11R4
X * client who's using the short version of the property. Copy
X * the data into a correctly-sized structure. Then, depending
X * on the flags set, ignore the window's real geometry and use
X * the data in the hint (but only if it passes some sanity
X * checking). The sanity checking is necessary because early
X * versions of XView write a short property, but rely on the
X * window manager to look at the window's geometry instead of
X * at the values in the hint.
X */
X if (preICCCM) {
X int maxDpyWidth = 2*DisplayWidth(dpy,screen);
X int maxDpyHeight = 2*DisplayHeight(dpy,screen);
X
X if (!fexisting
X && (normHints->flags & (USPosition|PPosition))
X && IsInt16(normHints->x)
X && IsInt16(normHints->y)
X && normHints->x > -maxDpyWidth
X && normHints->y > -maxDpyHeight
X && normHints->x < maxDpyWidth
X && normHints->y < maxDpyHeight) {
X paneAttr.x = normHints->x;
X paneAttr.y = normHints->y;
X }
X if ((normHints->flags & (USSize|PSize))
X && IsCard16(normHints->width)
X && IsCard16(normHints->height)
X && normHints->width >= MINSIZE
X && normHints->height >= MINSIZE
X && normHints->width < maxDpyWidth
X && normHints->height < maxDpyHeight) {
X paneAttr.width = normHints->width;
X paneAttr.height = normHints->height;
X }
X }
X
X cli->normHints = normHints;
X
X /*
X * Get the WM_HINTS
X */
X cli->wmHints = MemNew(XWMHints);
X
X if (!PropGetWMHints(dpy,window,cli->wmHints)) {
X cli->wmHints->flags = 0L;
X }
X
X /*
X * Get the protocols in which the client will participate
X */
X if (!PropGetWMProtocols(dpy,window,&(cli->protocols))) {
X cli->protocols = 0;
X }
X
X /*
X * Figure out what focus mode this window intends
X */
X cli->focusMode = focusModeFromHintsProtocols(cli->wmHints,
X cli->protocols);
X
X /*
X * Get the window class and instance strings
X */
X if (!PropGetWMClass(dpy,window,&(cli->wmClass),&(cli->wmInstance))) {
X cli->wmClass = cli->wmInstance = NULL;
X }
X
X /*
X * Get the OpenLook window type and associated decorations
X */
X cli->wmDecors = getOLWinDecors(dpy, window, transient, cli);
X
X /*
X * Establish window groups. Policy: if the window is transient, this
X * takes priority over any window group specified in WM_HINTS. If
X * it's transient, make it be part of the window group of the window
X * it is transient for. Otherwise, use the group specified in
X * WM_HINTS. If no group is specified in WM_HINTS, consider the
X * window to be the leader of its own group.
X */
X if (transient) {
X winGeneric = WIGetInfo(cli->transientFor);
X if (winGeneric != NULL)
X cli->groupid = winGeneric->core.client->groupid;
X else
X cli->groupid = cli->transientFor;
X } else if ((cli->wmHints) && (cli->wmHints->flags & WindowGroupHint)) {
X cli->groupid = cli->wmHints->window_group;
X } else {
X cli->groupid = window;
X }
X
X if (cli->groupid == window)
X cli->groupmask = GROUP_LEADER;
X else
X {
X if (((cli->wmDecors->flags & WMDecorationPushPin) &&
X (cli->wmDecors->menu_type == MENU_LIMITED))
X || transient)
X {
X cli->groupmask = GROUP_DEPENDENT;
X }
X else
X {
X cli->groupmask = GROUP_INDEPENDENT;
X }
X }
X GroupAdd(cli->groupid,cli,cli->groupmask);
X
X /*
X * Officially set up the frame
X */
X winFrame = MakeFrame(cli,window,&paneAttr);
X
X /*
X * If the hints don't specify a location, we choose a suitable one,
X * taking into account the window size and decoration sizes.
X */
X if ( !fexisting &&
X !(normHints->flags & USPosition) &&
X (!(normHints->flags & PPosition) ||
X (GRV.PPositionCompat && paneAttr.x <= 1 && paneAttr.y <= 1)))
X {
X calcPosition(dpy, screen, &paneAttr, winFrame);
X }
X else if (!fexisting && (normHints->flags & USPosition) &&
X !GRV.UseRelativePosition) {
X paneAttr.x += cli->scrInfo->vdm->offsetX;
X paneAttr.y += cli->scrInfo->vdm->offsetY;
X }
X
X /*
X * See if the position needs to be constrained to a logical
X * screen due to entries in .olvwmrc
X */
X if (!XFetchName(dpy, window, &mc.name))
X mc.name = NULL;
X icon_x = icon_y = 0;
X if (cli->groupmask != GROUP_DEPENDENT)
X if (cli->wmHints)
X if (cli->wmHints->flags & IconPositionHint)
X SearchProgString(dpy, cli->scrInfo, mc.name,
X cli->wmInstance, cli->wmClass,
X &paneAttr.x, &paneAttr.y,
X &cli->wmHints->icon_x, &cli->wmHints->icon_y);
X else SearchProgString(dpy, cli->scrInfo, mc.name,
X cli->wmInstance, cli->wmClass,
X &paneAttr.x, &paneAttr.y,
X &icon_x, &icon_y);
X else SearchProgString(dpy, cli->scrInfo, mc.name, NULL, NULL,
X &paneAttr.x, &paneAttr.y, &icon_x, &icon_y);
X else {
X /*
X * Map the popup on the same screen as the group leader
X */
X Client *leader = GroupLeader(cli->groupid);
X int curScreen;
X int dw = DisplayWidth(dpy, screen);
X int dh = DisplayHeight(dpy, screen);
X
X if (leader != NULL) {
X curScreen = leader->framewin->core.x / dw;
X if (leader->framewin->core.x < 0)
X curScreen--;
X if (paneAttr.x < 0)
X paneAttr.x = dw + (paneAttr.x % dw) + (curScreen * dw);
X else paneAttr.x = (paneAttr.x % dw) + (curScreen * dw);
X curScreen = leader->framewin->core.y / dh;
X if (leader->framewin->core.y < 0)
X curScreen--;
X if (paneAttr.y < 0)
X paneAttr.y = dh + (paneAttr.y % dh) + (curScreen * dh);
X else paneAttr.y = (paneAttr.y % dh) + (curScreen * dh);
X }
X }
X
X
X /*
X * If a non-olwm created window then create the pane for it
X * Else if it is a pinned menu then call the creation callback
X * so that it can fix up its pane
X */
X if (ourWinInfo == NULL) {
X winPane = MakePane(cli,winFrame,window,&paneAttr);
X } else {
X winPane = ourWinInfo;
X (WinClass(winPane)->core.createcallback)(ourWinInfo,cli,
X winFrame);
X }
X
X /*
X * Officially set up the icon
X */
X winIcon = MakeIcon(cli,window,&paneAttr);
X winIconPane = MakeIconPane(cli,winIcon,cli->wmHints,fexisting);
X
X /*
X * Keep track of any subwindows that need colormap installation
X */
X TrackSubwindows(cli);
X
X /*
X * Size and generally configure the frame window tree
X */
X FrameSetPosFromPane(winFrame,paneAttr.x,paneAttr.y);
X WinCallConfig(dpy, winPane, NULL);
X
X /*
X * Size and generally configure the icon window tree
X */
X WinCallConfig(dpy, winIconPane, NULL);
X if (cli->wmHints != NULL && (cli->wmHints->flags & IconPositionHint))
X IconSetPos(winIcon,cli->wmHints->icon_x,cli->wmHints->icon_y);
X else
X IconSetPos(winIcon,icon_x,icon_y);
X WinCallConfig(dpy, winIcon, NULL);
X
X /*
X * We manually move the icon pane window, since all the configuration
X * has been done with the icon pane parented to root.
X */
X WinRootPos(winIconPane, &tmpx, &tmpy);
X XMoveWindow(dpy, winIconPane->core.self, tmpx, tmpy);
X
X /*
X * Set the sticky bit according to the sticky list. We check the
X * window's group below (stickyness is inherited by group).
X * sticky was set when the client was created; if this is a VDM
X * then sticky will be set to true in the callback
X */
X mc.class = cli->wmClass;
X mc.instance = cli->wmInstance;
X if (ListApply(GRV.StickyList, matchInstClass, &mc) != NULL)
X cli->sticky = True;
X if (mc.name)
X XFree(mc.name);
X
X /*
X * Determine the proper initial state of the window.
X * If the window already exists and there is a WM_STATE property
X * then use the state that the last window manager left there,
X * otherwise use WM_HINTS.
X */
X if (fexisting &&
X PropGetWMState(dpy,winPane->core.self,&winState,&iconWin)) {
X if (winState == IconicState)
X initstate = IconicState;
X else
X initstate = NormalState;
X } else {
X /* For new windows, check the initial_state field of WM_HINTS. */
X if (cli->wmHints && (cli->wmHints->flags & StateHint)
X && (cli->wmHints->initial_state == IconicState))
X initstate = IconicState;
X else
X initstate = NormalState;
X }
X
X /*
X * Don't allow the popup into iconic state if its leader is in normal
X * state.
X *
X * Also set the sticky field of the client based on the leader
X */
X if (cli->groupmask == GROUP_DEPENDENT) {
X Client *leader = GroupLeader(cli->groupid);
X if (leader != NULL) {
X if (leader->wmState == NormalState && initstate == IconicState)
X initstate = NormalState;
X cli->sticky = leader->sticky;
X }
X }
X
X if (cli->sticky)
X MakeSticky(cli, True);
X MakeVirtual(cli);
X ClientProcessDragDropInterest(cli, PropertyNewValue);
X
X /*
X * Put the window into the correct initial state
X */
X switch ( initstate ) {
X case NormalState:
X cli->wmState = NormalState;
X MapRaised(winFrame);
X XMapRaised(dpy, winPane->core.self);
X if (!fexisting) {
X FrameWarpPointer(cli);
X if (GRV.AutoInputFocus)
X ClientSetFocus(cli, True, CurrentTime);
X if (GRV.AutoColorFocus)
X LockColormap(dpy, cli, winPane);
X }
X break;
X case IconicState:
X cli->wmState = IconicState;
X /* unmap the window in case it was mapped originally */
X XUnmapWindow(dpy, winPane->core.self);
X winPane->pcore.pendingUnmaps++;
X /* dependent group followers don't get their own icons */
X if (cli->groupmask != GROUP_DEPENDENT)
X IconShow(cli, winIcon);
X break;
X }
X ClientSetWMState(cli);
X
X /*
X * Get the window state
X */
X ClientGetWindowState(cli);
X
X /*
X * Turn off prop read filtering
X */
X PropClearAvailable();
X
X return cli;
X}
X
X/*
X * ReparentTree -- called at start up, this routine queries the window
X * tree and reparents all the windows
X */
Xvoid
XReparentTree(dpy,treeroot)
XDisplay *dpy;
XWindow treeroot;
X{
X unsigned int numChildren;
X Window *children, root, parent, w;
X int ii;
X Client *cli;
X
X children = NULL;
X
X if (XQueryTree(dpy, treeroot, &root, &parent,
X &children, &numChildren))
X {
X for (ii=0; ii<numChildren; ii++)
X {
X w = children[ii];
X if (WIGetInfo(w) == NULL)
X {
X cli = StateNew(dpy, treeroot, w, True, NULL);
X if (cli != NULL)
X {
X cli->framewin->fcore.panewin->pcore.pendingUnmaps++;
X /* unmap because of reparent */
X }
X }
X }
X }
X
X if (children != NULL)
X XFree((char *)children);
X}
X
X
X/*
X * StateNormIcon - transition a window to IconicState from NormalState
X */
Xvoid
XStateNormIcon(cli)
XClient *cli;
X{
X WinIconFrame *winIcon = cli->iconwin;
X
X if (winIcon == NULL)
X return;
X
X /* don't do some other transition */
X if (cli->wmState != NormalState)
X return;
X
X /* we can't iconify if we are a dependent */
X if (cli->groupmask == GROUP_DEPENDENT)
X return;
X
X /* Map the icon window */
X IconShow(cli, winIcon);
X
X /* iconify self and dependents */
X if (cli->groupmask == GROUP_LEADER)
X GroupApply(cli->groupid, iconifyOne, winIcon,
X GROUP_LEADER|GROUP_DEPENDENT);
X else
X iconifyOne(cli,winIcon);
X
X if (cli == CurrentClient && !GRV.FocusFollowsMouse)
X ClientSetFocus(cli, False, TimeFresh(cli->iconwin));
X}
X
X/*
X * StateIconNorm - transition a window to NormalState from IconicState
X */
Xvoid
XStateIconNorm(cli)
XClient *cli;
X{
X WinIconFrame *winIcon = cli->iconwin;
X
X if (winIcon == NULL)
X return;
X
X /* don't do some other transition */
X if (cli->wmState != IconicState)
X return;
X
X if (cli->groupmask == GROUP_LEADER)
X deiconifyGroup(cli, winIcon);
X else
X deiconifyOne(cli,winIcon,True);
X
X /* Unmap icons */
X IconHide(cli, winIcon);
X
X if (cli == CurrentClient && !GRV.FocusFollowsMouse)
X ClientSetFocus(cli, True, TimeFresh(cli->framewin));
X}
X
X/*
X * StateWithdrawn - a window is being withdrawn; tear down all related
X * structures; clear the client out of all lists it may be
X * on; reparent the pane window
X */
Xvoid
XStateWithdrawn(cli)
XClient *cli;
X{
X WinIconFrame *iconInfo = cli->iconwin;
X WinPaneFrame *frameInfo = cli->framewin;
X WinPane *paneInfo;
X Window pane;
X Display *dpy = cli->dpy;
X
X if (iconInfo == NULL || frameInfo == NULL)
X return;
X
X paneInfo = (WinPane*)(frameInfo->fcore.panewin);
X pane = paneInfo->core.self;
X iconInfo = cli->iconwin;
X
X /* Return the pointer if necessary */
X FrameUnwarpPointer(cli);
X
X /* Unmap the frame and pane. */
X UnmapWindow(frameInfo);
X XUnmapWindow(dpy, pane);
X
X /* Unmap the icon */
X if (iconInfo != NULL)
X IconHide(cli, iconInfo);
X
X /* move the pane and unparent it */
X FrameUnparentPane(cli, frameInfo, paneInfo);
X
X DestroyClient(cli);
X}
X
X/************************************************************************
X * Top-Level Window Property Update Functions
X ************************************************************************/
X
X/*
X * Refresh SizeHints from WM_NORMAL_HINTS property. The new values
X * can simply be copied into the client's normHints.
X */
Xvoid
XStateUpdateWMNormalHints(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X Window pane;
X XSizeHints sizeHints;
X Bool preICCCM;
X
X if (event->state != PropertyNewValue)
X return;
X
X pane = PANEWINOFCLIENT(cli);
X
X if (!PropGetWMNormalHints(cli->dpy,pane,&sizeHints,&preICCCM))
X return;
X
X *(cli->normHints) = sizeHints;
X}
X
X/*
X * Reapply WMHints from the WM_HINTS property. Ignore everything but
X * InputHint and Icon{Pixmap/Mask}Hint.
X */
Xvoid
XStateUpdateWMHints(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X Window pane;
X XWMHints wmHints;
X WinIconPane *iconPane;
X Pixmap iconMask;
X
X if (cli->framewin == NULL || cli->iconwin == NULL ||
X event->state != PropertyNewValue)
X return;
X
X pane = PANEWINOFCLIENT(cli);
X iconPane = (WinIconPane *)cli->iconwin->fcore.panewin;
X
X if (!PropGetWMHints(cli->dpy,pane,&wmHints))
X return;
X
X if (wmHints.flags & InputHint) {
X cli->focusMode =
X focusModeFromHintsProtocols(&wmHints,cli->protocols);
X }
X
X if (wmHints.flags & IconPixmapHint)
X IconPaneSetPixmap(cli->dpy,iconPane,wmHints.icon_pixmap);
X if (wmHints.flags & IconMaskHint)
X IconPaneSetMask(cli->dpy,iconPane,wmHints.icon_mask);
X if (wmHints.flags & IconPixmapHint || wmHints.flags & IconMaskHint)
X WinDrawFunc(iconPane);
X
X if (cli->wmHints == NULL)
X cli->wmHints = MemNew(XWMHints);
X
X *(cli->wmHints) = wmHints;
X}
X
X/*
X * Reset client protocols and focusMode from WM_PROTOCOLS
X */
Xvoid
XStateUpdateWMProtocols(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X Window pane;
X int protocols;
X
X if (cli->framewin == NULL || event->state != PropertyNewValue)
X return;
X
X pane = PANEWINOFCLIENT(cli);
X
X if (!PropGetWMProtocols(cli->dpy,pane,&protocols))
X return;
X
X if (cli->protocols == protocols)
X return;
X
X cli->focusMode = focusModeFromHintsProtocols(cli->wmHints,protocols);
X cli->protocols = protocols;
X}
X
X/*
X * StateUpdateWinAttr - reread the _OL_WIN_ATTR property.
X * For now just apply WA_PINSTATE.
X */
Xvoid
XStateUpdateWinAttr(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X OLWinAttr winAttr;
X Bool old;
X Window pane;
X
X if (cli->framewin == NULL || event->state != PropertyNewValue)
X return;
X
X pane = PANEWINOFCLIENT(cli);
X
X if (!PropGetOLWinAttr(cli->dpy,pane,&winAttr,&old))
X return;
X
X if ((winAttr.flags & WA_PINSTATE) && ClientIsPinnable(cli)) {
X WinPushPin *pushPin = (WinPushPin *)cli->framewin->winDeco;
X PushPinSetPinState(cli->dpy,pushPin,
X winAttr.pin_initial_state,False);
X }
X}
X
X/*
X * StateUpdateDecorAdd - read the DecorAdd property and reapply it
X */
Xvoid
XStateUpdateDecorAdd(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X /* REMIND - this needs to be implemented */
X}
X
X/*
X * StateUpdateDecorDel - read the DecorDel property and reapply it
X */
Xvoid
XStateUpdateDecorDel(cli,event)
X Client *cli;
X XPropertyEvent *event;
X{
X /* REMIND - this needs to be implemented */
X}
END_OF_FILE
if test 33415 -ne `wc -c <'states.c'`; then
echo shar: \"'states.c'\" unpacked with wrong size!
fi
# end of 'states.c'
fi
echo shar: End of archive 10 \(of 21\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 21 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Molecular Simulations, Inc. mail: dcmartin@postgres.berkeley.edu
796 N. Pastoria Avenue uucp: uwvax!ucbvax!dcmartin
Sunnyvale, California 94086 at&t: 408/522-9236