v12i060: olvwm - Open Look Virtual Window Manager, Part04/16

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


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

#! /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 4 (of 16)."
# Contents:  events.c wingframe.c winipane.c winpane.c
# Wrapped by sdo at piccolo on Fri Apr 26 17:31:04 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'events.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'events.c'\"
else
echo shar: Extracting \"'events.c'\" \(12105 characters\)
sed "s/^X//" >'events.c' <<'END_OF_FILE'
X/*
X *      (c) Copyright 1989 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[] = "@(#)events.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#)events.c 25.9 90/05/23 Crucible";
X *
X */
X
X#include <stdio.h>
X
X#include <sys/types.h>
X#include <sys/time.h>
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
X#include "olwm.h"
X#include "win.h"
X#include "globals.h"
X#include "events.h"
X#include "list.h"
X#include "mem.h"
X
X/* ===== externs ========================================================== */
X
extern int	DeadChildren;
extern void	ReapChildren();
X
X/* ===== globals ========================================================== */
X
XXModifierKeymap *ModMap = NULL;
Time LastEventTime = (Time) 0;
X
X/* ===== private data ===================================================== */
X
static int (*interposer)() = NULL;
static void *closure;
static List *deferredEventListHead = NULL_LIST;
static List *deferredEventListTail = NULL_LIST;
X
static struct timeval timeoutNext = 0;
static TimeoutFunc timeoutFunc = NULL;
static void *timeoutClosure = NULL;
X
X/* ===== private functions ================================================ */
X
X/*
X * lookupWindow
X * 
X * Given an event, look up the WinInfo corresponding to the window field of 
X * the event.  For events that have no window field, return NULL.
X */
WinGeneric *
lookupWindow( event )
X    XEvent *event;
X{
X    switch ( event->xany.type ) {
X    case KeymapNotify:
X    case MappingNotify:
X	/* these events have no window field */
X	return NULL;
X    default:
X	return WIGetInfo( event->xany.window );
X    }
X}
X
X
X/*
X * saveTimestamp
X *
X * Given an event, update LastEventTime with its timestamp.  For events that 
X * have no timestamp, do nothing.
X */
void
saveTimestamp( event )
X    XEvent *event;
X{
X    switch ( event->xany.type ) {
X    case KeyPress:
X    case KeyRelease:
X	LastEventTime = event->xkey.time;
X	break;
X    case ButtonPress:
X    case ButtonRelease:
X	LastEventTime = event->xbutton.time;
X	break;
X    case MotionNotify:
X	LastEventTime = event->xmotion.time;
X	break;
X    case EnterNotify:
X    case LeaveNotify:
X	LastEventTime = event->xcrossing.time;
X	break;
X    case PropertyNotify:
X	LastEventTime = event->xproperty.time;
X	break;
X    case SelectionClear:
X	LastEventTime = event->xselectionclear.time;
X	break;
X    case SelectionRequest:
X	/*
X	 * The timestamp in SelectionRequest events comes from other clients; 
X	 * it's not generated by the server.  It's thus not clear whether we 
X	 * should believe any timestamp in one of these events.
X	 */
X	/* LastEventTime = event->xselectionrequest.time; */
X	break;
X    case SelectionNotify:
X	/*
X	 * Ignore SelectionNotify events generated by other clients.
X	 * Save only the timestamps from server-generated events.
X	 */
X	if (!event->xany.send_event)
X	    LastEventTime = event->xselection.time;
X	break;
X    default:
X	break;
X    }
X}
X
static void
dispatchEvent(dpy, event, winInfo)
Display *dpy;
XXEvent *event;
WinGeneric *winInfo;
X{
X	EvFunc evFunc;
X
X	if (GRV.PrintAll)
X	    DebugEvent(event, "Dispatch - debug");
X
X	saveTimestamp( event );
X
X	if (winInfo == NULL)
X	{
X	    if (IsVirtual(event->xany.window))
X	        VirtualEvents(dpy, event);
X		/* REMIND should we do anything with these events? */
X	    else if (GRV.PrintOrphans)
X	    	    DebugEvent(event, "Orphaned (null window)");
X		return;
X	}
X
X	if (GRV.PrintAll)
X	    DebugWindow(winInfo);
X
X#ifdef DEBUG
X        if (winInfo->class == NULL)
X	{
X	    ErrorGeneral("Window instance with NULL class pointer");
X	}
X
X	if (winInfo->core.kind != winInfo->class->core.kind)
X	    ErrorWarning("Warning:  window with kind different than class kind");
X#endif 
X
X	evFunc = WinClass(winInfo)->core.xevents[event->xany.type];
X	if (evFunc != NULL)
X	{
X	    (*evFunc)(dpy, event, winInfo);
X	}
X	else if (IsVirtual(event->xany.window))
X	    VirtualEvents(dpy, event);
X	else
X	    if (GRV.PrintOrphans)
X		DebugEvent(event, "Orphaned");
X}
X
static int
dispatchInterposer(dpy, event)
Display *dpy;
XXEvent *event;
X{
X	int disposition;
X	WinGeneric *winInfo;
X	XEvent *temp;
X
X	if (GRV.PrintAll)
X	    DebugEvent(event, "Dispatch - interposer");
X
X	saveTimestamp( event );
X	winInfo = lookupWindow(event);
X	disposition = (*interposer)(dpy, event, winInfo, closure);
X
X	switch (disposition) {
X	case DISPOSE_DISPATCH:
X	    dispatchEvent(dpy, event, winInfo);
X	    break;
X	case DISPOSE_DEFER:
X	    temp = MemNew(XEvent);
X	    *temp = *event;
X	    if (deferredEventListHead == NULL_LIST) {
X		deferredEventListHead = ListCons(temp, NULL_LIST);
X		deferredEventListTail = deferredEventListHead;
X	    } else {
X		deferredEventListTail->next = ListCons(temp, NULL_LIST);
X		deferredEventListTail = deferredEventListTail->next;
X	    }
X	    break;
X	case DISPOSE_USED:
X	    /* do nothing */
X	    break;
X	}
X}
X
static void
doTimeout()
X{
X	TimeoutFunc f;
X	void *closure;
X
X	f = timeoutFunc;
X	closure = timeoutClosure;
X	TimeoutCancel();
X	(*f)(closure);
X}
X
static void
nextEventOrTimeout(dpy, event)
Display *dpy;
XXEvent *event;
X{
X	int fd = ConnectionNumber(dpy);
X	struct timeval polltime;
X	fd_set rdset, wrset, xset;
X	int ready = -1;
X
X	while (XPending(dpy) == 0 && ready <= 0 && timeoutFunc != NULL) {
X	    gettimeofday(&polltime,NULL);
X	    if ((timeoutFunc != NULL) &&
X		((polltime.tv_sec > timeoutNext.tv_sec) ||
X		 ((polltime.tv_sec == timeoutNext.tv_sec) && 
X		  (polltime.tv_usec >= timeoutNext.tv_usec))))
X	    {
X		doTimeout();
X		continue;
X	    }
X
X	    polltime.tv_sec = timeoutNext.tv_sec - polltime.tv_sec;
X	    polltime.tv_usec = 0;
X
X	    FD_ZERO(&rdset);
X	    FD_SET(fd,&rdset);
X	    FD_ZERO(&wrset);
X	    FD_ZERO(&xset);
X	    FD_SET(fd,&xset);
X
X	    ready = select(fd+1,&rdset,&wrset,&xset,&polltime);
X
X	    gettimeofday(&polltime,NULL);
X	    if ((timeoutFunc != NULL) &&
X		((polltime.tv_sec > timeoutNext.tv_sec) ||
X		 ((polltime.tv_sec == timeoutNext.tv_sec) && 
X		  (polltime.tv_usec >= timeoutNext.tv_usec))))
X	    {
X		doTimeout();
X	    }
X	}
X
X	XNextEvent(dpy, event);
X}
X
X
void
handleMappingNotify(dpy, e)
X    Display *dpy;
X    XEvent *e;
X{
X    void UpdateModifierMap();
X
X    switch (e->xmapping.request) {
X    case MappingModifier:
X	UpdateModifierMap(dpy);
X	break;
X    case MappingKeyboard:
X	XRefreshKeyboardMapping(e);
X	break;
X    case MappingPointer:
X	/* REMIND - handle mouse button changes */
X	break;
X    }
X}
X
X
X/* ===== public functions ================================================= */
X
X
X/*
X * EventLoop
X * 
X * The main event loop.  Reads events from the wire and dispatches them.
X */
void
XEventLoop( dpy )
X    Display *dpy;
X{
X	XEvent		event;
X
X	for (;;) {
X		if (timeoutFunc == NULL)
X		{
X		    XNextEvent( dpy, &event );
X		} 
X		else
X		{
X		    nextEventOrTimeout(dpy, &event);
X		}
X
X		if (DeadChildren > 0)
X			ReapChildren();
X
X		/*
X		 * Discard user events that have the Synthetic bit set.
X		 *
X		 * All device events (mouse and keyboard events) have types
X		 * that fall in between KeyPress and MotionNotify.
X		 */
X		if (event.xany.send_event
X			&& event.type <= MotionNotify
X			&& event.type >= KeyPress)
X		    continue;
X
X
X		/*
X		 * Handle MappingNotify events.  These events don't have 
X		 * window field, so they can't be dispatched normally.
X		 */
X		if (event.xany.type == MappingNotify) {
X		    handleMappingNotify(dpy, &event);
X		    continue;
X		}
X
X		/*
X		 * If there is an event interposer, and it returns True, that 
X		 * means it has successfully processed the event.  We continue 
X		 * around the loop instead of processing the event normally.
X		 */
X		if ( interposer != NULL)
X		    dispatchInterposer(dpy, &event);
X		else
X		    dispatchEvent(dpy, &event, lookupWindow(&event));
X	}
X
X	/*NOTREACHED*/
X}
X
int
PropagateEventToParent(dpy,event,win)
Display *dpy;
XXEvent *event;
WinGeneric *win;
X{
X	dispatchEvent(dpy,event,win->core.parent);
X}
X
X
void
UpdateModifierMap(dpy)
X    Display *dpy;
X{
X    if (ModMap != NULL)
X	XFreeModifiermap(ModMap);
X    ModMap = XGetModifierMapping(dpy);
X}
X
X
X/*
X * FindModifierMask
X *
X * Given a keycode, look in the modifier mapping table to see if this keycode 
X * is a modifier.  If it is, return the modifier mask bit for this key; 
X * otherwise, return zero.
X */
unsigned int
XFindModifierMask(kc)
X{
X    int i, j;
X    KeyCode *mapentry;
X
X    if (ModMap == NULL)
X	return 0;
X
X    mapentry = ModMap->modifiermap;
X    for (i=0; i<8; ++i) {
X	for (j=0; j<(ModMap->max_keypermod); ++j) {
X	    if (kc == *mapentry)
X		return 1 <<
X		    ( (mapentry - ModMap->modifiermap) / 
X		      ModMap->max_keypermod );
X	    ++mapentry;
X	}
X    }
X    return 0;
X}
X
X
static void *
redispatchEvent(e)
X    XEvent *e;
X{
X    dispatchEvent(e->xany.display, e, lookupWindow(e));
X    MemFree(e);
X}
X
X
X/***************************************************************************
X* Interposer functions
X***************************************************************************/
X
X/*
X * InstallInterposer
X *
X * Install an event interposition function.  Nested interposition is illegal.
X */
void
InstallInterposer( func, cl )
X    Bool (*func)();
X    void *cl;
X{
X    if ( interposer != NULL ) {
X	fputs( "olvwm: warning, nested event interposer!\n", stderr );
X#ifdef DEBUG
X	abort();
X#endif /* DEBUG */
X    }
X    interposer = func;
X    closure = cl;
X}
X
X/*
X * UninstallInterposer
X *
X * Uninstall an event interposition function.
X */
void
UninstallInterposer()
X{
X    if ( interposer == NULL ) {
X#ifdef DEBUG
X	fputs( "olvwm: warning, no interposer to uninstall.\n", stderr );
X#endif /* DEBUG */
X    }
X    interposer = (int (*)()) NULL;
X
X    if (deferredEventListHead != NULL) {
X	ListApply(deferredEventListHead, redispatchEvent, 0);
X	ListDestroy(deferredEventListHead);
X	deferredEventListHead = deferredEventListTail = NULL_LIST;
X    }
X}
X
X/***************************************************************************
X* Timeout functions
X***************************************************************************/
X
X/* TimeoutRequest(t,f,c) -- request that a timeout be generated t seconds
X *	in the future; when the timeout occurs, the function f is called
X *	with the closure c.
X */
void
TimeoutRequest(t,f,c)
int t;
TimeoutFunc f;
void *c;
X{
X#ifdef DEBUG
X	if (timeoutFunc != NULL)
X	{
X	    ErrorWarning("Timeout being set while another timeout current");
X	}
X#endif
X
X	gettimeofday(&timeoutNext,NULL);
X	timeoutNext.tv_sec += t;
X	timeoutFunc = f;
X	timeoutClosure = c;
X}
X
X/* TimeoutCancel() -- cancel an outstanding timeout.
X */
void 
TimeoutCancel()
X{
X	timeoutNext.tv_sec = 0;
X	timeoutNext.tv_usec = 0;
X	timeoutFunc = NULL;
X	timeoutClosure = NULL;
X}
X
X/***************************************************************************
X* Mouse button interpretation
X***************************************************************************/
X
X/* the default button mapping */
int     ButtonMap[] = {
X                -1,             /* Button Zero */
X                MB_SELECT,      /* Button1 */
X                MB_ADJUST,      /* Button2 */
X                MB_MENU,        /* Button3 */
X                -1,             /* Button4 */
X                -1,             /* Button5 */
X                };
X
X
X/* MouseButton  -- convert a button press to a logical button
X */
X/*ARGSUSED*/    /* dpy arg will be used when multiple Displays supported */
MouseButton(dpy, event)
Display *dpy;
XXEvent  *event;
X{
X        return ButtonMap[event->xbutton.button];
X}
X
X/* GetSelectButtonMapping -- return the current MB_SELECT button
X *
X *      Currently unused.
X */
X/*ARGSUSED*/    /* dpy arg will be used when multiple Displays supported */
GetSelectButtonMapping(dpy)
Display *dpy;
X{
X        int             i;
X        static int      button = -1;
X        static int      found = False;
X
X        if (!found)
X        {
X                for (i=Button1; i<Button5; i++)
X                        if (ButtonMap[i] == MB_SELECT)
X                                button = i;
X
X                /* if the user has not specified a Select button,
X                 * then use Button1 as a backup.
X                 */
X                if (button == -1)
X                        button = Button1;
X        }
X
X        return button;
X}
X
END_OF_FILE
if test 12105 -ne `wc -c <'events.c'`; then
    echo shar: \"'events.c'\" unpacked with wrong size!
