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