v12i068: olvwm - Open Look Virtual Window Manager, Part12/16
Scott Oaks - Sun Consulting NYC
sdo at soliado.East.Sun.COM
Mon Apr 29 03:31:11 AEST 1991
Submitted-by: sdo at 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 at 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 at uunet.uu.net
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list