fi
# end of 'events.c'
fi
if test -f 'wingframe.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'wingframe.c'\"
else
echo shar: Extracting \"'wingframe.c'\" \(12981 characters\)
sed "s/^X//" >'wingframe.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
X/*
X * wingframe.c -- generic frame window routines
X */
X
static char     sccsid[] = "@(#)wingframe.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) wingframe.c 1.8 90/05/23  Crucible";
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <string.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 Graphics_info	*olgx_gisnormal;
extern Atom		AtomOlwmAutoRaise;
extern Bool		FocusIndeterminate;
X
extern int VirtualDesktopX, VirtualDesktopY;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* We sometimes get MotionNotify events when the button
X * is not pressed (even though we set Button1MotionMask).
X * Is this a bug in the X11R3 server?  To handle this
X * we need to record Button1 having been pressed.
X * When the MB_SELECT button, (Button1), has been pressed
X * hadSelect is set to true.
X * REMIND globalise this!
X */
static  Bool            hadSelect = False;
static  Time            timeOfLastButPress = 0;
static  int             buttonPressX;
static  int             buttonPressY;
static  XButtonEvent    lastSelectRelease;
static  XButtonEvent    lastSelectPress;
static  Time            lastDoubleClickTime;
X
X/***************************************************************************
X* forward-declared functions
X***************************************************************************/
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * GFrameSelect -- handle selection state change
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
int
GFrameSelect(dpy, winInfo, selected)
Display	*dpy;
WinGeneric *winInfo;
Bool selected;
X{
X	(WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * GFrameFocus -- handle focus changes
X *
X * If we're in auto-raise mode, raise the window.  But if we're in focus-
X * follows-mouse, we query the pointer to make sure we're still in the same 
X * window before we do this raise.  This is to avoid restacking loops.
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
int
GFrameFocus(dpy, winInfo, focus)
Display	*dpy;
WinGeneric *winInfo;
X{
X	Bool samescreen;
X	Window root, child;
X	int rootx, rooty, winx, winy, state;
X	Client	*cli = winInfo->core.client;
X
X	if (focus)
X	    FocusIndeterminate = False;
X
X	if (focus && GRV.AutoRaise) {
X	    if (GRV.FocusFollowsMouse) {
X		samescreen = XQueryPointer(dpy, DefaultRootWindow(dpy), &root,
X		    &child, &rootx, &rooty, &winx, &winy, &state);
X		if (samescreen && child == winInfo->core.self)
X		    RaiseWindow(winInfo->core.self, cli->virtualWindow, 
X						    cli->sticky, dpy); 
X	    } else {
X		RaiseWindow(winInfo->core.self, cli->virtualWindow, 
X						cli->sticky, dpy); 
X	    }
X	}
X
X	(WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
X}
X
X/*
X * GFrameSetConfigFunc -- change configuration of frame window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
int
GFrameSetConfigFunc(dpy, win)
Display	*dpy;
WinGenericFrame *win;
X{
X        XWindowChanges xwc;
X	Client	*cli = win->core.client;
X	Window	vframe;
X
X        if (win->core.dirtyconfig)
X        {
X                xwc.x = win->core.x;
X                xwc.y = win->core.y;
X                xwc.width = win->core.width;
X                xwc.height = win->core.height;
X		xwc.sibling = win->core.stack_sib;
X		xwc.stack_mode = win->core.stack_mode;
X		if ((win->core.dirtyconfig & CWSibling) && 
X		    !(win->core.dirtyconfig &CWStackMode))
X			win->core.dirtyconfig &= ~CWSibling;
X                XConfigureWindow(dpy,win->core.self,win->core.dirtyconfig,&xwc);
X		if (cli->virtualWindow && cli->wmState != WithdrawnState) {
X		    if (cli->wmState == NormalState &&
X					win->core.kind == WIN_FRAME)
X		        vframe = cli->virtualWindow;
X		    else if (cli->wmState == IconicState &&
X					win->core.kind == WIN_ICON)
X			vframe = cli->virtualWindow;
X		    else vframe = cli->virtualInactive;
X		    xwc.x = (win->core.x - VirtualDesktopX) / GRV.VDMScale;
X		    xwc.y = (win->core.y - VirtualDesktopY) / GRV.VDMScale;
X		    xwc.width = win->core.width / GRV.VDMScale;
X		    xwc.height = win->core.height / GRV.VDMScale;
X		    XConfigureWindow(dpy, vframe, win->core.dirtyconfig, &xwc);
X		}
X		win->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode);
X        }
X}
X
X/* GFrameSetStack -- set the frame's stacking position.   Does not initiate
X *	a configuration change.
X */
void
GFrameSetStack(win, mask, mode, sib)
WinGenericFrame *win;
int mask;
int mode;
Window sib;
X{
X	WinGeneric *wsib;
X
X	if ((mask & CWSibling) && (mask & CWStackMode))
X	{
X		wsib = WIGetInfo(sib);
X		if (wsib != NULL)
X		{
X			win->core.stack_sib = wsib->core.client->framewin->core.self;
X			win->core.dirtyconfig |= CWSibling;
X		}
X	}
X	if (mask & CWStackMode)
X	{
X		win->core.stack_mode = mode;
X		win->core.dirtyconfig |= CWStackMode;
X	}
X}
X
X/* GFrameSetConfig - set the frame's size and position -- generally used in
X * resizing or moving the window.  We position the frame and resize the pane.
X * If the pane has refused resizing we skip that part.
X */
void
GFrameSetConfig(win,x,y,w,h)
WinGenericFrame *win;
int x,y,w,h;
X{
X        WinPane *pane = (WinPane *)win->fcore.panewin;
X
X        (WinFunc(win,core.newposfunc))(win,x,y);
X	if (pane != NULL)
X	{
X            if (WinFunc(pane,pcore.setsizefunc) != NULL)
X                (WinFunc(pane,pcore.setsizefunc))(pane,
X                    w-(WinFunc(win,fcore.widthleft))(win)-(WinFunc(win,fcore.widthright))(win),
X                    h-(WinFunc(win,fcore.heighttop))(win)-(WinFunc(win,fcore.heightbottom))(win));
X            WinCallConfig(win->core.client->dpy, pane, NULL);
X	}
X	else
X	{
X            WinCallConfig(win->core.client->dpy, win, NULL);
X	}
X}
X
X
X/***************************************************************************
X* global event functions
X***************************************************************************/
X
X/*
X * GFrameEventButtonRelease -- a button has been released
X *
X */
int
GFrameEventButtonRelease(dpy, event, frameInfo)
Display *dpy;
XXEvent  *event;
WinGenericFrame *frameInfo;
X{
X        WinGenericPane	*winPane = (WinGenericPane*)frameInfo->fcore.panewin;
X        Client *cli = frameInfo->core.client;
X
X#define bevent  (event->xbutton)
X        switch (MouseButton(dpy, event))
X        {
X	case MB_ADJUST:
X                if (WinFunc(frameInfo,fcore.adjustClick) != NULL)
X                {
X		    (WinFunc(frameInfo,fcore.adjustClick))(dpy,event,frameInfo);
X                }
X		break;
X
X        case MB_SELECT:
X                ClearSelections(dpy);
X                AddSelection(cli, event->xbutton.time);
X		RaiseWindow(frameInfo->core.self, cli->virtualWindow, 
X						cli->sticky, dpy); 
X                hadSelect = False;
X
X                if (WinFunc(frameInfo,fcore.selectClick) != NULL)
X                {
X		    (WinFunc(frameInfo,fcore.selectClick))(dpy,event,frameInfo);
X                }
X
X                /* If the click happened in the decoration windows,
X                 * (i.e. not in the pane), check for a double click.
X                 * Check last click time to see if we are in double
X                 * click land.  Also check that the user hasn't just
X                 * hit the button 3 times very rapidly.  This would
X                 * cause a cycle of the window changing size.
X		 * REMIND this is more nasty than it should be because
X		 * not all frames are yet required to have panes.
X		 * Once all panes have frames the subwindow test gets
X		 * easier.
X                 */
X                if ((WinFunc(frameInfo,fcore.selectDoubleClick) != NULL) &&
X		    ((winPane == NULL) || (bevent.subwindow != winPane->core.self)) &&
X                   ((bevent.time-lastSelectRelease.time) <= GRV.DoubleClickTime) &&
X                   ((bevent.time-lastDoubleClickTime) > GRV.DoubleClickTime))
X                {
X                    /* we have a double click */
X		    if (WinFunc(frameInfo,fcore.selectDoubleClick) != NULL)
X		    {
X			(WinFunc(frameInfo,fcore.selectDoubleClick))(dpy,event,frameInfo);
X		    }
X
X                    lastDoubleClickTime = bevent.time;
X                 }
X                lastSelectRelease = event->xbutton;
X                break;  /* out of MB_SELECT case */
X        }
X}
X
X/*
X * GFrameEventMotionNotify -- a button is down and the pointer is moving
X */
int
GFrameEventMotionNotify(dpy, event, frameInfo)
Display *dpy;
XXEvent  *event;
WinGenericFrame *frameInfo;
X{
X        /* We get this only after a Select press */
X        if (hadSelect == False) /* watch for erroneous motions */
X        {
X                return;
X        }
X
X	if (!event->xmotion.same_screen)
X		return;
X        /* See if we have moved more than the threshold amount. */
X        if ((ABS(event->xmotion.x - buttonPressX) < GRV.MoveThreshold) &&
X            (ABS(event->xmotion.y - buttonPressY) < GRV.MoveThreshold))
X                return;
X
X	(WinFunc(frameInfo,fcore.selectDrag))(dpy, event, frameInfo, &lastSelectPress);
X
X        /*
X         * UserMoveWindows() will grab the pointer and handle events
X         * using an interposer, so we can clear the hadSelect flag.
X         */
X        hadSelect = False;
X}
X
X/*
X * GFrameEventButtonPress -- a mouse button has gone down.
X */
X/* Really we should not be doing anything on the
X * ButtonPress event.  We should wait for the
X * ButtonRelease before deciding what to do.
X */
int
GFrameEventButtonPress(dpy, event, frameInfo)
Display *dpy;
XXEvent  *event;
WinGenericFrame *frameInfo;
X{
X        WinPane         *winPane = (WinPane*)frameInfo->fcore.panewin;
X        Window          panewindow = winPane->core.self;
X        Client *cli = frameInfo->core.client;
X
X        switch (MouseButton(dpy, event))
X        {
X        case MB_MENU:
X	    if (WinFunc(frameInfo,fcore.menuPress) != NULL)
X		(WinFunc(frameInfo,fcore.menuPress))(dpy, event, frameInfo);
X            break;
X
X        case MB_SELECT:
X                /* Save the location where the button went down so we
X                 * can see if the user moves the mouse more than
X                 * GRV.MoveThreshold, and wants to move the window.
X                 */
X                buttonPressX = event->xbutton.x;
X                buttonPressY = event->xbutton.y;
X
X                if (!GRV.FocusFollowsMouse && 
X		    (WinFunc(frameInfo,fcore.selectPress) != NULL))
X                {
X                /* It is possible for us to replay the event and
X                 * have the window, (decoration window, e.g. the
X                 * resize corner, the titlebar), in which the
X                 * button press happened to ignore it.
X                 * In this case we would get the event
X                 * again.  For example, the user could button press
X                 * in the title bar, (which doesn't select this event),
X                 * and have this EventFrame routine get the same event
X                 * twice.  So, we check that the time stamp of this
X                 * button press is different than the last.
X                 */
X                        if (event->xbutton.time == timeOfLastButPress)
X                                /* We already dealt with this event. */
X                                break;
X                        timeOfLastButPress = event->xbutton.time;
X                        if (event->xbutton.subwindow == panewindow)
X                        {
X			    (WinFunc(frameInfo,fcore.selectPress))(dpy,event,frameInfo);
X                        }
X
X                        /* Let the button press through
X                         * if we had grabbed it.
X                         */
X                        XAllowEvents(dpy, ReplayPointer, CurrentTime);
X                }  /* End if not GRV.FocusFollowsMouse */
X
X                lastSelectPress = event->xbutton;
X                hadSelect = True;
X                break;  /* Break case MB_SELECT */
X
X        case MB_ADJUST:
X	    if (!GRV.FocusFollowsMouse) {
X		if (event->xbutton.time == timeOfLastButPress)
X		    break;
X		timeOfLastButPress = event->xbutton.time;
X		if (event->xbutton.subwindow == panewindow
X		    && WinFunc(frameInfo,fcore.adjustPress) != NULL) {
X		    (WinFunc(frameInfo,fcore.adjustPress))
X			(dpy,event,frameInfo);
X		}
X		XAllowEvents(dpy, ReplayPointer, CurrentTime);
X		break;
X	    }
X        }  /*  End switch on button pressed */
X}
X
X
END_OF_FILE
if test 12981 -ne `wc -c <'wingframe.c'`; then
    echo shar: \"'wingframe.c'\" unpacked with wrong size!
fi
# end of 'wingframe.c'
fi
if test -f 'winipane.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winipane.c'\"
else
echo shar: Extracting \"'winipane.c'\" \(11706 characters\)
sed "s/^X//" >'winipane.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[] = "@(#)winipane.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winipane.c 1.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 <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 "events.h"
X
X#include "iconbitmap.h"
X
X/***************************************************************************
X* global data
X***************************************************************************/
X
extern Atom AtomChangeState;
extern Atom AtomColorMapWindows;
extern Atom AtomOlwmTimestamp;
extern Window NoFocusWin;
extern GC IconSelectedGC, IconNormalGC;
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* border width for reparented windows */
X#define NORMAL_BORDERWIDTH      0
X
X/* This event maks if for wm-created icon panes. */
X#define ICON_EVENT_MASK		(ButtonPressMask | ButtonReleaseMask | \
X				 Button1MotionMask | ExposureMask )
X
X/* This event mask is for clients who handle their own icons. */
X#define ICON_EVENT_MASK_2        (ButtonPressMask | ButtonReleaseMask | \
X				  Button1MotionMask)
X
static ClassPane classIconPane;
X
X/* default icon bitmap (single-plane pixmap) */
static Pixmap   pixIcon;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/*
X * drawIPane -- draw the pane window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawIPane(dpy, winInfo)
Display	*dpy;
WinIconPane *winInfo;
X{
X	Window		pane;
X	Client		*cli;
X	extern GC	IconSelectedGC, IconNormalGC, IconUnselectedGC;
X
X	cli = winInfo->core.client;
X	pane = winInfo->core.self;
X
X	if (!winInfo->iconClientWindow) {
X	    XFillRectangle(dpy, pane, IconUnselectedGC, 0, 0,
X			   winInfo->core.width, winInfo->core.height);
X	    XCopyPlane(dpy, winInfo->iconPixmap, pane, IconNormalGC,
X		       0, 0, winInfo->core.width, winInfo->core.height,
X		       0, 0, (unsigned long)1L);
X	}
X}
X
X
X/*
X * focusIPane -- handle focus change
X */
static int
focusIPane(dpy, winInfo, focus)
Display	*dpy;
WinGeneric *winInfo;
Bool focus;
X{
X	/* REMIND: change background pixel of pane window */
X}
X
X/*
X * destroyIPane -- destroy the pane window resources and free any allocated
X *	data.
X */
static int
destroyIPane(dpy, winInfo)
Display	*dpy;
WinIconPane *winInfo;
X{
X	/* free our data and throw away window */
X	WIUninstallInfo(winInfo->core.self);
X        if (!winInfo->iconClientWindow)
X	{
X	      /* REMIND there may be other resources to be freed */
X              XDestroyWindow(dpy,winInfo->core.self);
X	}
X	MemFree(winInfo);
X}
X
X/*
X * setconfigIPane -- change configuration of pane window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
setconfigIPane(dpy, winInfo)
Display	*dpy;
WinIconPane *winInfo;
X{
X        XWindowChanges xwc;
X
X        if (winInfo->core.dirtyconfig)
X        {
X                xwc.x = winInfo->core.x;
X                xwc.y = winInfo->core.y;
X                xwc.width = winInfo->core.width;
X                xwc.height = winInfo->core.height;
X                XConfigureWindow(dpy, winInfo->core.self,
X                        winInfo->core.dirtyconfig&(CWX|CWY|CWWidth|CWHeight), &xwc);
X                winInfo->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight);
X        }
X}
X
X
X/* 
X * newconfigIPane - compute a new configuration given an event
X * Note:  this function must *always* be called with a configure request
X * event.
X */
static int
newconfigIPane(win, pxcre)
WinIconPane *win;
XXConfigureRequestEvent *pxcre;
X{
X    int oldWidth, oldHeight;
X    int oldX, oldY;
X    WinIconFrame *winFrame = (WinIconFrame *)(win->core.parent);
X
X    if (pxcre == NULL)
X	return win->core.dirtyconfig;
X
X    oldX = win->core.x;
X    oldY = win->core.y;
X    oldWidth = win->core.width;
X    oldHeight = win->core.height;
X
X    if ((pxcre->value_mask & CWHeight) && (pxcre->height != oldHeight))
X    {
X	win->core.height = pxcre->height;
X	win->core.dirtyconfig |= CWHeight;
X    }
X
X    if ((pxcre->value_mask & CWWidth) && (pxcre->width != oldWidth))
X    {
X	win->core.width = pxcre->width;
X	win->core.dirtyconfig |= CWWidth;
X    }
X
X    if (pxcre->value_mask & CWBorderWidth)
X    {
X	win->pcore.oldBorderWidth = pxcre->border_width;
X    }
X
X    if (pxcre->value_mask & (CWX | CWY)) 
X    {
X	FrameSetPosFromPane(winFrame, (pxcre->value_mask & CWX)?(pxcre->x):oldX,
X		(pxcre->value_mask & CWY)?(pxcre->y):oldY);
X    }
X
X    if (pxcre->value_mask & (CWStackMode | CWSibling))
X    {
X	GFrameSetStack(winFrame, pxcre->value_mask, pxcre->detail, pxcre->above);
X    }
X
X    return win->core.dirtyconfig;
X}
X
X/* 
X * newposIPane - move to a given position (relative to parent)
X */
static int
newposIPane(win,x,y)
WinIconPane *win;
int x, y;
X{
X	if (win->core.x != x)
X	{
X		win->core.x = x;
X		win->core.dirtyconfig |= CWX;
X	}
X
X	if (win->core.y != y)
X	{
X		win->core.y = y;
X		win->core.dirtyconfig |= CWY;
X	}
X
X	return win->core.dirtyconfig;
X}
X
X/* 
X * setsizeIPane - set the pane to a particular size, and initiate a reconfigure
X */
static int
setsizeIPane(win,w,h)
WinIconPane *win;
int w, h;
X{
X	if (win->core.width != w)
X	{
X		win->core.width = w;
X		win->core.dirtyconfig |= CWWidth;
X	}
X
X	if (win->core.height != h)
X	{
X		win->core.height = h;
X		win->core.dirtyconfig |= CWHeight;
X	}
X}
X
static int
eventKeyPress(dpy, event, iconInfo)
X    Display     *dpy;
X    XEvent      *event;
X    WinIconPane        *iconInfo;
X
X{
extern Window   VDM;
X/*
X * Since the vdm is the only icon which we get this event for, we don't
X * have to check to see which it is . . .
X */
X
X   event->xany.window = VDM;
X   CheckVDMMove(dpy, event);
X}
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakeIconPane  -- create the pane window. Return a WinGeneric structure.
X */
WinIconPane *
MakeIconPane(cli,par,wmHints,fexisting)
Client *cli;
WinGeneric *par;
XXWMHints *wmHints;
Bool fexisting;
X{
X	WinIconPane *w;
X	WinIconFrame	*frame = (WinIconFrame *)par;
X	XSetWindowAttributes attributes;
X	long valuemask;
X	Window iconPane;
X	Window winRoot;
X	int borderWidth, depthReturn;
X	Display *dpy = cli->dpy;
X	int screen = cli->screen;
X	Status status;
X
X	/* create the associated structure */
X	w = MemNew(WinIconPane);
X	w->class = &classIconPane;
X	w->core.kind = WIN_ICONPANE;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = cli;
X	w->core.x = 0;
X	w->core.y = 0;
X	w->core.colormap = None;
X	w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
X	w->core.exposures = NULL;
X
X	/* install the pane structure.
X	 */
X	frame->fcore.panewin = (WinGenericPane *)w;
X
X	/* create the pane window and size it */
X	if (wmHints && (wmHints->flags & IconWindowHint))
X	{
X	    WinGeneric *wrongPane;
X
X            /* if we are reparenting existing windows, make sure that
X	     * we haven't already accidentally processed the icon window
X	     * as a pane.  If so, tear down the client created for that
X	     * "pane".
X	     */
X	    if (((wrongPane = WIGetInfo(wmHints->icon_window)) != NULL) && 
X		(wrongPane->core.kind != WIN_PANE))
X	    {
X		wmHints->flags &= ~IconWindowHint;
X		ErrorWarning("An existing window was named as an icon window.");
X	    }
X	    else
X	    {
X		if (wrongPane != NULL)
X		{
X		    StateWithdrawn(wrongPane->core.client);
X		}
X
X	        /* get the current width and height of the icon window */
X	        status = XGetGeometry(dpy, wmHints->icon_window, &winRoot,
X		    &(w->core.x), &(w->core.y),
X		    &(w->core.width), &(w->core.height),
X		    &borderWidth, &depthReturn);
X
X		if (status)
X		{
X	            w->iconPixmap = None;
X	            w->iconClientWindow = True;
X	            iconPane = wmHints->icon_window;
X	            XSelectInput(dpy, iconPane, ICON_EVENT_MASK_2);
X	            XSetWindowBorderWidth(dpy, iconPane, NORMAL_BORDERWIDTH);
X		}
X		else
X		{
X		    wmHints->flags &= ~IconWindowHint;
X		    ErrorWarning("An invalid window is was named as an icon window.");
X		}
X	    }
X	}
X	if (wmHints && !(wmHints->flags & IconWindowHint) &&
X	    (wmHints->flags & IconPixmapHint))
X	{
X	    w->iconClientWindow = False;
X	    w->iconPixmap = wmHints->icon_pixmap;
X
X	    /* get pixmap dimensions */
X	    status = XGetGeometry(dpy, w->iconPixmap, &winRoot,
X		&(w->core.x), &(w->core.y),
X		&(w->core.width), &(w->core.height),
X		&borderWidth, &depthReturn);
X
X	    if (status)
X	    {
X	         /* build icon pixmap window */
X	         valuemask = CWEventMask;
X	         attributes.event_mask = ICON_EVENT_MASK;
X		 if (cli->wmInstance &&
X				!strcmp(cli->wmInstance, "virtualDesktop"))
X		     attributes.event_mask |= (KeyPressMask | EnterWindowMask);
X
X	         iconPane = XCreateWindow(dpy, RootWindow(cli->dpy, cli->screen),
X		     0, 0, w->core.width, w->core.height,
X		     0, DefaultDepth(dpy, screen), InputOutput,
X		     DefaultVisual(dpy, screen), valuemask, &attributes);
X	    }
X	    else
X	    {
X		ErrorWarning("An invalid pixmap was named as an icon pixmap");
X		wmHints->flags &= ~IconPixmapHint;
X	    }
X	}
X	if (!wmHints || (wmHints && !(wmHints->flags & (IconPixmapHint|IconWindowHint))))
X	{
X	    w->iconClientWindow = False;
X	    w->iconPixmap = pixIcon;
X
X	    /* get pixmap dimensions */
X	    XGetGeometry(dpy, w->iconPixmap, &winRoot,
X		&(w->core.x), &(w->core.y),
X		&(w->core.width), &(w->core.height),
X		&borderWidth, &depthReturn);
X
X	    /* build icon pixmap window */
X	    valuemask = CWEventMask;
X	    attributes.event_mask = ICON_EVENT_MASK;
X
X	    iconPane = XCreateWindow(dpy, RootWindow(cli->dpy, cli->screen),
X		0, 0, w->core.width, w->core.height,
X		0, DefaultDepth(dpy, screen), InputOutput,
X		DefaultVisual(dpy, screen), valuemask, &attributes);
X	}
X	w->core.self = iconPane;
X
X	/* set up icon cursor */
X	XDefineCursor(dpy, w->core.self, GRV.IconPointer);
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	return w;
X}
X
X/*
X * IconPaneInit -- initialise the IconPane class function vector
X */
void
IconPaneInit(dpy)
Display *dpy;
X{
X        /* create default icon bitmap (single-plane pixmap) which has color
X         * applied to it when copied into icon window
X         */
X        pixIcon = XCreateBitmapFromData( dpy,
X                                         RootWindow(dpy, DefaultScreen(dpy)),
X                                         icon_bits, icon_width, icon_height );
X
X	classIconPane.core.kind = WIN_ICONPANE;
X	classIconPane.core.xevents[Expose] = WinEventExpose;
X	classIconPane.core.xevents[ButtonRelease] = PropagateEventToParent;
X	classIconPane.core.xevents[MotionNotify] = PropagateEventToParent;
X	classIconPane.core.xevents[ButtonPress] = PropagateEventToParent;
X	classIconPane.core.xevents[KeyPress] = eventKeyPress;
X	classIconPane.core.focusfunc = focusIPane;
X	classIconPane.core.drawfunc = drawIPane;	/* NULL */
X	classIconPane.core.destroyfunc = destroyIPane;
X	classIconPane.core.selectfunc = drawIPane;	/* NULL */
X	classIconPane.core.newconfigfunc = newconfigIPane;
X	classIconPane.core.newposfunc = newposIPane;
X	classIconPane.core.setconfigfunc = setconfigIPane;
X	classIconPane.core.createcallback = NULL;
X	classIconPane.core.heightfunc = NULL;
X	classIconPane.core.widthfunc = NULL;
X	classIconPane.pcore.setsizefunc = setsizeIPane;
X}
X
END_OF_FILE
if test 11706 -ne `wc -c <'winipane.c'`; then
    echo shar: \"'winipane.c'\" unpacked with wrong size!
fi
# end of 'winipane.c'
fi
if test -f 'winpane.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'winpane.c'\"
else
echo shar: Extracting \"'winpane.c'\" \(13021 characters\)
sed "s/^X//" >'winpane.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[] = "@(#)winpane.c	1.2 olvwm version 3/30/91";
X
X/*
X * Based on
static	char	sccsid[] = "@(#) winpane.c 25.8 90/05/23  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 AtomChangeState;
extern Atom AtomColorMapWindows;
extern Atom AtomOlwmTimestamp;
extern Window NoFocusWin;
extern void ColormapChange();
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/* border width for reparented windows */
X#define NORMAL_BORDERWIDTH      0
X
static ClassPane classPane;
X
X/***************************************************************************
X* private functions
X***************************************************************************/
X
X/* 
X * eventEnterLeaveNotify - The pointer has entered or left the window
X */
static int
eventEnterLeaveNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPane	*winInfo;
X{
X    if (event->xany.type == EnterNotify)
X        ColorWindowCrossing(dpy, event, winInfo);
X}
X
X/* 
X * eventColormapNotify
X *
X * Handle changes to this window's colormap attribute.
X */
static int
eventColormapNotify(dpy, event, winInfo)
X    Display	*dpy;
X    XEvent	*event;
X    WinPane	*winInfo;
X{
X    ColormapChange(dpy, event, (WinGeneric *)winInfo);
X}
X
X/* 
X * eventUnmapNotify - the client is transitioning to withrdrawn
X */
static int
eventUnmapNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPane	*winInfo;
X{
X        if (winInfo->pcore.pendingUnmaps > 0)
X        {
X            --winInfo->pcore.pendingUnmaps;
X        }
X	else
X	{
X            /* Mark current state */
X	    StateWithdrawn(winInfo->core.client);
X	}
X}
X
X
X/* 
X * eventDestroyNotify - the pane window has disappeared
X *	This function can get called either during new state processing,
X *	or while app is iconic
X */
static int
eventDestroyNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPane	*winInfo;
X{
X	StateWithdrawn(winInfo->core.client);
X}
X
X
X/* 
X * eventPropertyNotify - handle client messages, in particular iconic requests
X */
static int
eventPropertyNotify(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPane	*winInfo;
X{
X	ClientDistributeProperty(winInfo->core.client,event);
X}
X
X/* 
X * eventClientMessage - handle client messages, in particular iconic requests
X */
static int
eventClientMessage(dpy, event, winInfo)
Display	*dpy;
XXEvent	*event;
WinPane	*winInfo;
X{
X	Client		*cli = winInfo->core.client;
X
X        if (event->xclient.message_type == AtomChangeState)
X        {
X                if (event->xclient.data.l[0] == IconicState)
X                        StateNormIcon(cli);
X        }
X}
X
X
X#ifdef NOTDEF
X/*
X * drawPane -- draw the pane window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
drawPane(dpy, winInfo)
Display	*dpy;
WinGeneric *winInfo;
X{
X}
X#endif
X
X
X/*
X * focusPane -- handle focus change
X */
static int
focusPane(dpy, winInfo, focus)
Display	*dpy;
WinGeneric *winInfo;
Bool focus;
X{
X}
X
X/*
X * DestroyPane -- destroy the pane window resources and free any allocated
X *	data.
X */
static int
destroyPane(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
X/*
X * setconfigPane -- change configuration of pane window
X */
X/*ARGSUSED*/	/* dpy arg will be used when multiple Displays supported */
static int
setconfigPane(dpy, winInfo)
Display	*dpy;
WinPane *winInfo;
X{
X	XConfigureEvent ce;
X	XWindowChanges xwc;
X
X	if (winInfo->core.dirtyconfig)
X	{
X		xwc.x = winInfo->core.x;
X		xwc.y = winInfo->core.y;
X		xwc.width = winInfo->core.width;
X		xwc.height = winInfo->core.height;
X		XConfigureWindow(dpy, winInfo->core.self, 
X			winInfo->core.dirtyconfig, &xwc);
X		winInfo->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight);
X	}
X
X	/* send synthetic configure notify in root coordinates */
X	ce.type = ConfigureNotify;
X	ce.serial = 0L;
X	ce.event = winInfo->core.self;
X	ce.window = winInfo->core.self;
X	WinRootPos(winInfo,&ce.x,&ce.y);
X	ce.x -= winInfo->pcore.oldBorderWidth;
X	ce.y -= winInfo->pcore.oldBorderWidth;
X	ce.width = winInfo->core.width;
X	ce.height = winInfo->core.height;
X	ce.border_width = winInfo->pcore.oldBorderWidth;
X	ce.above = None;
X	ce.override_redirect = False;
X
X	XSendEvent(dpy, winInfo->core.self, False, StructureNotifyMask,&ce);
X}
X
X
X/* 
X * newconfigPane - compute a new configuration given an event
X * Note:  this function must *always* be called with a configure request
X * event.
X */
static int
newconfigPane(win, pxcre)
WinPane *win;
XXConfigureRequestEvent *pxcre;
X{
X    int oldWidth, oldHeight;
X    Client *cli = win->core.client;
X    int oldX, oldY;
X    WinPaneFrame *winFrame = cli->framewin;
X    void FrameMoveRelative();
X    int dwidth, dheight;
X
X    if (pxcre == NULL)
X	return win->core.dirtyconfig;
X
X    WinRootPos(win, &oldX, &oldY);
X    oldWidth = win->core.width;
X    oldHeight = win->core.height;
X
X    if ((pxcre->value_mask & CWHeight) && (pxcre->height != oldHeight))
X    {
X	win->core.height = pxcre->height;
X	win->core.dirtyconfig |= CWHeight;
X    }
X
X    if ((pxcre->value_mask & CWWidth) && (pxcre->width != oldWidth))
X    {
X	win->core.width = pxcre->width;
X	win->core.dirtyconfig |= CWWidth;
X    }
X
X    if (pxcre->value_mask & CWBorderWidth)
X    {
X	win->pcore.oldBorderWidth = pxcre->border_width;
X    }
X
X    if (pxcre->value_mask & (CWX | CWY)) 
X    {
X	FrameSetPosAbsolute(winFrame,
X			    (pxcre->value_mask & CWX)?(pxcre->x):oldX,
X			    (pxcre->value_mask & CWY)?(pxcre->y):oldY);
X    }
X    else 
X    {
X	dwidth = oldWidth - win->core.width;
X	dheight = oldHeight - win->core.height;
X	if ((dwidth != 0) || (dheight!=0))
X	{
X	    switch (cli->normHints->win_gravity)
X	    {
X		case NorthWestGravity:
X		    break;
X		case NorthGravity:
X		    FrameMoveRelative(winFrame,dwidth/2,0);
X		    break;
X		case NorthEastGravity:
X		    FrameMoveRelative(winFrame,dwidth,0);
X		    break;
X		case WestGravity:
X		    FrameMoveRelative(winFrame,0,dheight/2);
X		    break;
X		case CenterGravity:
X		    FrameMoveRelative(winFrame,dwidth/2,dheight/2);
X		    break;
X		case EastGravity:
X		    FrameMoveRelative(winFrame,dwidth,dheight/2);
X		    break;
X		case SouthWestGravity:
X		    FrameMoveRelative(winFrame,0,dheight);
X		    break;
X		case SouthGravity:
X		    FrameMoveRelative(winFrame,dwidth/2,dheight);
X		    break;
X		case SouthEastGravity:
X		    FrameMoveRelative(winFrame,dwidth,dheight);
X		    break;
X	    }
X	}
X    }
X
X
X    if (pxcre->value_mask & (CWStackMode | CWSibling))
X    {
X	GFrameSetStack(winFrame, pxcre->value_mask, pxcre->detail, pxcre->above);
X    }
X
X    return win->core.dirtyconfig;
X}
X
X/* 
X * newposPane - move to a given position (relative to parent)
X */
static int
newposPane(win,x,y)
WinPane *win;
int x, y;
X{
X	if (win->core.x != x)
X	{
X		win->core.x = x;
X		win->core.dirtyconfig |= CWX;
X	}
X
X	if (win->core.y != y)
X	{
X		win->core.y = y;
X		win->core.dirtyconfig |= CWY;
X	}
X
X	return win->core.dirtyconfig;
X}
X
X/* 
X * setsizePane - set the pane to a particular size, and initiate a reconfigure
X */
static int
setsizePane(win,w,h)
WinPane *win;
int w, h;
X{
X	if (win->core.width != w)
X	{
X		win->core.width = w;
X		win->core.dirtyconfig |= CWWidth;
X	}
X
X	if (win->core.height != h)
X	{
X		win->core.height = h;
X		win->core.dirtyconfig |= CWHeight;
X	}
X}
X
X/***************************************************************************
X* global functions
X***************************************************************************/
X
X/*
X * MakePane  -- create the pane window. Return a WinGeneric structure.
X */
WinPane *
MakePane(cli,par,win,paneattrs)
Client *cli;
WinGeneric *par;
Window win;
XXWindowAttributes *paneattrs;
X{
X	WinPane *w;
X	XSetWindowAttributes attributes;
X	long mask;
X	WinColormap *colorwin;
X
X	/* this window may already be mentioned as a colourmap window.
X	 * grab its colourmap window structure, and unhook it from the
X	 * event dispatching table so we can register a new structure
X	 * for the window.  We will call another function at the end
X	 * of pane processing to re-establish the relation between this
X	 * window and other structures in the system.
X	 */
X	colorwin = ColormapUnhook(win);
X
X	/* create the associated structure */
X	w = MemNew(WinPane);
X	w->core.self = win;
X	w->class = &classPane;
X	w->core.kind = WIN_PANE;
X	WinAddChild(par,w);
X	w->core.children = NULL;
X	w->core.client = cli;
X	w->core.x = 0; 		/* gets fixed up later */
X	w->core.y = 0;		/* gets fixed up later */
X	w->core.width = paneattrs->width;
X	w->core.height = paneattrs->height;
X	w->core.colormap = paneattrs->colormap;
X	w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
X	w->core.exposures = NULL;
X	w->pcore.oldBorderWidth = paneattrs->border_width;
X	w->pcore.oldSaveUnder = paneattrs->save_under;
X
X	cli->framewin->fcore.panewin = (WinGenericPane *)w;
X
X	/* register the window */
X	WIInstallInfo(w);
X
X	/* Put the window in the save set so it doesn't go away */
X	XChangeSaveSet(cli->dpy,win,SetModeInsert);
X
X        /*
X	 * on the pane we ask for:
X         * PropertyChangeMask -- for ICCCM functionality
X         * StructureNotifyMask -- to get the UnmapNotify event
X         * ColormapChangeMask -- to track colormaps accurately
X         * EnterWindowMask -- to install colormaps appropriately
X         */
X	if (!IsVirtual(win)) {
X	    mask = PropertyChangeMask | StructureNotifyMask |
X	        ColormapChangeMask | EnterWindowMask;
X            XSelectInput(cli->dpy, win, mask);
X	}
X
X        /*
X         * Since the pane is reparented, save-unders are not useful.
X         * In the code above the save-under attribute is propogated to
X         * the frame, so it is safe to remove it here.  
X         */
X        attributes.save_under = False;
X        XChangeWindowAttributes(cli->dpy,
X                                win,
X                                (unsigned long)CWSaveUnder,
X                                &attributes);
X
X        /* change the border width if necessary */
X        if (paneattrs->border_width != NORMAL_BORDERWIDTH)
X        {
X                XSetWindowBorderWidth(cli->dpy, win, NORMAL_BORDERWIDTH);
X        }
X
X        /*
X         * Focus Lenience.  Be lenient about enforcing the requirement that
X         * clients set the input hint in WM_HINTS before they can get keyboard
X         * input.  If this flag is set, and if someone has selected for
X         * keyboard input on this window (presumably this client), and if the
X         * focus mode is NoInput, then force it to be passive.  This way, if a
X         * client either fails to set the WM_HINTS.input field, or fails to
X         * write WM_HINTS at all, it can still get keyboard input.  
X	 * REMIND  This kind
X         * of flag should be implemented on a client-by-client basis, not on a
X         * global basis.
X         */
X        if (GRV.FocusLenience &&
X            (paneattrs->all_event_masks & (KeyPressMask|KeyReleaseMask)) &&
X            cli->focusMode == NoInput ) 
X	{
X            cli->focusMode = Passive;
X        }
X
X        /* Reparent the pane */
X        XReparentWindow(cli->dpy, win, par->core.self,
X	    w->core.x, w->core.y);
X
X	/* we may have saved colourmap manipulation information at 
X	 * the beginning.  Re-establish the connection between this window
X	 * and other structures based on the old structure.
X	 */
X	ColormapTransmogrify(colorwin, w);
X
X	/* keep track of any subwindows that need colormap installation */
X	TrackSubwindows(cli);
X
X
X	return w;
X}
X
X/*
X * PaneInit -- initialise the Pane class function vector
X */
void
PaneInit(dpy)
Display *dpy;
X{
X	classPane.core.kind = WIN_PANE;
X	classPane.core.xevents[EnterNotify] = eventEnterLeaveNotify;
X	classPane.core.xevents[LeaveNotify] = eventEnterLeaveNotify;
X	classPane.core.xevents[ColormapNotify] = eventColormapNotify;
X	classPane.core.xevents[UnmapNotify] = eventUnmapNotify;
X	classPane.core.xevents[DestroyNotify] = eventDestroyNotify;
X	classPane.core.xevents[PropertyNotify] = eventPropertyNotify;
X	classPane.core.xevents[ClientMessage] = eventClientMessage;
X	classPane.core.focusfunc = focusPane;
X	classPane.core.drawfunc = NULL;
X	classPane.core.destroyfunc = destroyPane;
X	classPane.core.selectfunc = NULL;
X	classPane.core.newconfigfunc = newconfigPane;
X	classPane.core.newposfunc = newposPane;
X	classPane.core.setconfigfunc = setconfigPane;
X	classPane.core.createcallback = NULL;
X	classPane.core.heightfunc = NULL;
X	classPane.core.widthfunc = NULL;
X	classPane.pcore.setsizefunc = setsizePane;
X}
END_OF_FILE
if test 13021 -ne `wc -c <'winpane.c'`; then
    echo shar: \"'winpane.c'\" unpacked with wrong size!
fi
# end of 'winpane.c'
fi
echo shar: End of archive 4 \(of 16\).
cp /dev/null ark4isdone
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