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