home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
x
/
volume15
/
olvwm-3.0
/
part16
< prev
next >
Wrap
Internet Message Format
|
1992-02-03
|
57KB
Path: uunet!sun-barr!ames!pasteur!nntp
From: scott.oaks@East.Sun.COM (Scott Oaks)
Newsgroups: comp.sources.x
Subject: v15i162: OpenLook Virtual Window Mgr (3.0), Part16/21
Message-ID: <1992Feb4.135937.8021@pasteur.Berkeley.EDU>
Date: 4 Feb 92 13:59:37 GMT
References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
Sender: dcmartin@msi.com (David C. Martin - Moderator)
Organization: University of California, at Berkeley
Lines: 1990
Approved: dcmartin@msi.com
Nntp-Posting-Host: postgres.berkeley.edu
Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
Posting-number: Volume 15, Issue 162
Archive-name: olvwm-3.0/part16
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
# "End of archive 16 (of 21)."
# Contents: LEGAL_NOTICE events.c slots.c wingframe.c
# Wrapped by dcmartin@fascet on Tue Jan 14 05:54:47 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'LEGAL_NOTICE' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'LEGAL_NOTICE'\"
else
echo shar: Extracting \"'LEGAL_NOTICE'\" \(2808 characters\)
sed "s/^X//" >'LEGAL_NOTICE' <<'END_OF_FILE'
X NOTICE TO USER: The source code, including the glyphs or icons
X forming a par of the OPEN LOOK TM Graphic User Interface, on this
X tape and in these files is copyrighted under U.S. and international
X laws. Sun Microsystems, Inc. of Mountain View, California owns
X the copyright and has design patents pending on many of the icons.
X AT&T is the owner of the OPEN LOOK trademark associated with the
X materials on this tape. Users and possessors of this source code
X are hereby granted a nonexclusive, royalty-free copyright and
X design patent license to use this code in individual and
X commercial software. A royalty-free, nonexclusive trademark
X license to refer to the code and output as "OPEN LOOK" compatible
X is available from AT&T if, and only if, the appearance of the
X icons or glyphs is not changed in any manner except as absolutely
X necessary to accommodate the standard resolution of the screen or
X other output device, the code and output is not changed except as
X authorized herein, and the code and output is validated by AT&T.
X Bigelow & Holmes is the owner of the Lucida (R) trademark for the
X fonts and bit-mapped images associated with the materials on this
X tape. Users are granted a royalty-free, nonexclusive license to use
X the trademark only to identify the fonts and bit-mapped images if,
X and only if, the fonts and bit-mapped images are not modified in any
X way by the user.
X
X
X Any use of this source code must include, in the user documentation
X and internal comments to the code, notices to the end user as
X follows:
X
X
X (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents
X pending in the U.S. and foreign countries. OPEN LOOK is a
X trademark of AT&T. Used by written permission of the owners.
X
X
X (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered
X trademark of Bigelow & Holmes. Permission to use the Lucida
X trademark is hereby granted only in association with the images
X and fonts described in this file.
X
X
X
X SUN MICROSYSTEMS, INC., AT&T, AND BIGELOW & HOLMES
X MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF
X THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
X WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.
X SUN MICROSYSTEMS, INC., AT&T AND BIGELOW & HOLMES,
X SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES
X WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED
X WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
X PARTICULAR PURPOSE. IN NO EVENT SHALL SUN MICROSYSTEMS,
X INC., AT&T OR BIGELOW & HOLMES BE LIABLE FOR ANY
X SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
X OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
X OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
X WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.
END_OF_FILE
if test 2808 -ne `wc -c <'LEGAL_NOTICE'`; then
echo shar: \"'LEGAL_NOTICE'\" unpacked with wrong size!
fi
# end of 'LEGAL_NOTICE'
fi
if test -f 'events.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'events.c'\"
else
echo shar: Extracting \"'events.c'\" \(16710 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
X#ident "@(#)events.c 1.1 olvwm version 1/3/92"
X
X/*
X * Based on
X#ident "@(#)events.c 26.40 91/09/14 SMI"
X *
X */
X
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X#include <sys/types.h>
X#include <sys/time.h>
X
X#include <X11/Xlib.h>
X#include <X11/Xresource.h>
X#include <X11/Xutil.h>
X#include <X11/keysym.h>
X
X#include "i18n.h"
X#include "ollocale.h"
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
Xextern int DeadChildren;
Xextern void ReapChildren();
X
X/* ===== globals ========================================================== */
X
XTime LastEventTime = (Time) 0;
XKeySym *KbdMap = NULL; /* pointer to current key table; 2d array */
Xint MinKeyCode = 0;
Xint MaxKeyCode = 0;
Xint KeySymsPerKeyCode = 0;
X
X/* ===== private data ===================================================== */
X
Xstatic int (*interposer)() = NULL;
Xstatic void *closure;
Xstatic List *deferredEventListHead = NULL_LIST;
Xstatic List *deferredEventListTail = NULL_LIST;
X
Xstatic struct timeval timeoutNext = {0, 0};
Xstatic TimeoutFunc timeoutFunc = NULL;
Xstatic void *timeoutClosure = NULL;
X
Xstatic XModifierKeymap *ModMap = NULL;
X
Xstatic explicitPointerGrab = False;
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 */
XWinGeneric *
XlookupWindow( 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 */
Xvoid
XsaveTimestamp( 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
X
X/*
X * Dispatches an event normally (i.e. not through an interposer). Looks up
X * the window structure from the event's window ID and calls the appropriate
X * event function for that window's class. All extension events are handled
X * through a single extension event handler in the class. If explicitGrab is
X * set, then someone has explicitly grabbed the pointer and redispatched the
X * event to a handler that is expecting an implicit grab, and so which won't
X * ungrab the pointer. We must therefore do an explicit ungrab of the
X * pointer.
X */
Xstatic void
XdispatchEvent(dpy, event, winInfo)
XDisplay *dpy;
XXEvent *event;
XWinGeneric *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 (DispatchVirtual(dpy, event))
X return;
X else {
X /* REMIND should we do anything with these events? */
X if (GRV.PrintOrphans)
X DebugEvent(event, "Orphaned (null window)");
X
X /* If a client unmaps and then remaps its window, the
X * MapRequest comes in on the frame window, but we just
X * destroyed that window (on the unmap) so it appears as
X * an orphan window. Hence we'll just create a new
X * frame/etc via StateNew()
X */
X if (event->xany.type == MapRequest) {
X StateNew(dpy, None,
X event->xmaprequest.window, False, NULL);
X }
X }
X
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 if (event->xany.type >= LASTEvent)
X evFunc = WinClass(winInfo)->core.extEventHdlr;
X else
X evFunc = WinClass(winInfo)->core.xevents[event->xany.type];
X
X if (evFunc != NULL)
X {
X (*evFunc)(dpy, event, winInfo);
X }
X else if (!DispatchVirtual(dpy, event))
X if (GRV.PrintOrphans)
X DebugEvent(event, "Orphaned");
X
X if (explicitPointerGrab && event->type == ButtonRelease &&
X AllButtonsUp(event))
X {
X XUngrabPointer(dpy, event->xbutton.time);
X }
X}
X
Xstatic int
XdispatchInterposer(dpy, event)
XDisplay *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
Xstatic void
XdoTimeout()
X{
X TimeoutFunc f;
X void *closure;
X
X f = timeoutFunc;
X closure = timeoutClosure;
X TimeoutCancel();
X (*f)(closure);
X}
X
Xstatic void
XnextEventOrTimeout(dpy, event)
XDisplay *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
X/*
X * Update our own modifier map. This is unfortunate, as we know Xlib already
X * keeps this information around.
X */
Xstatic void
XupdateModifierMap(dpy)
X Display *dpy;
X{
X if (ModMap != NULL)
X XFreeModifiermap(ModMap);
X ModMap = XGetModifierMapping(dpy);
X}
X
X
X/*
X * Update our own keyboard table. This is unfortunate, as we know Xlib
X * already keeps this information around.
X */
Xstatic void
XupdateKeyboardMap(dpy)
X Display *dpy;
X{
X if (KbdMap != NULL )
X XFree((char *)KbdMap);
X XDisplayKeycodes(dpy, &MinKeyCode, &MaxKeyCode);
X KbdMap = XGetKeyboardMapping(dpy, MinKeyCode, MaxKeyCode-MinKeyCode+1,
X &KeySymsPerKeyCode);
X}
X
X
X/*
X * Handle MappingNotify events. Refresh cached information about the keyboard
X * and the pointer.
X */
Xvoid
XhandleMappingNotify(dpy, e)
X Display *dpy;
X XEvent *e;
X{
X XMappingEvent *mapEvent = (XMappingEvent *)e;
X
X switch (mapEvent->request) {
X case MappingModifier:
X XRefreshKeyboardMapping(mapEvent);
X updateModifierMap(dpy);
X RefreshKeyGrabs(dpy);
X RefreshButtonGrabs(dpy);
X break;
X case MappingKeyboard:
X XRefreshKeyboardMapping(mapEvent);
X updateKeyboardMap(dpy);
X RefreshKeyGrabs(dpy);
X break;
X case MappingPointer:
X /* no need to handle pointer mapping changes */
X break;
X }
X}
X
X
X/*ARGSUSED*/
Xstatic void *
XredispatchEvent(e,c)
X XEvent *e;
X void *c;
X{
X dispatchEvent(e->xany.display, e, lookupWindow(e));
X MemFree(e);
X return (void *)NULL;
X}
X
X
X/*
X * Compute t2 - t1 and return the time value in diff. The tv_usec field is
X * always in the range 0..999999. This means that negative time values always
X * have tv_sec less than zero. For instance, negative one-half seconds is
X * represented with tv_sec == -1 and tv_usec == 500000.
X */
Xstatic void
Xtvdiff(t1, t2, diff)
X struct timeval *t1, *t2, *diff;
X{
X diff->tv_sec = t2->tv_sec - t1->tv_sec;
X diff->tv_usec = t2->tv_usec - t1->tv_usec;
X if (diff->tv_usec < 0) {
X diff->tv_sec -= 1;
X diff->tv_usec += 1000000;
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 */
Xvoid
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
X
X/*
X * Propagate an event to this window's parent. REMIND: doesn't update the
X * event fields or the event coordinates.
X */
Xint
XPropagateEventToParent(dpy,event,win)
XDisplay *dpy;
XXEvent *event;
XWinGeneric *win;
X{
X dispatchEvent(dpy,event,win->core.parent);
X}
X
X
X/*
X * Propagate a ButtonPress event to a child window. Win is assumed to be a
X * child of the event window. The event window and subwindow fields are
X * updated, and the coordinates are translated to the child's coordinate
X * system. Sets the explicitPointerGrab flag.
X */
Xvoid
XPropagatePressEventToChild(dpy, event, win)
X Display *dpy;
X XButtonPressedEvent *event;
X WinGeneric *win;
X{
X event->window = win->core.self;
X event->subwindow = None;
X event->x -= win->core.x;
X event->y -= win->core.y;
X dispatchEvent(dpy, event, win);
X explicitPointerGrab = True;
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 */
Xunsigned int
XFindModifierMask(kc)
XKeyCode kc;
X{
X int i, j;
X KeyCode *mapentry;
X
X if (ModMap == NULL || kc == 0)
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
X/*
X * Wait on dpy for some events to come in or for a timeout to occur. If
X * events come in, return True and change timeout to indicate the amount of
X * time remaining. If no events come in before the timeout expires, return
X * False. A negative timestamp is considered to have timed out immediately.
X */
XBool
XAwaitEvents(dpy, timeout)
X Display *dpy;
X struct timeval *timeout;
X{
X struct timeval starttime, curtime, diff1, diff2;
X fd_set rfds;
X int s;
X
X if (timeout->tv_sec < 0)
X return False;
X
X (void) gettimeofday(&starttime, NULL);
X
X while (1) {
X FD_ZERO(&rfds);
X FD_SET(ConnectionNumber(dpy), &rfds);
X s = select(ConnectionNumber(dpy)+1, &rfds, NULL, NULL, timeout);
X if (s == 0) {
X /* we timed out without getting anything */
X return False;
X }
X
X /*
X * If an error occurred, report it and return False.
X */
X if (s == -1 && errno != EINTR) {
X perror("select");
X#ifdef DEBUG
X fputs("olvwm: generating core dump for analysis...\n", stderr);
X if (fork() == 0) {
X abort();
X exit(1);
X }
X#endif
X return False;
X }
X
X /*
X * Either we got interrupted or the descriptor became ready, or both.
X * Compute the remaining time on the timeout. This can be negative,
X * because there is a slight window for delays between the select()
X * call above and this gettimeofday() call. This means that we can
X * return an indication of valid data to the caller, yet also return
X * a value for the time remaining that is less than or equal to zero.
X */
X (void) gettimeofday(&curtime, NULL);
X tvdiff(&starttime, &curtime, &diff1);
X tvdiff(&diff1, timeout, &diff2);
X *timeout = diff2;
X starttime = curtime;
X
X /*
X * If we got some data, return True. Otherwise, we were interrupted.
X * If we timed out, return False. If not, there is time remaining;
X * continue around the loop.
X */
X if (s > 0)
X return True;
X
X if (timeout->tv_sec < 0)
X return False;
X }
X}
X
X
X/***************************************************************************
X* Interposer functions
X***************************************************************************/
X
X/*
X * InstallInterposer
X *
X * Install an event interposition function. Nested interposition is illegal.
X */
Xvoid
XInstallInterposer( func, cl )
X Bool (*func)();
X void *cl;
X{
X if ( interposer != NULL ) {
X fputs( gettext("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 * Uninstalls an event interposition function. Does nothing if there is
X * currently no interposer. Replays any queued events. Inhibits focus
X * changes and colormap installation while replaying them. This prevents
X * redundant focus changes and colormap installation.
X */
Xvoid
XUninstallInterposer()
X{
X interposer = (int (*)()) NULL;
X
X if (deferredEventListHead != NULL) {
X ClientInhibitFocus(True);
X ColormapInhibit(True);
X ListApply(deferredEventListHead, redispatchEvent, 0);
X ListDestroy(deferredEventListHead);
X deferredEventListHead = deferredEventListTail = NULL_LIST;
X ClientInhibitFocus(False);
X ColormapInhibit(False);
X }
X}
X
X
X/*
X * Return an indication of whether an interposer is currently installed.
X */
XBool
XInterposerInstalled()
X{
X return (interposer != NULL) ? True : False;
X}
X
X
X/***************************************************************************
X* Timeout functions
X***************************************************************************/
X
X/* TimeoutRequest(t,f,c) -- request that a timeout be generated t microseconds
X * in the future; when the timeout occurs, the function f is called
X * with the closure c.
X */
Xvoid
XTimeoutRequest(t,f,c)
Xint t;
XTimeoutFunc f;
Xvoid *c;
X{
X#ifdef DEBUG
X if (timeoutFunc != NULL)
X {
X ErrorWarning("Timeout being set while another timeout current");
X }
X#endif
X gettimeofday(&timeoutNext,NULL);
X timeoutNext.tv_sec += t / 1000000;
X timeoutNext.tv_usec += t % 1000000;
X if (timeoutNext.tv_usec >= 1000000) {
X timeoutNext.tv_usec -= 1000000;
X timeoutNext.tv_sec += 1;
X }
X timeoutFunc = f;
X timeoutClosure = c;
X}
X
X/* TimeoutCancel() -- cancel an outstanding timeout.
X */
Xvoid
XTimeoutCancel()
X{
X timeoutNext.tv_sec = 0;
X timeoutNext.tv_usec = 0;
X timeoutFunc = NULL;
X timeoutClosure = NULL;
X}
X
X
X/*
X * Initialize the event handling system. This function is called exactly
X * once at startup.
X */
Xvoid
XInitEvents(dpy)
X Display *dpy;
X{
X updateKeyboardMap(dpy);
X updateModifierMap(dpy);
X}
END_OF_FILE
if test 16710 -ne `wc -c <'events.c'`; then
echo shar: \"'events.c'\" unpacked with wrong size!
fi
# end of 'events.c'
fi
if test -f 'slots.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'slots.c'\"
else
echo shar: Extracting \"'slots.c'\" \(16468 characters\)
sed "s/^X//" >'slots.c' <<'END_OF_FILE'
X/*
X * (c) Copyright 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
X#ident "@(#)slots.c 1.1 olvwm version 1/3/92"
X
X/*
X * Based on
X#ident "@(#)slots.c 26.8 91/09/14 SMI"
X *
X */
X
X#include <stdio.h>
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
X#include "i18n.h"
X#include "ollocale.h"
X#include "mem.h"
X#include "st.h"
X#include "olwm.h"
X#include "win.h"
X#include "globals.h"
X#include "list.h"
X#include "slots.h"
X
X#define PLUSINFINITY 0xfffffff /* REMIND fix this for architecture-independence */
X
X/***************************************************************************
X* Local functions
X***************************************************************************/
X
X#define ROUNDUP(n,d) (((n)+(d)-1)/(d))
X/* #define ROUND(n,d) ((0.5+((float)(n)/(float)(d)))*(int)(d)) */
X#define ROUND(n,d) (((((n)%(d))>((d)/2))?(((n)/(d))+1):((n)/(d)))*(d))
X
X#define SLOTOFFSET(ig,ma,mi) (((ma))*(ig)->mislots+(mi))
X#define AOCCUPANCY(ig,ma,mi) ((ig->occupancy+SLOTOFFSET((ig),(ma),(mi))))
X#define OCCUPANCY(ig,ma,mi) (*(AOCCUPANCY((ig),(ma),(mi))))
X
X#define ISVERT(so) (((so)==SOBottomToTop)||((so)==SOTopToBottom))
X#define ISHORZ(so) (((so)==SOLeftToRight)||((so)==SORightToLeft))
X#define ISDECREASING(so) (((so)==SORightToLeft)||((so)==SOBottomToTop))
X
Xstatic char *
Xsotochar(so)
XSlotOrder so;
X{
X if (so == SOTopToBottom)
X return ("SOTopToBottom");
X if (so == SOBottomToTop)
X return ("SOBottomToTop");
X if (so == SOLeftToRight)
X return ("SOLeftToRight");
X if (so == SORightToLeft)
X return ("SORightToLeft");
X return("SOIllegal");
X}
X
X#ifdef notused
X#ifdef DEBUG
X/* dumpocc -- print the occupancy count table to stderr
X */
Xstatic void
Xdumpocc()
X{
X int ima, imi;
X
X fprintf(stderr,"dump of occupancy table:\n");
X for (ima = 0; ima<maslots; ima++)
X for (imi = 0; imi<mislots; imi++)
X if (OCCUPANCY(ima,imi)!=0)
X fprintf(stderr,"%x: occ[%d,%d]/[%d] = %d\n",AOCCUPANCY(ima,imi),ima,imi,SLOTOFFSET(ima,imi),OCCUPANCY(ima,imi));
X fprintf(stderr,"end of dump of occupancy table\n");
X}
X#endif
X#endif
X
X
X/* setMajorMinor -- set two output variables from two input variables,
X * based on the major/minor settings.
X */
Xstatic void
XsetMajorMinor(iconGrid,r,c,pma,pmi)
XIconGrid *iconGrid;
Xint r, c, *pma, *pmi;
X{
X if (ISVERT(iconGrid->SOmajor))
X {
X *pma = r;
X *pmi = c;
X }
X else
X {
X *pma = c;
X *pmi = r;
X }
X}
X
X/* setAbsolute -- set two output variables from two input variables, based
X * on major/minor settings; this is the inverse of setMajorMinor.
X */
Xstatic void
XsetAbsolute(iconGrid,ma,mi,pr,pc)
XIconGrid *iconGrid;
Xint ma, mi;
Xint *pr, *pc;
X{
X if (ISVERT(iconGrid->SOmajor))
X {
X *pr = ma;
X *pc = mi;
X }
X else
X {
X *pc = ma;
X *pr = mi;
X }
X}
X
X/* incrRegion -- increment the occupancy count of a region
X */
Xstatic void
XincrRegion(iconGrid,slot,val)
XIconGrid *iconGrid;
XIconSlot *slot;
Xint val;
X{
X int ii,jj;
X
X for (ii = slot->ma;
X (ii>=0)&&(ii<iconGrid->maslots)&&(ii<slot->ma+slot->maw); ii++)
X for (jj = slot->mi;
X (jj>=0)&&(jj<iconGrid->mislots)&&(jj<slot->mi+slot->miw); jj++)
X {
X if ((OCCUPANCY(iconGrid,ii,jj) += val) < iconGrid->minoccupancy)
X iconGrid->minoccupancy = OCCUPANCY(iconGrid,ii,jj);
X }
X}
X
X/* findMinMaxRgn -- find the minimum and maximum occupancies of a region
X */
Xstatic void
XfindMinMaxRgn(iconGrid,ma, mi, nmajor, nminor, pminrgn, pmaxrgn)
XIconGrid *iconGrid;
Xint ma, mi, nmajor, nminor, *pminrgn, *pmaxrgn;
X{
X int min, max;
X int ii, jj;
X int occ;
X
X min = PLUSINFINITY;
X max = -1;
X
X for (ii=ma; ii<ma+nmajor; ii++)
X for (jj = mi; jj<mi+nminor; jj++)
X {
X occ = OCCUPANCY(iconGrid,ii,jj);
X if (occ < min)
X min = occ;
X if (occ > max)
X max = occ;
X }
X *pminrgn = min;
X *pmaxrgn = max;
X}
X
Xstatic IconSlot *
XincrDynamicSlots(iconGrid,nmajor, nminor)
XIconGrid *iconGrid;
Xint nmajor, nminor;
X{
X int minoccrgn; /* smallest occupancy found for a region of given size */
X int minfound, minfoundrgn; /* smallest occupancy found for one slot
X * and a region respectively; used to reset
X * search values */
X int ma, mi; /* indices in major and minor directions */
X int maxrgn, minrgn; /* max and min occupancies in a region */
X IconSlot *slot = MemNew(IconSlot);
X
X minoccrgn = iconGrid->minoccupancy;
X slot->positioned = False;
X
X for (;;) /* will actually only iterate twice */
X {
X minfound = minfoundrgn = PLUSINFINITY;
X for (ma = 0; (ma <= iconGrid->maslots-nmajor); ma++)
X {
X for (mi = 0; (mi <= iconGrid->mislots-nminor); mi++)
X {
X findMinMaxRgn(iconGrid,ma,mi,nmajor,nminor,&minrgn,&maxrgn);
X if (minrgn < minfound)
X minfound = minrgn;
X if (maxrgn < minfoundrgn)
X minfoundrgn = maxrgn;
X if (maxrgn <= minoccrgn)
X {
X slot->ma = ma;
X slot->mi = mi;
X slot->maw = nmajor;
X slot->miw = nminor;
X incrRegion(iconGrid,slot,1);
X return slot;
X }
X }
X }
X /* no regions available with occupancy <= known minimum */
X if (minfound > iconGrid->minoccupancy) /* increase slot minimum */
X iconGrid->minoccupancy = minfound;
X minoccrgn = minfoundrgn; /* increase local region min */
X }
X}
X
X/* setIconPos -- given a slot, position the icon frame window accordingly.
X */
Xstatic void
XsetIconPos(win, slot)
XWinIconFrame *win;
XIconSlot *slot;
X{
X int x,y;
X IconGrid *iconGrid = win->core.client->scrInfo->iconGrid;
X
X if (iconGrid->SOmajor == SOTopToBottom)
X {
X y = ICON_GRID_HEIGHT*slot->ma;
X if (iconGrid->SOminor == SOLeftToRight)
X {
X x = ICON_GRID_WIDTH*slot->mi;
X }
X else
X {
X x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
X }
X }
X else if (iconGrid->SOmajor == SOBottomToTop)
X {
X y = iconGrid->pixvert - ICON_GRID_HEIGHT*slot->ma - win->core.height;
X if (iconGrid->SOminor == SOLeftToRight)
X {
X x = ICON_GRID_WIDTH*slot->mi;
X }
X else
X {
X x = iconGrid->pixhoriz - slot->mi*ICON_GRID_WIDTH - win->core.width;
X }
X }
X else if (iconGrid->SOmajor == SOLeftToRight)
X {
X x = ICON_GRID_WIDTH*slot->ma;
X if (iconGrid->SOminor == SOTopToBottom)
X {
X y = ICON_GRID_HEIGHT*slot->mi;
X }
X else
X {
X y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
X }
X }
X else if (iconGrid->SOmajor == SORightToLeft)
X {
X x = iconGrid->pixhoriz - ICON_GRID_WIDTH*slot->ma - win->core.width;
X if (iconGrid->SOminor == SOTopToBottom)
X {
X y = ICON_GRID_HEIGHT*slot->mi;
X }
X else
X {
X y = iconGrid->pixvert - slot->mi*ICON_GRID_HEIGHT - win->core.height;
X }
X }
X
X x += slot->off_x;
X y += slot->off_y;
X (WinFunc(win,core.newposfunc))(win, x, y);
X}
X
X/* incrPositionedSlots -- an icon has been explicitly positioned; create an
X * iconslot record and increment the occupancy count of the affected slots.
X */
Xstatic IconSlot *
XincrPositionedSlots(iconGrid,x,y,w,h,snaptogrid)
XIconGrid *iconGrid;
Xint x,y,w,h;
XBool snaptogrid;
X{
X IconSlot *slot = MemNew(IconSlot);
X#define ROUNDIF(v,w) (snaptogrid?ROUND((v),(w)):(v))/(w)
X#define ROUNDDIM(p,s,w) (ROUNDUP(((p)%(w))+(s),(w)))
X
X if (iconGrid->SOmajor == SOTopToBottom)
X {
X slot->ma = ROUNDIF(y,ICON_GRID_HEIGHT);
X slot->maw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
X if (iconGrid->SOminor == SOLeftToRight)
X {
X slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
X slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
X }
X else
X {
X slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
X slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
X }
X }
X else if (iconGrid->SOmajor == SOBottomToTop)
X {
X slot->ma = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
X slot->maw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
X slot->miw = w;
X if (iconGrid->SOminor == SOLeftToRight)
X {
X slot->mi = ROUNDIF(x,ICON_GRID_WIDTH);
X slot->miw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
X }
X else
X {
X slot->mi = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
X slot->miw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
X }
X }
X else if (iconGrid->SOmajor == SOLeftToRight)
X {
X slot->ma = ROUNDIF(x,ICON_GRID_WIDTH);
X slot->maw = ROUNDDIM(x,w,ICON_GRID_WIDTH);
X if (iconGrid->SOminor == SOTopToBottom)
X {
X slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
X slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
X }
X else
X {
X slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
X slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
X }
X }
X else if (iconGrid->SOmajor == SORightToLeft)
X {
X slot->ma = ROUNDIF(iconGrid->pixhoriz-(x+w),ICON_GRID_WIDTH);
X slot->maw = ROUNDDIM(iconGrid->pixhoriz-(x+w),w,ICON_GRID_WIDTH);
X if (iconGrid->SOminor == SOTopToBottom)
X {
X slot->mi = ROUNDIF(y,ICON_GRID_HEIGHT);
X slot->miw = ROUNDDIM(y,h,ICON_GRID_HEIGHT);
X }
X else
X {
X slot->mi = ROUNDIF(iconGrid->pixvert-(y+h),ICON_GRID_HEIGHT);
X slot->miw = ROUNDDIM(iconGrid->pixvert-(y+h),h,ICON_GRID_HEIGHT);
X }
X }
X if (slot->ma < 0) slot->ma = 0;
X if (slot->ma >= iconGrid->maslots) slot->ma = iconGrid->maslots-1;
X if (slot->mi < 0) slot->mi = 0;
X if (slot->mi >= iconGrid->mislots) slot->mi = iconGrid->mislots-1;
X slot->positioned = True;
X incrRegion(iconGrid,slot,1);
X return slot;
X}
X
X
X/***************************************************************************
X* Global functions
X***************************************************************************/
X
X/*
X * SlotInit --
X */
XIconGrid *
XSlotInit(dpy,screenno)
XDisplay *dpy;
Xint screenno;
X{
X IconGrid *iconGrid;
X int occLen;
X
X iconGrid = MemNew(IconGrid);
X iconGrid->iconList = NULL_LIST;
X iconGrid->pixhoriz = DisplayWidth(dpy,screenno);
X iconGrid->pixvert = DisplayHeight(dpy,screenno);
X iconGrid->slotshoriz = iconGrid->pixhoriz/ICON_GRID_WIDTH;
X iconGrid->slotsvert = iconGrid->pixvert/ICON_GRID_HEIGHT;
X occLen = iconGrid->slotshoriz * iconGrid->slotsvert * sizeof(int);
X iconGrid->occupancy = MemAlloc(occLen);
X iconGrid->minoccupancy = 0;
X
X SlotSetLocations(dpy,iconGrid);
X
X return iconGrid;
X}
X
X/* SlotAlloc - given a sized and possibly positioned icon window, allocate
X * the appropriate slots for it. If the window is positioned,
X * True should be passed for the second parameter, and the x,y
X * position will be honoured. If the window is not positioned, it
X * will be positioned by this function to the appropriate slots(s).
X * If snaptogrid is true and positioned is true, the given position is
X * modified so that the upper left corner of the icon is at the closest
X * icon grid point. Modifies the icon structure to assign it the icon
X * slot.
X * Returns an IconSlot pointer if successful; NULL otherwise.
X *
X * If the window is not positioned, the x and y coordinates are used as
X * offsets to the position icon; this allows particular icons to be located`
X * in a particular logical screen within the virtual desktop.
X */
Xstruct _iconSlot *
XSlotAlloc(winicon, positioned, snaptogrid)
XWinIconFrame *winicon;
XBool positioned;
XBool snaptogrid;
X{
X int nhoriz, nvert; /* number of slots occupied, horizontally & vertically */
X int nmajor, nminor; /* number of slots occupied, in major & minor directions */
X IconSlot *slot;
X IconGrid *iconGrid = winicon->core.client->scrInfo->iconGrid;
X int scr_x, scr_y;
X int dw, dh;
X
X iconGrid->iconList = ListCons(winicon, iconGrid->iconList);
X
X if (positioned)
X {
X dw = DisplayWidth(winicon->core.client->dpy,
X winicon->core.client->screen);
X dh = DisplayHeight(winicon->core.client->dpy,
X winicon->core.client->screen);
X scr_x = abs((winicon->core.x + ICON_HORZBORDER) % dw);
X scr_y = abs((winicon->core.y + ICON_VERTBORDER) % dh);
X slot = incrPositionedSlots(iconGrid, scr_x, scr_y,
X winicon->core.width, winicon->core.height, snaptogrid);
X if (winicon->core.x > 0)
X slot->off_x = ((winicon->core.x + ICON_HORZBORDER) / dw) * dw;
X else slot->off_x = ((winicon->core.x + ICON_HORZBORDER - dw) / dw) * dw;
X if (winicon->core.y > 0)
X slot->off_y = ((winicon->core.y + ICON_VERTBORDER) / dh) * dh;
X else slot->off_y = ((winicon->core.y + ICON_VERTBORDER - dh) / dh) * dh;
X winicon->iconslot = slot;
X if (snaptogrid)
X setIconPos(winicon, slot);
X else
X (WinFunc(winicon,core.newposfunc))(winicon,winicon->core.x,winicon->core.y);
X }
X else
X {
X nhoriz = ROUNDUP(winicon->core.width, ICON_GRID_WIDTH);
X nvert = ROUNDUP(winicon->core.height, ICON_GRID_HEIGHT);
X setMajorMinor(iconGrid, nvert, nhoriz, &nmajor, &nminor);
X slot = incrDynamicSlots(iconGrid, nmajor, nminor);
X slot->off_x = winicon->core.x + ICON_HORZBORDER;
X slot->off_y = winicon->core.y + ICON_VERTBORDER;
X winicon->iconslot = slot;
X setIconPos(winicon,slot);
X }
X
X return slot;
X}
X
X/* SlotFree -- An icon is going away, so its references to slots should also go
X * away. Returns True iff the free was successful.
X * Note that if this code is changed, the similar code in SlotSetLocations
X * may need to be changed also.
X */
XBool
XSlotFree(winicon)
XWinIconFrame *winicon;
X{
X List **l;
X IconGrid *iconGrid = winicon->core.client->scrInfo->iconGrid;
X WinIconFrame *win;
X
X if (winicon->iconslot == NULL)
X {
X return;
X }
X
X incrRegion(iconGrid,winicon->iconslot,-1);
X MemFree(winicon->iconslot);
X winicon->iconslot = NULL;
X
X l = &iconGrid->iconList;
X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
X {
X if (win == winicon)
X {
X ListDestroyCell(l);
X break;
X }
X }
X}
X
X/* sets the order in which slots are allocated for icons which are
X * not explicitly positioned. The order is gotten from the global
X * resource vector.
X * For example, the AlongBottom order is expressed as
X * major BottomToTop, minor LeftToRight. The major and minor orders
X * cannot be both vertical or horizontal. Any icons which were
X * automatically positioned are repositioned to equivalent positions
X * in the new order.
X */
X/*ARGSUSED*/
XBool
XSlotSetLocations(dpy,iconGrid)
XDisplay *dpy;
XIconGrid *iconGrid;
X{
X List *lauto, *lpos;
X List **l;
X WinIconFrame *win;
X int ima, imi;
X
X /* set up the new order of things */
X switch (GRV.IconPlacement)
X {
X case AlongTop:
X iconGrid->SOmajor = SOTopToBottom;
X iconGrid->SOminor = SOLeftToRight;
X break;
X
X case AlongTopRL:
X iconGrid->SOmajor = SOTopToBottom;
X iconGrid->SOminor = SORightToLeft;
X break;
X
X case AlongBottom:
X iconGrid->SOmajor = SOBottomToTop;
X iconGrid->SOminor = SOLeftToRight;
X break;
X
X case AlongBottomRL:
X iconGrid->SOmajor = SOBottomToTop;
X iconGrid->SOminor = SORightToLeft;
X break;
X
X case AlongLeft:
X iconGrid->SOmajor = SOLeftToRight;
X iconGrid->SOminor = SOTopToBottom;
X break;
X
X case AlongLeftBT:
X iconGrid->SOmajor = SOLeftToRight;
X iconGrid->SOminor = SOBottomToTop;
X break;
X
X case AlongRight:
X iconGrid->SOmajor = SORightToLeft;
X iconGrid->SOminor = SOTopToBottom;
X break;
X
X case AlongRightBT:
X iconGrid->SOmajor = SORightToLeft;
X iconGrid->SOminor = SOBottomToTop;
X break;
X }
X
X setMajorMinor(iconGrid,iconGrid->slotsvert,iconGrid->slotshoriz,
X &(iconGrid->maslots),&(iconGrid->mislots));
X
X if (iconGrid->iconList == NULL_LIST)
X {
X for (ima = 0; ima<iconGrid->maslots; ima++)
X for (imi = 0; imi<iconGrid->mislots; imi++)
X OCCUPANCY(iconGrid,ima,imi)=0;
X return;
X }
X
X /* partition existing icons */
X lauto = NULL_LIST;
X lpos = NULL_LIST;
X l = &iconGrid->iconList;
X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
X {
X if (!win->iconslot->positioned)
X {
X lauto = ListCons(win,lauto);
X }
X else
X {
X lpos = ListCons(win,lpos);
X }
X /* this is the basics of a SlotFree */
X MemFree(win->iconslot);
X win->iconslot = NULL;
X }
X ListDestroy(iconGrid->iconList);
X iconGrid->iconList = NULL_LIST;
X
X for (ima = 0; ima<iconGrid->maslots; ima++)
X for (imi = 0; imi<iconGrid->mislots; imi++)
X OCCUPANCY(iconGrid,ima,imi)=0;
X
X /* place positioned icons */
X l = &lpos;
X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
X {
X SlotAlloc(win,True,False);
X (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
X }
X ListDestroy(lpos);
X
X /* place auto-positioned icons */
X l = &lauto;
X for (win = ListEnum(l); win != NULL; win = ListEnum(l))
X {
X SlotAlloc(win,False,False);
X (WinFunc(win,core.setconfigfunc))(win->core.client->dpy,win);
X }
X ListDestroy(lauto);
X}
END_OF_FILE
if test 16468 -ne `wc -c <'slots.c'`; then
echo shar: \"'slots.c'\" unpacked with wrong size!
fi
# end of 'slots.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'\" \(15552 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
X/*
X * wingframe.c -- generic frame window routines
X */
X
X#ident "@(#)wingframe.c 1.1 olvwm version 1/3/92"
X
X/*
X * Based on
X#ident "@(#)wingframe.c 26.27 91/09/14 SMI"
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 <X11/keysym.h>
X#include <olgx/olgx.h>
X
X#include "i18n.h"
X#include "ollocale.h"
X#include "mem.h"
X#include "olwm.h"
X#include "win.h"
X#include "globals.h"
X#include "events.h"
X#include "virtual.h"
X
X/***************************************************************************
X* private data
X***************************************************************************/
X
X/*
X * REMIND
X * The hadSelect variable is necessary because we sometimes receive
X * MotionNotify events with all buttons up, even though we ask for only
X * ButtonMotionMask. We set hadSelect only on receipt of an event that is
X * bound to the Select action, and we ignore motion events that occur if
X * hadSelect isn't set.
X */
Xstatic Bool hadSelect = False;
Xstatic Time timeOfLastButPress = 0;
Xstatic int buttonPressX;
Xstatic int buttonPressY;
Xstatic XButtonEvent lastSelectRelease;
Xstatic XButtonEvent lastSelectPress;
Xstatic Time lastDoubleClickTime;
Xstatic SemanticAction currentAction = ACTION_NONE;
X
X/***************************************************************************
X* forward-declared functions
X***************************************************************************/
X
Xextern void ClientSetCurrent();
X
X/***************************************************************************
X* static functions
X***************************************************************************/
X
Xvoid
XautoRaise(frame)
X WinGenericFrame *frame;
X{
X Bool samescreen;
X Window root, child;
X int rootx, rooty, winx, winy;
X unsigned int state;
X Client *cli = frame->core.client;
X if (cli->isFocus) {
X if (GRV.FocusFollowsMouse) {
X samescreen = XQueryPointer(cli->dpy, WinRootID(frame),
X &root, &child, &rootx, &rooty, &winx, &winy, &state);
X if (samescreen && child == frame->core.self)
X ClientFront(cli);
X } else {
X ClientFront(cli);
X }
X }
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 */
Xint
XGFrameSelect(dpy, winInfo, selected)
XDisplay *dpy;
XWinGeneric *winInfo;
XBool 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 * If colormap installation is tracking the input focus, get the first entry
X * in the client's WM_COLORMAP_WINDOWS list and install its colormap;
X * otherwise, install the pane's colormap.
X */
X/*ARGSUSED*/
Xint
XGFrameFocus(dpy, winInfo, focus)
XDisplay *dpy;
XWinGenericFrame *winInfo;
XBool focus;
X{
X WinGeneric *cmwi;
X
X if (focus) {
X ClientSetCurrent(winInfo->core.client);
X ClientSetWindowState(winInfo->core.client);
X
X if (GRV.ColorTracksInputFocus) {
X if (winInfo->core.client->colormapWins)
X cmwi = winInfo->core.client->colormapWins->value;
X else
X cmwi = (WinGeneric *) winInfo->fcore.panewin;
X LockColormap(dpy, winInfo->core.client, cmwi);
X }
X
X if (GRV.AutoRaise) {
X if (GRV.AutoRaiseDelay > 0) {
X TimeoutCancel();
X TimeoutRequest(GRV.AutoRaiseDelay, autoRaise, winInfo);
X } else {
X autoRaise(winInfo);
X }
X }
X }
X}
X
X/*
X * GFrameSetConfigFunc -- change configuration of frame window
X * REMIND: ensure that transient windows are treated properly.
X */
Xint
XGFrameSetConfigFunc(dpy, win)
XDisplay *dpy;
XWinGenericFrame *win;
X{
X XWindowChanges xwc;
X int dw, dh;
X Client *cli = win->core.client;
X
X if (win->core.dirtyconfig)
X {
X if (cli->sticky) {
X dw = DisplayWidth(win->core.client->dpy,
X win->core.client->screen);
X dh = DisplayHeight(win->core.client->dpy,
X win->core.client->screen);
X
X if (win->core.x + (int) win->core.width < 0) {
X win->core.x = (dw + (win->core.x % dw)) % dw;
X win->core.dirtyconfig |= CWX;
X }
X else if (win->core.x >= dw) {
X win->core.x = win->core.x % dw;
X win->core.dirtyconfig |= CWX;
X }
X if (win->core.y + (int) win->core.height < 0) {
X win->core.y = (dh + (win->core.y % dh)) % dh;
X win->core.dirtyconfig |= CWY;
X }
X else if (win->core.y >= dh) {
X win->core.y = win->core.y % dh;
X win->core.dirtyconfig |= CWY;
X }
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
X ConfigureWindow(dpy,win,win->core.dirtyconfig,&xwc);
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 */
Xvoid
XGFrameSetStack(win, mask, mode, sib)
XWinGenericFrame *win;
Xint mask;
Xint mode;
XWindow 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 */
Xvoid
XGFrameSetConfig(win,x,y,w,h)
XWinGenericFrame *win;
Xint 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 */
Xint
XGFrameEventButtonRelease(dpy, event, frameInfo)
XDisplay *dpy;
XXEvent *event;
XWinGenericFrame *frameInfo;
X{
X WinGenericPane *winPane = (WinGenericPane*)frameInfo->fcore.panewin;
X Client *cli = frameInfo->core.client;
X
X if (!AllButtonsUp(event))
X return;
X
X#define bevent (event->xbutton)
X
X switch (currentAction)
X {
X case ACTION_SELECT:
X if (GRV.SelectWindows) {
X ClearSelections(dpy);
X AddSelection(cli, event->xbutton.time);
X }
X
X ClientSetCurrent(cli);
X ClientFront(cli);
X
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 currentAction = ACTION_NONE;
X break; /* out of ACTION_SELECT case */
X case ACTION_ADJUST:
X if (WinFunc(frameInfo,fcore.adjustClick) != NULL)
X {
X (WinFunc(frameInfo,fcore.adjustClick))(dpy,event,frameInfo);
X }
X currentAction = ACTION_NONE;
X break;
X
X }
X}
X
X/*
X * GFrameEventMotionNotify -- a button is down and the pointer is moving
X */
Xint
XGFrameEventMotionNotify(dpy, event, frameInfo)
XDisplay *dpy;
XXEvent *event;
XWinGenericFrame *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
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 */
Xint
XGFrameEventButtonPress(dpy, event, frameInfo)
XDisplay *dpy;
XXEvent *event;
XWinGenericFrame *frameInfo;
X{
X WinPane *winPane = (WinPane*)frameInfo->fcore.panewin;
X Window panewindow = winPane->core.self;
X SemanticAction a;
X unsigned int ignoremask;
X
X ignoremask = ModMaskMap[MOD_CONSTRAIN] |
X ModMaskMap[MOD_INVERT] |
X ModMaskMap[MOD_REDUCE];
X
X a = ResolveMouseBinding(dpy, event, ignoremask);
X
X switch (a) {
X case ACTION_SELECT:
X currentAction = a;
X /*
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 ACTION_SELECT */
X
X case ACTION_ADJUST:
X currentAction = a;
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 }
X break;
X case ACTION_MENU:
X currentAction = a;
X if (WinFunc(frameInfo,fcore.menuPress) != NULL)
X (WinFunc(frameInfo,fcore.menuPress))(dpy, event, frameInfo);
X break;
X
X } /* End switch on button pressed */
X}
X
X
X/*
X * GFrameEventEnterNotify
X *
X * If we entered from outside and we're in follows-mouse mode, set the focus.
X * If we enter the frame from the pane or directly from elsewhere (i.e.
X * nonlinearly) install the appropriate colormap.
X */
Xint
XGFrameEventEnterNotify(dpy, event, frameInfo)
XDisplay *dpy;
XXEvent *event;
XWinGenericFrame *frameInfo;
X{
X Client *cli = frameInfo->core.client;
X
X if (GRV.FocusFollowsMouse && event->xcrossing.detail != NotifyInferior)
X ClientSetFocus(cli,True,event->xcrossing.time);
X
X switch (event->xcrossing.detail) {
X case NotifyInferior:
X case NotifyNonlinear:
X ColorWindowCrossing(dpy, event, cli->scrInfo->rootwin);
X break;
X }
X}
X
X
X/*
X * GFrameEventFocus
X *
X * If the focus changed normally (i.e. not as the result of a keyboard grab or
X * ungrab), call the focus functions.
X */
Xint
XGFrameEventFocus(dpy, event, frameInfo)
X Display *dpy;
X XEvent *event;
X WinGenericFrame *frameInfo;
X{
X switch (event->xfocus.mode) {
X case NotifyNormal:
X case NotifyWhileGrabbed:
X if (event->xfocus.detail <= NotifyNonlinearVirtual) {
X if (event->type == FocusIn)
X WinCallFocus(frameInfo, True);
X else {
X Client *cli;
X
X cli = frameInfo->core.client;
X /*
X * When we lose focus,
X * we have to WinCallFocus on both the Icon and the regular
X * Frame: if we double click on an icon, it gets input
X * focus and when it loses it, it must redraw the frame.
X * Otherwise, the newly opened frame gets drawn as if it
X * had input focus
X *
X * We can't do this when getting focus, since it confuses
X * autoraise. There's got to be a better way . . .
X */
X if (cli->framewin)
X WinCallFocus(cli->framewin, False);
X if (cli->iconwin)
X WinCallFocus(cli->iconwin, False);
X }
X }
X break;
X }
X}
END_OF_FILE
if test 15552 -ne `wc -c <'wingframe.c'`; then
echo shar: \"'wingframe.c'\" unpacked with wrong size!
fi
# end of 'wingframe.c'
fi
echo shar: End of archive 16 \(of 21\).
cp /dev/null ark16isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 21 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
--
Molecular Simulations, Inc. mail: dcmartin@postgres.berkeley.edu
796 N. Pastoria Avenue uucp: uwvax!ucbvax!dcmartin
Sunnyvale, California 94086 at&t: 408/522-9236