v12i061: olvwm - Open Look Virtual Window Manager, Part05/16

Scott Oaks - Sun Consulting NYC sdo at soliado.East.Sun.COM
Mon Apr 29 03:29:33 AEST 1991


Submitted-by: sdo at soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC)
Posting-number: Volume 12, Issue 61
Archive-name: olvwm/part05

#! /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 5 (of 16)."
# Contents:  Notice.c winmenu.c winroot.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:05 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Notice.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Notice.c'\"
else
echo shar: Extracting \"'Notice.c'\" \(14629 characters\)
sed "s/^X//" >'Notice.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 *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static	char	sccsid[] = "@(#) Notice.c 25.6 90/05/22 Crucible";
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 <olgx/olgx.h>
X
X#include "olwm.h"
X#include "notice.h"
X#include "globals.h"
X
extern Graphics_info	*olgx_gistext;
extern Graphics_info	*olgx_gisbutton;
X
extern int		PointInRect();
X
X#define	NOTICE_EVENT_MASK	( ButtonPressMask | ButtonReleaseMask \
X				  | PointerMotionMask | KeyPressMask )
X#define	NOTICE_ATTR_MASK	( CWBorderPixel | CWBackPixel | CWSaveUnder )
X
X/* difference between inside beveled box and outside beveled box */
X#define BORDER_WIDTH		5	
X#define	MIN_BOX_SIDE		( 15 + BORDER_WIDTH )	/* betw side & text */
X#define	MIN_BOX_TOP		( 15 + BORDER_WIDTH )	/* betw top & text */
X#define	MIN_BOX_BOTTOM		( 15 + BORDER_WIDTH )	/* betw bot & text */
X#define MIN_BUTTON_SPACE	15		/* space between buttons */
X#define MIN_BUTTON_VSPACE	15		/* space above buttons */
X#define MIN_STRING_VSPACE	5		/* space above/below strings */
X
typedef struct {
X	int		x;
X	int		y;
X	unsigned int	width;		/* space taken up by text */
X	unsigned int	fullWidth;	/* width including endcaps */
X} noticeButtonDetails;
X
typedef struct {
X	Display			*dpy;
X	Window			window;
X	unsigned int		buttonHeight;
X	unsigned int		fontHeight;
X	unsigned int		boxHeight;
X	unsigned int		boxWidth;
X	int			x;
X	int			y;
X	int			totalButtonWidth;
X	noticeButtonDetails	*buttonInfo;
X} noticeBoxDetails;
X
static void calculateBoxDimensions();
static void drawNoticeBox();
static int  noticeEventLoop();
X
X/*
X * NoticeBox -- pop up a box which forces the user to answer
X * 		  a question using the buttons
X *
X * Arguments:
X *	dpy	    - pointer to current display
X *	screen	    - index to current screen
X *	noticeBox   - pointer to NoticeBox structure:
X *		numButtons	(number of buttons)
X *		defaultButton	(index into buttonText for mouse warp)
X *		buttonText	(array of strings for button text)
X *		numStrings	(number of descriptive strings)
X *		stringText	(array of strings for description)
X *		boxX		(box origin (-1 =use default/centered))
X *		boxY		(box origin (-1 =use default/centered))
X *
X *	Default placement of the box is centered in the display
X *	Returns -1 on failure (0 for 0th button, 1 for 1st button, etc.)
X */
int
UseNoticeBox( dpy, screen, noticeBox )
Display		*dpy;
int		screen;
NoticeBox	*noticeBox;
X{
X	XSetWindowAttributes	attributes;
X	int			buttonSelected;
X	noticeBoxDetails	boxDetails;
X	int			pointerX, pointerY;
X	int			dummyInt;
X	Window			dummyWin;
X	int			ii;
X	int			defaultButton;
X
X	/* set up window attributes structure */
X	attributes.border_pixel = GRV.Bg2Color;
X	attributes.background_pixel = GRV.Bg1Color;
X	attributes.save_under = True;
X
X	/* set up initial elements of boxDetails structure */
X	boxDetails.dpy = dpy;
X	boxDetails.buttonInfo = 
X		(noticeButtonDetails *)MemAlloc( noticeBox->numButtons 
X			* (unsigned int)sizeof(noticeButtonDetails) );
X
X	/* figure out size to make window and where to put it */
X	calculateBoxDimensions( screen, noticeBox, &boxDetails ); 
X
X	/* create window */
X	boxDetails.window = XCreateWindow( dpy, 
X					   RootWindow(dpy, 
X						      DefaultScreen(dpy)),
X				           boxDetails.x, boxDetails.y, 
X					   boxDetails.boxWidth, 
X					   boxDetails.boxHeight, 0, 
X					   DefaultDepth(dpy, DefaultScreen(dpy)), 
X					   InputOutput, CopyFromParent, 
X				           NOTICE_ATTR_MASK,
X				           &attributes );
X	
X	/* grab server and map window so box can be drawn here */
X	XGrabServer( dpy );
X	XMapRaised( dpy, boxDetails.window );
X
X	/* only beep if beeps are selected */
X	if (GRV.Beep != BeepNever)
X		XBell(dpy,100);
X
X	drawNoticeBox( noticeBox, &boxDetails );
X
X	/* save current mouse position */
X	XQueryPointer( dpy, RootWindow(dpy, DefaultScreen(dpy)),
X		       &dummyWin, &dummyWin,
X		       &pointerX, &pointerY,
X		       &dummyInt, &dummyInt, &dummyInt );
X
X	/* warp pointer to default button */
X	defaultButton = noticeBox->defaultButton;
X	if (GRV.PopupJumpCursor)
X	    XWarpPointer( dpy, None, boxDetails.window, 0, 0, 0, 0, 
X		      boxDetails.buttonInfo[defaultButton].x
X		        + boxDetails.buttonInfo[defaultButton].fullWidth/2, 
X		      boxDetails.buttonInfo[defaultButton].y
X		        + boxDetails.buttonHeight/2 );
X
X	XSelectInput( dpy, boxDetails.window, NOTICE_EVENT_MASK );
X	buttonSelected = noticeEventLoop( noticeBox, &boxDetails );
X
X	/* put the pointer back where we got it */
X	/* REMIND we need to test to see if the pointer is still within the 
X	* default button */
X	if (GRV.PopupJumpCursor)
X	    XWarpPointer( dpy, None, RootWindow(dpy, DefaultScreen(dpy)),
X		      0, 0, 0, 0, pointerX, pointerY );
X
X	/* free up the server as soon as we're done with it */
X	XUngrabServer( dpy );
X
X	/* destroy window */
X	XDestroyWindow( dpy, boxDetails.window );
X	MemFree( boxDetails.buttonInfo );
X	return( buttonSelected );
X}
X
X/*
X * noticeEventLoop -- watch for events while in notice box
X *
X */
static int
noticeEventLoop( noticeBox, details )
NoticeBox		*noticeBox;
noticeBoxDetails	*details;
X{
X	XEvent	event;
X	Bool	done = False;
X	int	buttonSelected = -1;
X	int	buttonDown = -1;
X	Bool	buttonDrawnDown = False;
X	int	ii;
X	int	buttonState;		/* OLGX_NORMAL or OLGX_DEFAULT */
X	int	keyboardGrabbed = False;
X
X	/* take control until we get an answer */
X	/* REMIND:  we're assuming the pointer can be grabbed, 
X	 * since we were successfully called from some menu 
X	 * REMIND: we may want to change the pointer during the grab
X	 */
X	XGrabPointer( details->dpy, details->window, False, 
X		      NOTICE_EVENT_MASK,
X		      GrabModeAsync, GrabModeAsync,
X		      None, None, CurrentTime );
X
X	/* REMIND: need to check return, in case someone else has
X	 * grabbed the keyboard (what to do then? just XGrabKey(),
X	 * or ignore keypress events?)
X	 */
X	keyboardGrabbed = ( GrabSuccess == XGrabKeyboard( 
X					details->dpy, details->window,
X					False, GrabModeAsync, 
X					GrabModeAsync, CurrentTime ) );
X
X	while ( !done )
X	{
X	    XNextEvent( details->dpy, &event );
X
X	    /*
X	     * Discard synthetic events
X	     *
X	     * This event loop is only interested in user events, so we
X	     * don't even bother checking to see if this event is a mouse
X	     * or keyboard event.
X	     */
X	    if (event.xany.send_event)
X		continue;
X
X	    switch (event.type)
X	    {
X		case ButtonPress:
X		    /* first check to see if we're even in the notice box */
X		    if ( !PointInRect( event.xbutton.x, 
X				       event.xbutton.y,
X				       0, 0,
X				       details->boxWidth,
X				       details->boxHeight ) )
X			break;
X
X		    /* if on one of the notice buttons, depress it */
X		    for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X		    {
X			if ( PointInRect( event.xbutton.x, 
X					  event.xbutton.y,
X					  details->buttonInfo[ii].x, 
X					  details->buttonInfo[ii].y,
X					  details->buttonInfo[ii].fullWidth,
X					  details->buttonHeight ) )
X			{
X			    buttonDown = ii;
X			    buttonDrawnDown = True;
X			    olgx_draw_button( olgx_gisbutton, 
X					details->window, 
X					details->buttonInfo[ii].x, 
X					details->buttonInfo[ii].y,
X					details->buttonInfo[ii].fullWidth, 0,
X					noticeBox->buttonText[ii], 
X					OLGX_INVOKED );
X			    break;
X			}
X		    }
X		    break;
X
X		case ButtonRelease:
X		    /* only a depressed button can be selected */
X		    if ( PointInRect( event.xbutton.x, 
X				event.xbutton.y,
X				details->buttonInfo[buttonDown].x, 
X				details->buttonInfo[buttonDown].y,
X				details->buttonInfo[buttonDown].fullWidth,
X				details->buttonHeight ) )
X		    {
X			buttonSelected = buttonDown;
X			done = True;
X		    }
X
X		    if (!done)
X		    {
X			buttonDown = -1;
X			buttonDrawnDown = False;
X		    }
X
X		    break;
X		
X		case MotionNotify:
X		    /* check state of buttons */
X		    if ( buttonDown < 0 )
X			break;
X
X		    if ( PointInRect( event.xbutton.x, 
X				event.xbutton.y,
X				details->buttonInfo[buttonDown].x, 
X				details->buttonInfo[buttonDown].y,
X			        details->buttonInfo[buttonDown].fullWidth,
X			        details->buttonHeight ) )
X		    {
X			/* Moved within button down at start of motion.
X			 * If the button was is drawn undepressed,
X			 * make it go down.
X			 */
X			if ( !buttonDrawnDown )
X			{
X			    olgx_draw_button( olgx_gisbutton, 
X				details->window, 
X				details->buttonInfo[buttonDown].x, 
X				details->buttonInfo[buttonDown].y,
X				details->buttonInfo[buttonDown].fullWidth, 0,
X				noticeBox->buttonText[buttonDown], 
X				OLGX_INVOKED );
X
X			    buttonDrawnDown = True;
X			}
X		    }
X		    else
X		    {
X			/* Moved out of button that was down at start.
X			 * If the button was previously drawn down,
X			 * draw it undepressed.
X			 */
X			if ( buttonDrawnDown )
X			{
X			    /* check if needs "default" indicator */
X			    if ( noticeBox->defaultButton == buttonDown )
X			    	buttonState = OLGX_DEFAULT;
X			    else
X			    	buttonState = OLGX_NORMAL;
X
X			    olgx_draw_button( olgx_gisbutton, 
X				    details->window, 
X				    details->buttonInfo[buttonDown].x,
X				    details->buttonInfo[buttonDown].y,
X				    details->buttonInfo[buttonDown].fullWidth,
X				    0, noticeBox->buttonText[buttonDown], 
X				    buttonState | OLGX_ERASE );
X
X			    buttonDrawnDown = False;
X			}
X		    }
X
X		    break;
X
X		case KeyPress:
X		    if (keyboardGrabbed &&
X			event.xkey.keycode == GRV.ConfirmKey.keycode )
X		    {
X			buttonSelected = noticeBox->defaultButton;
X			done = True;
X		    }
X
X		    break;
X
X		default:
X		    break;
X	    }
X	}
X
X	/* release control */
X	XUngrabPointer( details->dpy, CurrentTime );
X	if ( keyboardGrabbed )
X		XUngrabKeyboard( details->dpy, CurrentTime );
X	XFlush( details->dpy );
X
X	return( buttonSelected);
X}
X
X/*
X * calculateBoxDimensions -- determine size of box needed, etc. based on
X * 		information passed in in noticeBox structure.  Return
X *		values in boxDetails structure.
X */
static void
calculateBoxDimensions( screen, noticeBox, boxDetails )
int			screen;
NoticeBox		*noticeBox;
noticeBoxDetails	*boxDetails;
X{
X	unsigned int	displayWidth, displayHeight;
X	int		longestStringLength = 0;
X	int		totalButtonWidth = 0;
X	int		ii;
X
X	boxDetails->fontHeight = GRV.TextFontInfo->ascent + 
X					GRV.TextFontInfo->descent;
X
X	/* calculate the width of the text which appears inside the button */
X	for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X	{
X		boxDetails->buttonInfo[ii].width = 
X			XTextWidth( GRV.ButtonFontInfo, 
X				    noticeBox->buttonText[ii], 
X				    strlen(noticeBox->buttonText[ii]) );
X		boxDetails->buttonInfo[ii].fullWidth = 
X			boxDetails->buttonInfo[ii].width 
X				+ 2 * ButtonEndcap_Width(olgx_gisbutton);
X	}
X
X	/* add together widths of all the buttons */
X	for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X		totalButtonWidth += boxDetails->buttonInfo[ii].fullWidth;
X	boxDetails->totalButtonWidth = totalButtonWidth;
X
X	/* figure out which descriptive string is longest */
X	for ( ii = 0 ; ii < noticeBox->numStrings ; ii++ )
X		longestStringLength = 
X			MAX( longestStringLength,
X			     XTextWidth( GRV.TextFontInfo, 
X				         noticeBox->stringText[ii], 
X				         strlen(noticeBox->stringText[ii]) ) );
X
X	/* 
X	 * REMIND: this calculation assumes all the buttons are
X	 * on the same line
X	 */
X	boxDetails->boxWidth = 2 * MIN_BOX_SIDE 
X		   + MAX( longestStringLength,
X			  totalButtonWidth + 
X			      /* amount of space between all the buttons */
X			      MIN_BUTTON_SPACE * (noticeBox->numButtons - 1) );
X
X	boxDetails->buttonHeight = Button_Height(olgx_gisbutton);
X
X	boxDetails->boxHeight = MIN_BOX_TOP + MIN_BOX_BOTTOM
X		    + ( noticeBox->numStrings * boxDetails->fontHeight )
X		    /* amount of space vertically between all the strings */
X		    + ( (noticeBox->numStrings - 1) * MIN_STRING_VSPACE )
X		    + MIN_BUTTON_VSPACE + boxDetails->buttonHeight;
X
X	displayWidth = DisplayWidth( boxDetails->dpy, screen );
X	displayHeight = DisplayHeight( boxDetails->dpy, screen );
X
X	/* if not set, create default "origin" for box: centered */
X	boxDetails->x = ( noticeBox->boxX == -1 ) 
X			    ? (int)( displayWidth - boxDetails->boxWidth )/2 
X			    : noticeBox->boxX ;
X	boxDetails->y = ( noticeBox->boxY == -1 ) 
X			    ? (int)( displayHeight - boxDetails->boxHeight )/2 
X			    : noticeBox->boxY ;
X
X}
X
X/*
X * drawNoticeBox -- draw box outline, strings, and buttons using information
X *		in noticeBox and boxDetails structures which are passed in.
X *		Location of buttons (x, y) are set in boxDetails structure
X *		for use later (mouse warping, determining pointer position).
X */
static void
drawNoticeBox( noticeBox, boxDetails )
NoticeBox		*noticeBox;
noticeBoxDetails	*boxDetails;
X{
X	int	ii;
X	int	buttonX, buttonY;
X	int	buttonState;		/* OLGX_NORMAL or OLGX_DEFAULT */
X
X	/* draw beveled box */
X	olgx_draw_box( olgx_gistext, boxDetails->window, 0, 0, 
X		       boxDetails->boxWidth, boxDetails->boxHeight, 
X		       OLGX_NORMAL, True );
X
X	olgx_draw_box( olgx_gistext, boxDetails->window, 
X		       BORDER_WIDTH, BORDER_WIDTH, 
X		       boxDetails->boxWidth - 2 * BORDER_WIDTH, 
X		       boxDetails->boxHeight - 2 * BORDER_WIDTH, 
X		       OLGX_NORMAL, True );
X
X	/* draw descriptive text 
X	 * REMIND: all strings are along the left edge (MIN_BOX_SIDE) 
X	 */
X	for ( ii = 0 ; ii < noticeBox->numStrings ; ii++ )
X		olgx_draw_text( olgx_gistext, boxDetails->window, 
X			noticeBox->stringText[ii], MIN_BOX_SIDE,
X			/* need to move each line further down the screen */
X			MIN_BOX_TOP + GRV.TextFontInfo->ascent * ( ii + 1 )
X				+ ( MIN_STRING_VSPACE * ii ),
X			0, False, OLGX_NORMAL );
X
X	/* put buttons in - notice that it's a single row */
X	/* row of buttons should be centered within available space,
X	 * assuming MIN_BUTTON_SPACE between each of the them
X	 */
X	buttonX = ( boxDetails->boxWidth - (boxDetails->totalButtonWidth 
X		        + MIN_BUTTON_SPACE * (noticeBox->numButtons - 1)) )/2;
X	/* this calculates from the bottom of the box */
X	buttonY = ( boxDetails->boxHeight - 
X			( MIN_BOX_BOTTOM + boxDetails->buttonHeight ) );
X	for ( ii = 0 ; ii < noticeBox->numButtons ; ii++ )
X	{
X		if ( noticeBox->defaultButton == ii )
X			buttonState = OLGX_DEFAULT;
X		else
X			buttonState = OLGX_NORMAL;
X
X		/* save button's x, y values for use later */
X		boxDetails->buttonInfo[ii].x = buttonX;
X		boxDetails->buttonInfo[ii].y = buttonY;
X
X		olgx_draw_button( olgx_gisbutton, boxDetails->window, 
X				  buttonX, buttonY,
X				  boxDetails->buttonInfo[ii].fullWidth, 0,
X				  noticeBox->buttonText[ii], 
X				  buttonState );
X
X		/* set up buttonX for next button */ 
X		buttonX = buttonX + boxDetails->buttonInfo[ii].fullWidth
X				+ MIN_BUTTON_SPACE;
X	}
X}
END_OF_FILE
if test 14629 -ne `wc -c <'Notice.c'`; then
    echo shar: \"'Notice.c'\" unpacked with wrong size!
