sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) (04/29/91)
Submitted-by: sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) Posting-number: Volume 12, Issue 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@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@uunet.uu.net argv@ora.com argv@zipcode.com