sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) (04/29/91)
Submitted-by: sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) Posting-number: Volume 12, Issue 68 Archive-name: olvwm/part12 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 12 (of 16)." # Contents: states.c # Wrapped by sdo@piccolo on Fri Apr 26 17:31:08 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'states.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'states.c'\" else echo shar: Extracting \"'states.c'\" \(29221 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 * Written for Sun Microsystems by Crucible, Santa Cruz, CA. X */ X X/* states.c - functions relating to changes in client state X * (Normal, Iconic, Withdrawn) X */ X static char sccsid[] = "@(#)states.c 1.4 olvwm version 4/17/91"; X X/* X * Based on static char sccsid[] = "@(#) states.c 25.23 90/05/30 Crucible"; 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#include "mem.h" X#include "olwm.h" X#include "win.h" X#include "group.h" X#include "globals.h" X X#define TRUE (1) X#define FALSE (0) X X/*************************************************************************** X* global data X***************************************************************************/ X extern int DefScreen; extern Atom AtomClass; extern Atom AtomDecorAdd; extern Atom AtomDecorClose; extern Atom AtomDecorDelete; extern Atom AtomDecorFooter; extern Atom AtomDecorHeader; extern Atom AtomDecorPin; extern Atom AtomDecorResize; extern Atom AtomDeleteWindow; extern Atom AtomMenuFull; extern Atom AtomMenuLimited; extern Atom AtomNone; extern Atom AtomOlwmTimestamp; extern Atom AtomPinIn; extern Atom AtomPinOut; extern Atom AtomProtocols; extern Atom AtomSaveYourself; extern Atom AtomTakeFocus; extern Atom AtomWinAttr; extern Atom AtomWTBase; extern Atom AtomWTCmd; extern Atom AtomWTHelp; extern Atom AtomWTNotice; extern Atom AtomWTOther; extern Atom AtomWTProp; extern Window NoFocusWin; extern Bool FocusIndeterminate; X extern Window VDM; X 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 static WMDecorations BaseWindow = X{ X WMDecorationCloseButton | WMDecorationResizeable | WMDecorationHeader, X MENU_FULL, X PIN_IN X}; X static WMDecorations CmdWindow = X{ X WMDecorationCloseButton | WMDecorationResizeable | WMDecorationHeader | X WMDecorationPushPin, X MENU_LIMITED, X PIN_IN X}; X static WMDecorations PropWindow = X{ X WMDecorationCloseButton | WMDecorationResizeable | X WMDecorationHeader | WMDecorationPushPin, X MENU_LIMITED, X PIN_IN X}; X static WMDecorations NoticeWindow = X{ X WMDecorationHeader, X MENU_NONE, X PIN_IN X}; X static WMDecorations HelpWindow = X{ X WMDecorationCloseButton | WMDecorationPushPin | WMDecorationHeader, X MENU_LIMITED, X PIN_IN X}; X static WMDecorations OtherWindow = X{ X 0L, X MENU_NONE, X PIN_IN X}; X static WMDecorations TransientWindow = X{ X 0L, X MENU_NONE, X PIN_IN X}; X static WMDecorations MinimalWindow = X{ X WMDecorationResizeable, X MENU_FULL, X PIN_IN X}; X typedef struct { X char *class, *instance; X} minimalclosure; X X/*************************************************************************** X* forward private declarations X***************************************************************************/ X X X/*************************************************************************** X* private functions X*********t******************************************************************/ 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 */ static Bool matchInstClass(str,mc) char *str; minimalclosure *mc; X{ X if ((mc->class == NULL) || (strcmp(str,mc->class))) X return ((mc->instance != NULL) && (!strcmp(str,mc->instance))); X else X return True; 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 */ WMDecorations * getOLWinDecors(dpy, win, pwinType, transient, wmInstance, wmClass) Display *dpy; Window win; int *pwinType; Bool transient; char *wmInstance, *wmClass; X{ X WMDecorations *decors; X unsigned long nItems, remain; X long offset; X Atom *decorChange; X struct X { X Atom win_type; X Atom menu_type; X int pin_initial_state; X } *winAttrs; X minimalclosure mc; X X decors = MemNew(WMDecorations); 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 = wmClass; X mc.instance = wmInstance; X if (ListApply(GRV.Minimals,matchInstClass,&mc) != NULL) X { X *decors = MinimalWindow; X *pwinType = OLMINIMALDECOR; X return decors; X } X X winAttrs = GetWindowProperty(dpy, win, AtomWinAttr, 0L, X 3*LONG_LENGTH(Atom), /* one winAttrs struct */ X AtomWinAttr, 0, &nItems, &remain); X X /* if the property does not exist, then we assume that the X * window is a base window X */ X if ((winAttrs == NULL) || (nItems != 3)) X { X if (transient) X { X *decors = TransientWindow; X *pwinType = OLTRANSIENTWINDOW; X } X else X { X *decors = BaseWindow; X *pwinType = OLBASEWINDOW; X } X } X else X { X if (winAttrs->win_type == AtomWTBase) X { X *decors = BaseWindow; X *pwinType = OLBASEWINDOW; X } X else if (winAttrs->win_type == AtomWTCmd) X { X *decors = CmdWindow; X *pwinType = OLCMDWINDOW; X } X else if (winAttrs->win_type == AtomWTProp) X { X *decors = PropWindow; X *pwinType = OLPROPWINDOW; X } X else if (winAttrs->win_type == AtomWTHelp) X { X *decors = HelpWindow; X *pwinType = OLHELPWINDOW; X } X else if (winAttrs->win_type == AtomWTNotice) X { X *decors = NoticeWindow; X *pwinType = OLNOTICEWINDOW; X } X else if (winAttrs->win_type == AtomWTOther) X { X *decors = OtherWindow; X *pwinType = OLOTHERWINDOW; X X /* this is the only case where we look at menu type */ 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 * Check the pushpin's initial state X * REMIND There's some backwards compatibility code here. Older X * clients use the _OL_PIN_IN and _OL_PIN_OUT atoms here, X * whereas the OLXCI specifies zero as out and one as in. X * Handle both cases. X */ X if ((winAttrs->pin_initial_state == AtomPinIn) || X (winAttrs->pin_initial_state == PIN_IN)) X decors->pushpin_initial_state = PIN_IN; X else if ((winAttrs->pin_initial_state == AtomPinOut) || X (winAttrs->pin_initial_state == PIN_OUT)) X decors->pushpin_initial_state = PIN_OUT; X else X decors->pushpin_initial_state = PIN_OUT; X X XFree(winAttrs); X } X X X X /* are there any non-standard decorations ? */ X /* first check for decorations added */ X offset = 0L; X for(;;) X { X decorChange = GetWindowProperty(dpy, win, AtomDecorAdd, X offset, LONG_LENGTH(Atom), XA_ATOM, 0, X &nItems, &remain); X X if ((nItems == 0) || (decorChange == NULL)) X break; X X offset++; X X if (*decorChange == AtomDecorClose) X decors->flags |= WMDecorationCloseButton; X else if (*decorChange == AtomDecorFooter) X decors->flags |= WMDecorationFooter; X else if (*decorChange == AtomDecorResize) X decors->flags |= WMDecorationResizeable; X else if (*decorChange == AtomDecorHeader) X decors->flags |= WMDecorationHeader; X else if (*decorChange == AtomDecorPin) X decors->flags |= WMDecorationPushPin; X X XFree(decorChange); X } X X /* now check for decorations deleted */ X offset = 0L; X for(;;) X { X decorChange = GetWindowProperty(dpy, win, AtomDecorDelete, X offset, LONG_LENGTH(Atom), XA_ATOM, 0, X &nItems, &remain); X X if ((nItems == 0) || (decorChange == NULL)) X break; X X offset++; X X if (*decorChange == AtomDecorClose) X decors->flags &= ~(WMDecorationCloseButton); X else if (*decorChange == AtomDecorFooter) X decors->flags &= ~(WMDecorationFooter); X else if (*decorChange == AtomDecorResize) X decors->flags &= ~(WMDecorationResizeable); X else if (*decorChange == AtomDecorHeader) X decors->flags &= ~(WMDecorationHeader); X else if (*decorChange == AtomDecorPin) X decors->flags &= ~(WMDecorationPushPin); X X XFree(decorChange); 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 return decors; X} X X X/* X * calcPosition -- calculate the next position to place a new window. This X * function places all new windows on the diagonal and makes sure that X * there is enough room on the screen for the new window's size passed X * in w and h. X */ static void calcPosition(dpy, screen, attrs) Display *dpy; XXWindowAttributes *attrs; X{ X static int nextPosition = 0; X int stepValue; X X /* REMIND redo this to allow for window decorations when X * calculating max size X */ X /* if the height of the current window is too large ... */ X while (nextPosition + attrs->height > DisplayHeight(dpy, screen)) X { X /* if we are already at the upper left corner ... */ X if (nextPosition == 0) X { X /* .. then set the height to just fit */ X attrs->height = DisplayHeight(dpy, screen); X break; X } X else X /* .. try to fit window in upper-left */ X nextPosition = 0; X } X X /* if the width of the current window is too large to fit... */ X while (nextPosition + attrs->width > DisplayWidth(dpy, screen)) X { X /* if we are already at the upper-left corner... */ X if (nextPosition == 0) X { X /* ... then set the width to just fit */ X attrs->width = DisplayWidth(dpy, screen); X break; X } X else X /* ... try to fit window in the upper-left */ X nextPosition = 0; X } X X stepValue = 30; /* REMIND This should really be based on HEADER_HEIGHT. */ X X /* we will return the current position */ X attrs->x = attrs->y = nextPosition; X X /* calculate the next return value */ X nextPosition = (nextPosition + stepValue ) X % DisplayWidth(dpy, screen); X#ifdef DEBUG X printf("calcPosition: returning x %d y %d\n",attrs->x,attrs->y); X#endif X} X X/* iconifyOne -- iconify one client X */ static void * iconifyOne(cli, winIcon) Client *cli; WinGeneric *winIcon; X{ Window tmp; X X DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin); X if (cli->groupmask == GROUP_DEPENDENT) X RemoveSelection(cli); /* warp if necessary */ X XUnmapWindow(cli->dpy, cli->framewin->core.self); X XUnmapWindow(cli->dpy, PANEWINOFCLIENT(cli)); X XUnmapWindow(cli->dpy, cli->virtualWindow); X tmp = cli->virtualWindow; X cli->virtualWindow = cli->virtualInactive; X cli->virtualInactive = tmp; 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 */ static void * deiconifyOne(cli, winIcon) Client *cli; WinGeneric *winIcon; X{ Window tmp; X X DrawIconToWindowLines(cli->dpy, winIcon, cli->framewin); X XMapRaised(cli->dpy, cli->framewin->core.self); X XMapRaised(cli->dpy, PANEWINOFCLIENT(cli)); X tmp = cli->virtualWindow; X cli->virtualWindow = cli->virtualInactive; X cli->virtualInactive = tmp; X XMapRaised(cli->dpy, cli->virtualWindow); X cli->wmState = NormalState; X ClientSetWMState(cli); X return NULL; 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 * 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 */ Client * StateNew(dpy, window, fexisting, ourWinInfo) Display *dpy; Window window; Bool fexisting; WinPane *ourWinInfo; X{ X Client *cli; X WinPane *winPane; X WinIconFrame *winIcon; X WinPaneFrame *winFrame; X WinIconPane *winIconPane; X Window transient_for; X Window tmp; X NewXSizeHints *normalHints = NULL; X Bool transient = False; X unsigned long nItems; X unsigned long remain; X int status; X int initstate; X int count; X Atom *protocols; X XWindowAttributes paneAttr; X int screen = DefaultScreen(dpy); X int tmpx, tmpy; X char *classInstance; X minimalclosure mc; X extern int VirtualDesktopX, VirtualDesktopY; X X /* if it's a transient window, do not adorn it */ X transient = XGetTransientForHint(dpy, window, &transient_for); X X /* X * if this window is not a child of root, then it will be ignored X */ X if (ourWinInfo == NULL) X { X Window root, parent, *children; X int nChild; X Status result; X X result = XQueryTree(dpy, window, X &root, &parent, &children, &nChild); X X if ((result == 0) || (parent != RootWindow(dpy, screen))) X return NULL; X } X X /* by selecting for DestroyNotifys here, we are guaranteed that X * if the window goes away we will eventually hear about it. X * The GetWindowAttributes following this select ensures that X * we don't have a race condition in finding out. X */ X X if (!ourWinInfo && !IsVirtual(window)) X XSelectInput(dpy, window, StructureNotifyMask); X X /* get all the info about the new pane */ X status = XGetWindowAttributes(dpy, window, &paneAttr); X if ( status == 0 ) { X#ifdef DEBUG X ErrorWarning("StateNew: GetWindowAttributes failed!"); X#endif /* DEBUG */ X return NULL; X } X X if (paneAttr.override_redirect) X { X return NULL; X } X X /* X * If it's an already-existing window, but it's unmapped, just X * ignore it. X */ X if (fexisting && paneAttr.map_state != IsViewable) { 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 /* X * Get the WM_NORMAL_HINTS property. If it's short, then we have a X * pre-ICCCM client on our hands, so we'll have to fill in some of the X * missing values. X */ X normalHints = GetWindowProperty(dpy, window, XA_WM_NORMAL_HINTS, X 0L, LONG_LENGTH(NewXSizeHints), XA_WM_SIZE_HINTS, 0, X &nItems, &remain); X X /* clean up the normal hints we may have gotten back */ X if (normalHints == NULL) X { X /* X * We didn't get the property; punt. X */ X normalHints = MemNew(NewXSizeHints); X } X else if ( nItems == LONG_LENGTH(NewXSizeHints)-3 ) X { X /* REMIND check: does this section work properly on an X11R4 X * property? 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 NewXSizeHints *temp; X X temp = MemNew(NewXSizeHints); X bcopy(normalHints,temp, X sizeof(NewXSizeHints)-3*sizeof(long)); X XFree(normalHints); X normalHints = temp; X X if ((!fexisting) && ((normalHints->flags & (USPosition|PPosition)) X && IsInt16(normalHints->pad.x) X && IsInt16(normalHints->pad.y))) { X paneAttr.x = normalHints->pad.x; X paneAttr.y = normalHints->pad.y; X } X if ((!fexisting) && ((normalHints->flags & (USSize|PSize)) X && IsCard16(normalHints->pad.width) X && IsCard16(normalHints->pad.height) X && normalHints->pad.width >= MINSIZE X && normalHints->pad.height >= MINSIZE X && normalHints->pad.width < 2*DisplayWidth(dpy, X screen) X && normalHints->pad.height < 2*DisplayHeight(dpy, X screen))) X { X paneAttr.width = normalHints->pad.width; X paneAttr.height = normalHints->pad.height; X } X } X else if (nItems != LONG_LENGTH(NewXSizeHints)) X { X /* X * We got a property of the wrong length; punt. X */ X XFree(normalHints); X normalHints = MemNew(NewXSizeHints); X } X X /* If the hints structure did not have a min size set in X * it, zero the fields out so the MAX function below will X * work. We can't be sure that the min width and height X * fields have zero in them just because they haven't been X * set. X */ X if (!(normalHints->flags & PMinSize)) X { X normalHints->min_width = 0; X normalHints->min_height = 0; X } X X /* We set up the min size to be at least MINSIZE (for pane). */ X normalHints->flags |= PMinSize; X normalHints->min_width = MAX(MINSIZE, normalHints->min_width); X normalHints->min_height = MAX(MINSIZE, normalHints->min_height); X X cli->normHints = normalHints; X X if ( !fexisting && X !(normalHints->flags & USPosition) && X (!(normalHints->flags & PPosition) || X (GRV.PPositionCompat && paneAttr.x <= 1 && paneAttr.y <= 1))) X { X /* X * The hints don't specify a position, so we choose a suitable X * one, taking into account the window size (to prevent the window X * from lapping off the screen). X */ X calcPosition(dpy, screen, &paneAttr); X } X else if (!fexisting && (normalHints->flags & USPosition)) { X paneAttr.x += VirtualDesktopX; X paneAttr.y += VirtualDesktopY; X } X X if (!(normalHints->flags & PWinGravity)) X { X normalHints->win_gravity = NorthWestGravity; X normalHints->flags |= PWinGravity; X } X else if (normalHints->win_gravity == 0) X { X normalHints->win_gravity = NorthWestGravity; X } X X /* Get the WM_HINTS; if the property does not exist then we will use X * NULL throughout. All references to wmHints must be guarded for a X * NULL value. */ X cli->wmHints = GetWindowProperty(dpy, window, XA_WM_HINTS, 0L, X LONG_LENGTH(XWMHints), XA_WM_HINTS, 0, &nItems, &remain); X X if (cli->wmHints == NULL) X cli->wmHints = MemNew(XWMHints); X else if (nItems == sizeof(XWMHints)/sizeof(int)) X cli->hasMessages = True; X else X cli->hasMessages = False; X X /* Get the window class and instance strings */ X classInstance = GetWindowProperty(dpy, window, AtomClass, 0L, X 100000L, XA_STRING, 0, &nItems, &remain); X if (classInstance != NULL) X { X cli->wmInstance = MemNewString(classInstance); X cli->wmClass = MemNewString(classInstance + strlen(classInstance) + 1); X XFree(classInstance); X } X X /* Get the OpenLook window type and associated decorations */ X cli->wmDecors = getOLWinDecors(dpy, window, &(cli->olType),transient,cli->wmInstance, cli->wmClass); X X /* Get the protocols in which the client will participate */ X protocols = GetWindowProperty(dpy, window, AtomProtocols, 0L, X 3*LONG_LENGTH(Atom), XA_ATOM, 0, &nItems, &remain); X X cli->protocols = 0; X if (protocols != NULL) X { X for (count = 0; count < nItems; count++) X { X if (protocols[count] == AtomTakeFocus) X cli->protocols |= TAKE_FOCUS; X else if (protocols[count] == AtomSaveYourself) X cli->protocols |= SAVE_YOURSELF; X else if (protocols[count] == AtomDeleteWindow) X cli->protocols |= DELETE_WINDOW; X } X XFree(protocols); X } X X /* We need to check to see if this window is a group leader X * or not. If it is a group leader then we do nothing with X * it. If it is not a group leader, we need to find the group X * leader's frame and add ourselves as a follower. Note that X * on startup windows get mapped with leaders first. X */ X if ((cli->wmHints) && (cli->wmHints->flags & WindowGroupHint)) X { X cli->groupid = cli->wmHints->window_group; X } X else X { X cli->groupid = window; X } X if (cli->groupid == window) X cli->groupmask = GROUP_LEADER; X else X { X if ((cli->protocols & DELETE_WINDOW) && X (cli->wmDecors->flags & WMDecorationPushPin) && X (cli->wmDecors->menu_type == MENU_LIMITED)) 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 /* figure out what focus mode this window intends */ X if ((cli->wmHints) && (cli->wmHints->input)) X { X if (cli->protocols & TAKE_FOCUS) X cli->focusMode = LocallyActive; X else X cli->focusMode = Passive; X } X else /* wmHints->input == False */ X { X if (cli->protocols & TAKE_FOCUS) X cli->focusMode = GloballyActive; X else X cli->focusMode = NoInput; X } X X if (cli->groupid == VDM) X cli->sticky = TRUE; X else { X mc.class = cli->wmClass; X mc.instance = cli->wmInstance; X if (ListApply(GRV.StickyList,matchInstClass,&mc) != NULL) X cli->sticky = TRUE; X else cli->sticky = FALSE; X } X X /* officially set up the frame */ X winFrame = MakeFrame(cli,window,&paneAttr,fexisting); X X if (ourWinInfo == NULL) X { X /* officially set up the pane */ X winPane = MakePane(cli,winFrame,window,&paneAttr); X } X else X { X winPane = ourWinInfo; X (WinClass(winPane)->core.createcallback)(ourWinInfo,cli,winFrame); X } X X /* officially set up the icon */ X winIcon = MakeIcon(cli,window,&paneAttr,fexisting); X winIconPane = MakeIconPane(cli,winIcon,cli->wmHints); X X /* size and generally configure the frame window tree */ X FrameSetPosFromPane(winFrame,paneAttr.x,paneAttr.y); X WinCallConfig(dpy, winPane, NULL); X X /* size and generally configure the icon window tree */ X WinCallConfig(dpy, winIconPane, NULL); X if (cli->wmHints != NULL) X IconSetPos(winIcon,cli->wmHints->icon_x,cli->wmHints->icon_y); X else X IconSetPos(winIcon,0,0); X WinCallConfig(dpy, winIcon, NULL); X /* we manually move the icon pane window, since all the configuration has X * been done with the icon pane parented to root */ X WinRootPos(winIconPane, &tmpx, &tmpy); X XMoveWindow(dpy, winIconPane->core.self, tmpx, tmpy); X X /* Determine the proper initial state of the window. */ X if (fexisting && window != VDM) { X int state; X Window *iw; /* REMIND: ignored for now */ X /* For existing windows, look for a WM_STATE property. */ X if (ClientGetWMState(dpy, winPane->core.self, &state, &iw) X && state == IconicState) X initstate = IconicState; X else X initstate = NormalState; X } else { X /* For new windows, check the initial_state field of WM_HINTS. */ X /* This includes the VDM, which we created (so it exists) but X * for which the WM never set the state X */ 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 if (cli->groupmask == GROUP_DEPENDENT) X { X Client *leader = GroupLeader(cli->groupid); X if (leader != NULL) X initstate = leader->wmState; X } X X if (window == VDM) X VirtualSetUpFrame(cli, winFrame->core.self); X MakeVirtual(cli, dpy); X switch ( initstate ) { X case NormalState: X cli->wmState = NormalState; X XMapRaised(dpy, winFrame->core.self); X XMapRaised(dpy, winPane->core.self); X XMapRaised(dpy, cli->virtualWindow); X if (!fexisting) X FrameWarpPointer(cli); X break; X case IconicState: X cli->wmState = IconicState; X /* dependent group followers don't get their own icons */ X if (cli->groupmask != GROUP_DEPENDENT) X IconShow(cli, winIcon); X tmp = cli->virtualWindow; X cli->virtualWindow = cli->virtualInactive; X cli->virtualInactive = tmp; X break; X } X ClientSetWMState(cli); 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 */ void ReparentTree(dpy) Display *dpy; X{ X int numChildren; X Window *children, root, parent, w; X int ii; X Client *cli; X X children = NULL; X X if (XQueryTree(dpy, RootWindow(dpy, DefScreen), &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#ifdef DEBUG X printf("setting: %d\n",w); X#endif X cli = StateNew(dpy, 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(children); X} X X X/* X * StateNormIcon - transition a window to IconicState from NormalState X */ void StateNormIcon(cli) Client *cli; X{ X WinIconFrame *winIcon = cli->iconwin; 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,GROUP_LEADER|GROUP_DEPENDENT); X else X iconifyOne(cli,winIcon); X} X X/* X * StateIconNorm - transition a window to NormalState from IconicState X */ void StateIconNorm(cli) Client *cli; X{ X WinIconFrame *winIcon = cli->iconwin; X X /* don't do some other transition */ X if (cli->wmState != IconicState) X return; X X if (cli->groupmask == GROUP_LEADER) X GroupApply(cli->groupid,deiconifyOne,winIcon, X GROUP_LEADER|GROUP_DEPENDENT); X else X deiconifyOne(cli,winIcon); X X /* Unmap icons */ X IconHide(cli, winIcon); 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 */ void StateWithdrawn(cli) Client *cli; X{ X WinIconFrame *iconInfo = cli->iconwin; X WinPaneFrame *frameInfo; X WinPane *paneInfo; X Window pane; X Display *dpy = cli->dpy; X XClientMessageEvent cm; X X#ifdef DEBUG X printf("StateWithdrawn: cli %x\n", cli); X#endif X frameInfo = cli->framewin; X paneInfo = (WinPane*)(frameInfo->fcore.panewin); X pane = paneInfo->core.self; X iconInfo = cli->iconwin; X X if (cli->isFocus) { X cm.type = ClientMessage; X cm.message_type = AtomProtocols; X cm.format = 32; X cm.window = NoFocusWin; X cm.data.l[0] = AtomTakeFocus; X cm.data.l[1] = TimeFresh(frameInfo); X XSendEvent(dpy, NoFocusWin, False, 0, &cm); X FocusIndeterminate = True; X } X X /* Return the pointer if necessary */ X FrameUnwarpPointer(cli); X X /* Unmap the frame. */ X XUnmapWindow(dpy, frameInfo->core.self); X X /* Unmap the pane so we get a map X * request when the client wants a transition X * from Withdrawn to Normal or Iconic. X */ 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 DestroyClient(cli); X} END_OF_FILE if test 29221 -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 12 \(of 16\). cp /dev/null ark12isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 16 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 -- Dan Heller O'Reilly && Associates Z-Code Software Comp-sources-x: Senior Writer President comp-sources.x@uunet.uu.net argv@ora.com argv@zipcode.com