fi
# end of 'Notice.c'
fi
if test -f 'winmenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winmenu.c'\"
else
echo shar: Extracting \"'winmenu.c'\" \(13410 characters\)
sed "s/^X//" >'winmenu.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 *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)winmenu.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winmenu.c 25.4 90/05/18 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 <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "globals.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Atom AtomDecorAdd;
extern Atom AtomDecorHeader;
extern Atom AtomDecorPin;
extern Atom AtomDeleteWindow;
extern Atom AtomMenuLimited;
extern Atom AtomProtocols;
extern Atom AtomPushpinState;
extern Atom AtomWinAttr;
extern Atom AtomWTOther;
X
extern Window NoFocusWin;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* function vector for menu windows */
static ClassMenu classMenu;
X
static int bindex_last; 	/* set to last menu button pressed; cleared
X				 * when button released or a submenu is
X				 * brought up */
X
X/*
X * after_info_t
X *
X * REMIND this is an abomination.  This structure simply holds the arguments
X * for the "afterProcessing" function, which should get called when a pop-up
X * menu is finished tracking.  Unfortunately, the architecture of this pinned
X * menu system assumes that popping up a menu is synchronous, when in fact it
X * just installs an event interposer and returns immediately.  The solution is
X * to pass along this information as a closure and have the information passed
X * back by the menu "sync" function.
X */
X
typedef struct {
X    Display *dpy;
X    Menu *menu;
X    WinMenu *winInfo;
X    int bindex;
X} after_info_t;
X
static after_info_t afterInfo;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
static void
afterProcessing(dpy, menu, winInfo, bindex)
Display *dpy;
Menu *menu;
WinMenu *winInfo;
int bindex;
X{
X        unsigned long   nItems, remain;
X        long    *pinState;
X
X        /* unhighlight button */
X        if ((bindex >= 0) && (bindex < menu->buttonCount))
X                SetButton(dpy, menu, bindex, False);
X
X        /* if our push-pin is out then we should go away */
X	pinState = GetWindowProperty(dpy, winInfo->core.self, AtomPushpinState,
X		0L, LONG_LENGTH(long), XA_INTEGER, 0, &nItems, &remain);
X
X	if (pinState != NULL)
X	{
X            if (*pinState == PIN_OUT)     /* pin is out */
X            {
X                /* make our window die */
X		ClientKill(winInfo->core.client,False);
X            }
X            XFree(pinState);
X	}
X}
X
X
static void
afterProcWrapper( i )
X    after_info_t *i;
X{
X    afterProcessing( i->dpy, i->menu, i->winInfo, i->bindex );
X}
X
X/* pressButton -- a user has moved the pointer in such a way that a
X *      button should be pressed (that is, highlighted, ready for
X *      activation.  If any other button is pressed, unpress that button
X *      along the way.
X */
static int
pressButton(dpy, menu, winInfo, event, bindex, mbutton)
Display *dpy;
Menu *menu;
WinMenu *winInfo;
XXEvent *event;
int bindex;
int mbutton;
X{
X        if ((mbutton == MB_MENU) || (mbutton = MB_SELECT))
X        {
X                SetButton(dpy, menu, bindex, True);
X
X                if ((menu->buttons[bindex].stacked == True) &&
X                    (menu->buttons[bindex].action.submenu != NULL) &&
X                    (mbutton == MB_MENU))
X                {
X                        afterInfo.dpy = dpy;
X                        afterInfo.menu = menu;
X                        afterInfo.winInfo = winInfo;
X                        afterInfo.bindex = bindex;
X                        MenuShowSync(dpy, winInfo,
X                            (Menu *)(menu->buttons[bindex].action.submenu),
X                            event, afterProcWrapper, &afterInfo);
X                }
X        }
X}
X
X
X
X/* findButton - find the button corresponding to an x,y position
X *              modifies the x,y position to the correct popup location
X *              for cascaded menus.
X * returns: button index or -1 if button not found
X */
static int
findButton(menu, ex, ey, winInfo)
Menu *menu;
int *ex, *ey;
WinMenu *winInfo;
X{
X        int bindex;
X
X        /* figure out if the button press is in a button */
X        for (bindex=0; bindex < menu->buttonCount; bindex++)
X        {
X                if (PointInRect(*ex, *ey,
X                                menu->buttons[bindex].activeX,
X                                menu->buttons[bindex].activeY,
X                                menu->buttons[bindex].activeW,
X                                menu->buttons[bindex].activeH))
X                {
X			WinRootPos(winInfo, ex, ey);
X                        *ex += menu->buttons[bindex].activeX +
X                             menu->buttons[bindex].activeW;
X                        *ey += menu->buttons[bindex].activeY;
X                        return bindex;
X                }
X        }
X        return -1;
X}
X
X
X/***************************************************************************
X*  private event functions
X***************************************************************************/
X
X/* 
X * eventButtonPress  - a button has gone down.
X */
static int
eventButtonPress(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinMenu	*winInfo;
X{
X	Menu *menu = (Menu *)(winInfo->menu);
X	int bindex;
X	int ex, ey;
X
X	ex = event->xbutton.x;
X	ey = event->xbutton.y;
X	bindex = findButton(menu, &ex, &ey, winInfo);
X	bindex_last = bindex;
X	if (bindex != -1)
X	    pressButton(dpy, menu, winInfo, event, bindex, MouseButton(dpy,event));
X}
X
X/* 
X * eventButtonRelease  - a button has gone up
X */
static int
eventButtonRelease(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinMenu	*winInfo;
X{
X	Menu *menu = (Menu *)(winInfo->menu);
X	int bindex;
X	int ex, ey;
X
X	ex = event->xbutton.x;
X	ey = event->xbutton.y;
X
X	if (MouseButton(dpy,event) == MB_ADJUST)
X		return;
X
X	bindex = findButton(menu, &ex, &ey, winInfo);
X
X	/* Make sure that the button under the ButtonRelease is the
X	 * same one that the ButtonPress went down on.
X	 */
X	if ((bindex == bindex_last) &&
X	    (bindex_last >= 0) &&
X	    (bindex_last < menu->buttonCount))
X		ExecButtonAction(dpy,winInfo,menu,bindex,True);
X
X	afterProcessing(dpy,menu,winInfo,bindex_last);
X}
X
X/* 
X * eventClientMessage  - handle a DELETE_WINDOW message.
X */
static int
eventClientMessage(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinMenu	*winInfo;
X{
X    if ((event->xclient.message_type == AtomProtocols) &&
X        (event->xclient.data.l[0] == AtomDeleteWindow))
X    {
X	DestroyClient(winInfo->core.client);
X    }
X}
X
X/* 
X * eventPropertyNotify  - the main window manager has changed a property on
X *	our pane; handle the property.
X */
static int
eventPropertyNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinMenu	*winInfo;
X{
X	ClientDistributeProperty(winInfo->core.client, event);
X}
X
X
X/*
X * drawMenu -- draw the menu window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawMenu(dpy, winInfo)
Display	*dpy;
WinMenu *winInfo;
X{
X	DrawMenu(dpy, winInfo->menu);
X}
X
X
X/*
X * DestroyMenu -- destroy the menu window resources and free any allocated
X *	data.
X */
static int
destroyMenu(dpy, winInfo)
Display	*dpy;
WinMenu *winInfo;
X{
X	/* free our data and throw away window */
X	((Menu *)winInfo->menu)->originalMenu->currentlyDisplayed = False;
X	MemFree(winInfo->menu);
X	XUndefineCursor(dpy, winInfo->core.self);
X	XDestroyWindow(dpy, winInfo->core.self);
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X
X/* 
X * focusselectMenu - the focus or selection state has changed
X */
static int
focusselectMenu(dpy, winInfo, selected)
Display *dpy;
WinMenu *winInfo;
Bool selected;
X{
X        (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * newconfigMenu - recomputes the size of the menu window
X *	Note that menus don't change size, so this is a no-op.
X */
static int 
newconfigMenu(win, pxcre)
WinMenu *win;
XXConfigureRequestEvent *pxcre;
X{
X	return win->core.dirtyconfig;
X}
X
X/* menuSetParent -- callback during creation.  Since menus are internally-
X * 	created windows we must fix up certain fields that are only available
X *	after the window is mapped.
X */
static int
menuSetParent(w,cli,par)
WinMenu *w;
Client *cli;
WinGenericFrame *par;
X{
X    w->core.client = cli;
X    WinAddChild(par,w);
X    XReparentWindow(cli->dpy, w->core.self, par->core.self, w->core.x, w->core.y);
X    par->fcore.panewin = (WinGenericPane *)w;
X}
X
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeMenu  -- create the pinned menu's menu window (around which we'll put
X *	a frame).    The window is mapped during the transition to normal
X *	state.
X */
WinMenu *
MakeMenu(dpy, junkwindow, menu, idx)
Display	*dpy;
WinGeneric *junkwindow;
Menu *menu;
int idx;
X{
X	WinMenu *w;
X	Window win;
X        unsigned long valuemask;
X        XSetWindowAttributes attributes;
X	Menu *originalMenu;
X	Atom atomList[3];
X	NewXSizeHints sizeHints;
X	XWMHints wmHints;
X
X	/* save a pointer to the menu we're putting in the window.
X	 * We will duplicate the structure later on and set the
X	 * currentlyDisplayed flag in the original.
X	 */
X	originalMenu = menu;
X
X	/* create the associated structure */
X	w = MemNew(WinMenu);
X	w->class = &classMenu;
X	w->core.kind = WIN_MENU;
X	w->core.children = NULL;
X	w->core.x = menu->x;	
X	w->core.y = menu->y;
X	w->core.width = menu->width;
X	w->core.height = menu->height - menu->titleHeight;
X	w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
X	w->core.exposures = NULL;
X
X	/* create the actual window */
X        attributes.event_mask = ButtonReleaseMask | ButtonPressMask | 
X		ExposureMask | PropertyChangeMask;
X        attributes.background_pixel = GRV.Bg1Color;
X	attributes.cursor = GRV.MenuPointer;
X        valuemask = CWEventMask | CWBackPixel | CWCursor;
X
X        win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
X                        w->core.x, w->core.y,
X			w->core.width, w->core.height,
X                        0,
X                        DefaultDepth(dpy, DefaultScreen(dpy)),
X                        InputOutput,
X                        DefaultVisual(dpy, DefaultScreen(dpy)),
X                        valuemask,
X                        &attributes);
X	w->core.self = win;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	/* first we set the properties defining what kind of OpenLook window it is */
X	atomList[0] = AtomWTOther;
X	atomList[1] = AtomMenuLimited;
X	atomList[2] = (Atom) PIN_IN;
X	XChangeProperty(dpy, win, AtomWinAttr, AtomWinAttr,
X		32, PropModeReplace, (unsigned char *)atomList, 3);
X
X	/* add a push-pin */
X	atomList[0] = AtomDecorPin;
X	atomList[1] = AtomDecorHeader;
X	XChangeProperty(dpy, win, AtomDecorAdd, XA_ATOM,
X		32, PropModeReplace, (unsigned char *)atomList, 2);
X
X	/* set protocols */
X	atomList[0] = AtomDeleteWindow;
X	XChangeProperty(dpy, win, AtomProtocols, XA_ATOM,
X		32, PropModeReplace, (unsigned char *)atomList, 1);
X
X	/* now set the size hints */
X	sizeHints.flags = USPosition | USSize;
X	XChangeProperty(dpy, win, XA_WM_NORMAL_HINTS, XA_WM_SIZE_HINTS, 
X		32, PropModeReplace, (unsigned char *)&sizeHints,
X		sizeof(NewXSizeHints)/sizeof(long));
X
X	/* and the wmHints */
X	wmHints.flags = InputHint | StateHint | WindowGroupHint;
X	wmHints.initial_state = NormalState;
X	wmHints.input = False;
X	   /*
X	    * REMIND this is hack to make StateNew think we're a dependent 
X	    * follower, and thus not iconify us.
X	    */
X	wmHints.window_group = NoFocusWin;
X
X	XChangeProperty(dpy, win, XA_WM_HINTS, XA_WM_HINTS, 
X		32, PropModeReplace, (unsigned char *)&wmHints,
X		sizeof(XWMHints)/sizeof(long));
X
X	XStoreName(dpy, win, menu->title);
X
X	/* create a private, duplicate menu structure */
X	w->menu = (void *)MemNew(Menu);
X	*(Menu *)(w->menu) = *menu;
X	menu = (Menu *)(w->menu);
X	menu->originalMenu = originalMenu;
X	originalMenu->currentlyDisplayed = True;
X	menu->title = NULL;
X	menu->x = menu->y = 0;
X	menu->titleHeight = menu->titleWidth = 0;
X	menu->height = w->core.height;
X	menu->window = win;
X
X	StateNew(dpy, win, False, w);
X
X	return w;
X}
X
void
MenuInit(dpy)
Display *dpy;
X{
X	classMenu.core.kind = WIN_MENU;
X	classMenu.core.xevents[ButtonPress] = eventButtonPress;
X	classMenu.core.xevents[ButtonRelease] = eventButtonRelease;
X	classMenu.core.xevents[ClientMessage] = eventClientMessage;
X	classMenu.core.xevents[PropertyNotify] = eventPropertyNotify;
X	classMenu.core.xevents[Expose] = WinEventExpose;
X	classMenu.core.focusfunc = focusselectMenu;
X	classMenu.core.drawfunc = drawMenu;
X	classMenu.core.destroyfunc = destroyMenu;
X	classMenu.core.selectfunc = focusselectMenu;
X	classMenu.core.newconfigfunc = newconfigMenu;
X	classMenu.core.newposfunc = WinNewPosFunc;
X	classMenu.core.setconfigfunc = WinSetConfigFunc;
X	classMenu.core.createcallback = menuSetParent;
X	classMenu.core.heightfunc = NULL;
X	classMenu.core.widthfunc = NULL;
X	classMenu.pcore.setsizefunc = NULL;
X
X}
END_OF_FILE
if test 13410 -ne `wc -c <'winmenu.c'`; then
    echo shar: \"'winmenu.c'\" unpacked with wrong size!
fi
# end of 'winmenu.c'
fi
if test -f 'winroot.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winroot.c'\"
else
echo shar: Extracting \"'winroot.c'\" \(14250 characters\)
sed "s/^X//" >'winroot.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 *	Written for Sun Microsystems by Crucible, Santa Cruz, CA.
X */
X
static char     sccsid[] = "@(#)winroot.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winroot.c 25.8 90/05/22 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 <X11/Xresource.h>
X#include <olgx/olgx.h>
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "menu.h"
X#include "globals.h"
X#include "group.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Menu *RootMenu;
extern Window	NoFocusWin;
extern Time	SelectionTime;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
static int lastButton;
static XEvent buttonPressEvent;
static ClassRoot classRoot;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
static void
redistributeKeystroke( dpy, e )
Display *dpy;
XXEvent *e;
X{
X    XKeyEvent *ke = (XKeyEvent *) e;
X    Window childwin, dstwin, srcwin;
X    int srcx, srcy, dstx, dsty;
X    static Bool pressreceived = False;
X    static XKeyEvent pressevent;
X
X    if ( ke->type == KeyPress ) {
X	if ( pressreceived == False ) {
X	    srcwin = ke->window;
X	    dstwin = ke->window;
X	    srcx = ke->x;
X	    srcy = ke->y;
X	    while (1) {
X		XTranslateCoordinates( dpy, srcwin, dstwin, srcx, srcy,
X		    &dstx, &dsty, &childwin );
X		if ( childwin == None )
X		    break;
X		srcx = dstx;
X		srcy = dsty;
X		srcwin = dstwin;
X		dstwin = childwin;
X	    }
X	    pressevent = *ke;
X	    pressevent.x = dstx;
X	    pressevent.y = dsty;
X	    pressevent.window = dstwin;
X	    pressevent.subwindow = None;
X	    pressreceived = True;
X	}
X    } else {
X	if ( pressreceived == True ) {
X#ifdef notdef
X	    XUngrabKeyboard( dpy, pressevent.time );
X#endif /* notdef */
X	    XSendEvent( dpy, pressevent.window, True, 
X		KeyPressMask, &pressevent );
X	    XTranslateCoordinates( dpy, ke->window, pressevent.window,
X		ke->x, ke->y, &dstx, &dsty, &childwin );
X	    ke->x = dstx;
X	    ke->y = dsty;
X	    ke->window = pressevent.window;
X	    ke->subwindow = None;
X	    XSendEvent( dpy, pressevent.window, True, KeyPressMask, ke );
X	}
X	pressreceived = False;
X    }
X}
X
X
static Bool
matchKeystrokeToSpec(event,spec)
X    XEvent *event;
X    KeySpec *spec;
X{
X    return (spec->keycode == event->xkey.keycode &&
X	    (spec->modmask == AnyModifier ||
X	     spec->modmask == event->xkey.state));
X}
X
X
static void
rootKeystroke(dpy,pEvent)
Display	*dpy;
XXEvent *pEvent;
X{
X    Window		child;
X    WinGeneric		*childInfo;
X    Client		*childClient;
X    Bool		samescreen;
X    int			destX, destY;
X
X    samescreen = XTranslateCoordinates(dpy,
X	DefaultRootWindow(dpy), DefaultRootWindow(dpy),
X	pEvent->xkey.x, pEvent->xkey.y, &destX, &destY, &child );
X
X    if (!samescreen)
X	return;
X
X    if (pEvent->type == KeyPress && child != None &&
X	matchKeystrokeToSpec(pEvent, &(GRV.FrontKey))) {
X	XWindowChanges xwc;
X	xwc.stack_mode = Opposite;
X	XConfigureWindow( dpy, child, CWStackMode, &xwc );
X	childInfo = WIGetInfo(child);
X	childClient = childInfo->core.client;
X	if (childClient && childClient->virtualWindow) {
X	    XConfigureWindow(dpy, childClient->virtualWindow, CWStackMode, &xwc);
X	}
X    } else if (matchKeystrokeToSpec(pEvent, &(GRV.HelpKey))) {
X	redistributeKeystroke( dpy, pEvent );
X    } else if (pEvent->type == KeyPress && child != None &&
X	       matchKeystrokeToSpec(pEvent, &(GRV.OpenKey))) {
X	childInfo = WIGetInfo(child);
X	if ( childInfo ) {
X	    childClient = childInfo->core.client;
X	    if (childClient != NULL)
X	    {
X	        if ( childClient->wmState == IconicState ) {
X		    StateIconNorm(childClient);
X	        } else {
X		    /* check for base vs. popup window */
X	    	    if (childClient->groupmask == GROUP_DEPENDENT) {
X		        /*
X		         * REMIND: passing (Menu *)NULL is bogus.
X		         * Also, should pass DA_THIS instead of 0.
X		         */
X		        DismissAction(dpy,childInfo,(Menu *)NULL,0,False);
X		    } else {
X		        StateNormIcon(childClient);
X		    }
X    	        }
X	    }
X	}
X    } else if (pEvent->type == KeyPress &&
X	       matchKeystrokeToSpec(pEvent, &(GRV.ColorLockKey))) {
X	InstallPointerColormap(dpy, pEvent->xkey.root, pEvent->xkey.x_root,
X			       pEvent->xkey.y_root, True);
X    } else if (pEvent->type == KeyPress &&
X	       matchKeystrokeToSpec(pEvent, &(GRV.ColorUnlockKey))) {
X	UnlockColormap(dpy);
X    }
X}
X
X
static void
rootProperty( dpy, pEvent )
Display	*dpy;
XXEvent	*pEvent;
X{
X	unsigned long	nitems, remain;
X	char 		*resourceString;
X	XrmDatabase	serverDB;
X
X	/* make sure that the property was the one we care about and
X	 * changed (as opposed to deleted)
X	 */
X	if ( (pEvent->xproperty.atom != XA_RESOURCE_MANAGER) 
X	     || (pEvent->xproperty.state != PropertyNewValue) )
X		return;
X
X	resourceString = GetWindowProperty(dpy, RootWindow(dpy, DefaultScreen(dpy)),
X		XA_RESOURCE_MANAGER, 0L, 100000000L, 
X		/* REMIND what should the length really be ? */
X		XA_STRING, 0, &nitems, &remain);
X	if (resourceString != NULL)
X        {
X		serverDB = XrmGetStringDatabase( resourceString );
X		UpdateDBValues( dpy, serverDB );
X		XFree( resourceString );
X        }
X}
X
X
X/* 
X * eventEnterNotify - the pointer has entered the root window
X */
static int
eventEnterNotify(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X    ColorWindowCrossing(dpy, pEvent, winInfo);
X}
X
X/* 
X * eventConfigureRequest - a client wants to change configuration
X */
static int
eventConfigureRequest(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X#define ConfEvent	(pEvent->xconfigurerequest)
X	if ((winInfo = WIGetInfo(ConfEvent.window)) == NULL)
X	{
X		/* we don't know about this window, so let it go */
X		ClientConfigure(NULL,NULL,pEvent);
X	}
X	else /* OBSOLETE: if (ConfEvent.value_mask & (CWX | CWY | CWWidth | CWHeight)) */
X	{
X		/* configure the window and its frame */
X		ClientConfigure(winInfo->core.client,winInfo,pEvent);
X	}
X	/* REMIND doesn't handle stacking or border width yet */
X}
X
X/* 
X * eventMapRequest - a new client is mapping
X */
static int
eventMapRequest(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X#define MapEvent	(pEvent->xmap)
X	StateNew(dpy, MapEvent.window, False, NULL);
X}
X
X/* 
X * eventMotionNotify - the pointer is moving
X */
static int
eventMotionNotify(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X	short			boxX, boxY, boxW, boxH;
X	clientInBoxClosure	cibclosure;
X	Time			timestamp;
X
X	if (!pEvent->xmotion.same_screen)
X	    return;
X
X	/* If the user hasn't moved more than the threshold
X	 * amount, break out of here.  REMIND  Also, if we get a 
X	 * MotionNotify event with no buttons down, we ignore it.
X	 * Ideally this shouldn't happen, but some areas of the code
X	 * still leave the pointer grabbed even after all the buttons
X	 * have gone up.
X	 */
X	if ((ABS(pEvent->xmotion.x - buttonPressEvent.xbutton.x) < 
X	     GRV.MoveThreshold) &&
X	    (ABS(pEvent->xmotion.y - buttonPressEvent.xbutton.y) < 
X	     GRV.MoveThreshold))
X	    return;
X	if (pEvent->xmotion.state == 0)
X	   return;
X
X	switch(lastButton)
X	{
X	case MB_SELECT:	
X		ClearSelections(dpy);
X
X		/* need to trace a bounding box */
X		if (TraceBoundingBox(dpy, &buttonPressEvent, 
X			&boxX, &boxY, &boxW, &boxH, &timestamp))
X		{
X		    /* select all frames or icons in the box */
X		    cibclosure.dpy = dpy;
X		    cibclosure.func = AddSelection;
X		    cibclosure.bx = boxX;
X		    cibclosure.by = boxY;
X		    cibclosure.bw = boxW;
X		    cibclosure.bh = boxH;
X		    cibclosure.timestamp = timestamp;
X		    ListApply(ActiveClientList, ClientInBox, &cibclosure);
X		}
X		break;
X
X	case MB_ADJUST:	
X		/* bounding box with toggles */
X		if (TraceBoundingBox(dpy, &buttonPressEvent, 
X			&boxX, &boxY, &boxW, &boxH, &timestamp))
X		{
X		    cibclosure.dpy = dpy;
X		    cibclosure.func = ToggleSelection;
X		    cibclosure.bx = boxX;
X		    cibclosure.by = boxY;
X		    cibclosure.bw = boxW;
X		    cibclosure.bh = boxH;
X		    cibclosure.timestamp = timestamp;
X		    ListApply(ActiveClientList, ClientInBox, &cibclosure);
X		}
X		break;
X	}
X}
X
X/* 
X * eventButtonRelease - handle a click
X */
static int
eventButtonRelease(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X	/* This only happens if we did NOT get a motion notify
X	 * after the last button press. 
X	 */
X	if (MouseButton(dpy, pEvent) == MB_SELECT)
X	{
X		/* Clear the selection list. */
X		ClearSelections(dpy);
X
X		/* Set the input focus to the root window. */
X		XSetInputFocus(dpy, NoFocusWin, RevertToPointerRoot,
X			       pEvent->xbutton.time);
X
X		/* Tell the server that we are now the current
X		 * selection owner.  This might be necessary if
X		 * the user had selected some text in an xterm
X		 * and wants to unselect it.  S/he does this by
X		 * clicking in the root window.
X		 */
X		 XSetSelectionOwner(dpy, XA_PRIMARY,
X				    RootWindow(dpy, DefaultScreen(dpy)),
X			            pEvent->xbutton.time);
X		 SelectionTime = pEvent->xbutton.time;
X	}
X}
X		
X/* 
X * eventButtonPress - record a button press
X */
static int
eventButtonPress(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X	buttonPressEvent = *pEvent;
X
X	/* set lastButton */
X	if ((lastButton = MouseButton(dpy, pEvent)) == MB_MENU)
X	{
X		/* bring up menu for root */
X		MenuShow(dpy, winInfo, RootMenu, pEvent);
X	}
X}
X
X/* 
X * eventSelectionNotify - someone else has asked for the selection value
X */
static int
eventSelectionNotify(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X	/* We get this event from the owner of the selection
X	 * if we had made a XConvertSelection call.  At the
X	 * moment we never make a XConvertSelction call
X	 * so we don't have to worry about a SelectionNotify
X	 * event.  An XCovertSelection call is used to get
X	 * the current selection.
X	 */
X}
X
X/* 
X * eventSelectionRequest - someone else has asked for the selection value
X */
static int
eventSelectionRequest(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X		SelectionResponse((XSelectionRequestEvent *)pEvent);
X}
X
X/* 
X * eventSelectionClear - someone else has asked to be the selection owner
X */
static int
eventSelectionClear(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X	/*
X	 * Someone else has asked to be the selection owner.
X	 * Clear our list of selected windows.
X	 */
X	ClearSelections(dpy);
X}
X
X/* 
X * eventKeyPressRelease - a keystroke has happened in the root window
X */
static int
eventKeyPressRelease(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X   rootKeystroke( dpy, pEvent );
X}
X
X/* 
X * eventPropertyNotify - a root property has changed
X */
static int
eventPropertyNotify(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X    rootProperty( dpy, pEvent );
X}
X
X/* 
X * eventUnmapNotify - an unreparented pane is going away
X */
static int
eventUnmapNotify(dpy, pEvent, winInfo)
Display	*dpy;
XXEvent	*pEvent;
WinRoot	*winInfo;
X{
X    WinGeneric *wg;
X
X    wg = WIGetInfo(pEvent->xunmap.window);
X    if (wg != NULL)
X    {
X	StateWithdrawn(wg->core.client);
X    }
X}
X
X#ifdef NOTDEF
X/*
X * drawRoot -- draw the root window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawRoot(dpy, winInfo)
Display	*dpy;
WinGeneric *winInfo;
X{
X}
X
X/*
X * DestroyRoot -- destroy the root window resources and free any allocated
X *	data.
X */
static int
destroyRoot(dpy, winInfo)
Display	*dpy;
WinGeneric *winInfo;
X{
X	/* free our data and throw away window */
X	WIUninstallInfo(winInfo->core.self);
X	MemFree(winInfo);
X}
X#endif
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeRoot  -- create the root window. Return a WinGeneric structure.
X */
WinGeneric *
MakeRoot(dpy, par)
Display	*dpy;
WinGeneric *par;	/* ignored */
X{
X	XWindowAttributes attr;
X	WinRoot *w;
X	Window win;
X
X	win = RootWindow(dpy, DefaultScreen(dpy));
X
X	if (XGetWindowAttributes(dpy, win, &attr) == 0) {
X	    ErrorGeneral("could not get attributes of root window");
X	    /*NOTREACHED*/
X	}
X
X	/* create the associated structure */
X	w = MemNew(WinRoot);
X	w->core.self = win;
X	w->class = &classRoot;
X	w->core.kind = WIN_ROOT;
X	w->core.parent = NULL;
X	w->core.children = NULL;
X	w->core.client = NULL;
X	w->core.x = 0;
X	w->core.y = 0;
X	w->core.width = attr.width;
X	w->core.height = attr.height;
X	w->core.dirtyconfig = False;
X	w->core.colormap = attr.colormap;
X	w->core.exposures = NULL;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	return w;
X}
X
void
RootInit(dpy)
Display *dpy;
X{
X	classRoot.core.kind = WIN_ROOT;
X	classRoot.core.xevents[ConfigureRequest] = eventConfigureRequest;
X	classRoot.core.xevents[EnterNotify] = eventEnterNotify;
X	classRoot.core.xevents[MapRequest] = eventMapRequest;
X	classRoot.core.xevents[MotionNotify] = eventMotionNotify;
X	classRoot.core.xevents[ButtonRelease] = eventButtonRelease;
X	classRoot.core.xevents[ButtonPress] = eventButtonPress;
X	classRoot.core.xevents[SelectionNotify] = eventSelectionNotify;
X	classRoot.core.xevents[SelectionRequest] = eventSelectionRequest;
X	classRoot.core.xevents[SelectionClear] = eventSelectionClear;
X	classRoot.core.xevents[KeyPress] = eventKeyPressRelease;
X	classRoot.core.xevents[KeyRelease] = eventKeyPressRelease;
X	classRoot.core.xevents[PropertyNotify] = eventPropertyNotify;
X	classRoot.core.xevents[UnmapNotify] = eventUnmapNotify;
X	classRoot.core.focusfunc = NULL;
X	classRoot.core.drawfunc = NULL;
X	classRoot.core.destroyfunc = NULL;
X	classRoot.core.selectfunc = NULL;
X	classRoot.core.newconfigfunc = NULL;
X	classRoot.core.newposfunc = NULL;
X	classRoot.core.setconfigfunc = NULL;
X	classRoot.core.createcallback = NULL;
X	classRoot.core.heightfunc = NULL;
X	classRoot.core.widthfunc = NULL;
X}
END_OF_FILE
if test 14250 -ne `wc -c <'winroot.c'`; then
    echo shar: \"'winroot.c'\" unpacked with wrong size!
fi
# end of 'winroot.c'
fi
echo shar: End of archive 5 \(of 16\).
cp /dev/null ark5isdone
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