home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-04 | 55.5 KB | 2,179 lines |
- Newsgroups: comp.sources.x
- Path: uunet!elroy.jpl.nasa.gov!ames!pasteur!nntp
- From: scott.oaks@East.Sun.COM (Scott Oaks)
- Subject: v15i153: OpenLook Virtual Window Mgr (3.0), Part07/21
- Message-ID: <1992Feb4.135625.7258@pasteur.Berkeley.EDU>
- Sender: dcmartin@msi.com (David C. Martin - Moderator)
- Nntp-Posting-Host: postgres.berkeley.edu
- Organization: University of California, at Berkeley
- References: <csx-15i147-olvwm-3.0@uunet.UU.NET>
- Date: Tue, 4 Feb 1992 13:56:25 GMT
- Approved: dcmartin@msi.com
-
- Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
- Posting-number: Volume 15, Issue 153
- Archive-name: olvwm-3.0/part07
-
- # 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 7 (of 21)."
- # Contents: client.c events.h winpush.c
- # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:43 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'client.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'client.c'\"
- else
- echo shar: Extracting \"'client.c'\" \(37162 characters\)
- sed "s/^X//" >'client.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/* client.c - functions relating to clients as a whole
- X */
- X
- X#ident "@(#)client.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)client.c 26.42 91/09/14 SMI"
- X *
- X */
- X
- X#include <errno.h>
- X#include <stdio.h>
- X#include <X11/Xos.h>
- X#include <X11/Xlib.h>
- X#include <X11/Xutil.h>
- X#include <X11/Xatom.h>
- X#include <X11/keysym.h>
- X#include <olgx/olgx.h>
- X
- X#include "i18n.h"
- X#include "ollocale.h"
- X#include "events.h"
- X#include "mem.h"
- X#include "olwm.h"
- X#include "win.h"
- X#include "group.h"
- X#include "globals.h"
- X#include "virtual.h"
- X
- X/***************************************************************************
- X* global data
- X***************************************************************************/
- X
- X/*
- X * List of currently active clients. All frames and icons and the no-focus
- X * window are reachable by traversing this list.
- X */
- XList *ActiveClientList;
- X
- X/*
- X * Pointer to the "current" client. This is usually the client whose window
- X * has the input focus, but not always. The exceptions include icons and
- X * pinned menus, where the icon or menu window may be the "current" client but
- X * where the focus really is with the no-focus window.
- X */
- X
- XClient *CurrentClient = NULL;
- X
- X/*
- X * DoingWindowState indicates whether olwm is doing window state.
- X * This is set in InitClientState() and used in MakeRoot().
- X */
- XBool DoingWindowState = False;
- X
- Xextern Atom AtomColorMapWindows;
- Xextern Atom AtomDecorDel;
- Xextern Atom AtomDecorAdd;
- Xextern Atom AtomDeleteWindow;
- Xextern Atom AtomProtocols;
- Xextern Atom AtomLeftFooter;
- Xextern Atom AtomRightFooter;
- Xextern Atom AtomShowProperties;
- Xextern Atom AtomTakeFocus;
- Xextern Atom AtomWindowBusy;
- Xextern Atom AtomWinAttr;
- Xextern Atom AtomWMState;
- Xextern Atom AtomWMName;
- Xextern Atom AtomWMIconName;
- Xextern Atom AtomWMHints;
- Xextern Atom AtomWMNormalHints;
- Xextern Atom AtomSunLedMap;
- Xextern Atom AtomSunWindowState;
- Xextern Atom AtomSunDragDropInterest;
- X
- Xextern void RecursiveRefresh();
- Xextern void PushPinChangeState();
- Xextern void FrameUpdateHeader();
- Xextern void FrameUpdateFooter();
- Xextern void IconUpdateName();
- Xextern void ColorUpdateColorMapWindows();
- Xextern void StateUpdateWinAttr();
- Xextern void StateUpdateDecorAdd();
- Xextern void StateUpdateDecorDel();
- Xextern void StateUpdateWMNormalHints();
- Xextern void StateUpdateWMHints();
- Xextern void StateUpdateWMProtocols();
- X
- X/***************************************************************************
- X* private data
- X***************************************************************************/
- X
- Xtypedef struct _ledstate {
- X int led;
- X int led_mode;
- X} LedState;
- X
- Xstatic LedState composeLedState;
- X
- Xstatic Client *lastCurrentClient = NULL;
- X
- X#define LED_MAP_LENGTH (33L)
- X
- X/***************************************************************************
- X* private functions
- X***************************************************************************/
- X
- Xstatic void clientSetBusy();
- X
- X/*
- X * setComposeLed - sets the compose led to the new mode iff different than
- X * the current mode.
- X */
- Xstatic void
- XsetComposeLed(dpy,mode)
- X Display *dpy;
- X int mode;
- X{
- X XKeyboardControl kbdValue;
- X
- X if (mode == composeLedState.led_mode)
- X return;
- X
- X composeLedState.led_mode = mode;
- X kbdValue.led = composeLedState.led;
- X kbdValue.led_mode = composeLedState.led_mode;
- X
- X XChangeKeyboardControl(dpy,KBLed|KBLedMode,&kbdValue);
- X}
- X
- X/***************************************************************************
- X* global functions
- X***************************************************************************/
- X
- X/*
- X * InitClientState - init kbd led state for client use
- X */
- XInitClientState(dpy)
- XDisplay *dpy;
- X{
- X int *ledMap;
- X int i,numLeds,led;
- X unsigned int nitems,nremain;
- X XKeyboardControl kbdvalue;
- X
- X DoingWindowState = False;
- X
- X /*
- X * Get the _SUN_LED_MAP property from the default root window
- X */
- X ledMap = GetWindowProperty(dpy,DefaultRootWindow(dpy),AtomSunLedMap,
- X 0L,LED_MAP_LENGTH,XA_INTEGER,32,&nitems,&nremain);
- X
- X if (ledMap == NULL || nitems != LED_MAP_LENGTH || nremain != 0) {
- X return;
- X }
- X numLeds = ledMap[0]; /* first entry is the number of leds */
- X
- X /*
- X * Find out which led number is marked Compose
- X */
- X for (i = 1; i <= numLeds; i++) {
- X if (ledMap[i] == XK_Multi_key) {
- X composeLedState.led = i;
- X composeLedState.led_mode = -1; /* for first time */
- X DoingWindowState = True;
- X }
- X }
- X
- X /*
- X * Turn off the compose led
- X */
- X if (DoingWindowState)
- X setComposeLed(dpy,LedModeOff);
- X
- X XFree((char *)ledMap);
- X}
- X
- X/*
- X * ClientDefaultWindowState - applies the default window state
- X */
- XClientDefaultWindowState(dpy)
- X Display *dpy;
- X{
- X setComposeLed(dpy,LedModeOff);
- X}
- X
- X/*
- X * ClientSetWindowState - applies the client's window state
- X */
- XClientSetWindowState(cli)
- X Client *cli;
- X{
- X if (!DoingWindowState)
- X return;
- X
- X /*
- X * If the client has specified the window state then interpret it.
- X */
- X if (cli->windowState) {
- X if (cli->windowState->flags & WSSemanticState) {
- X if (cli->windowState->state & WSSemanticCompose)
- X setComposeLed(cli->dpy,LedModeOn);
- X else
- X setComposeLed(cli->dpy,LedModeOff);
- X }
- X /*
- X * Else just apply the default state
- X */
- X } else {
- X ClientDefaultWindowState(cli->dpy);
- X }
- X}
- X
- X/*
- X * ClientGetWindowState - gets the _SUN_WINDOW_STATE property and if the
- X * client has the focus then apply that new state.
- X */
- XClientGetWindowState(cli)
- X Client *cli;
- X{
- X Window pane;
- X OLWindowState winState;
- X
- X if (!DoingWindowState)
- X return;
- X
- X if (cli->framewin == NULL)
- X return;
- X
- X pane = PANEWINOFCLIENT(cli);
- X
- X if (!PropGetOLWindowState(cli->dpy,pane,&winState))
- X return;
- X
- X if (cli->windowState == NULL)
- X cli->windowState = MemNew(OLWindowState);
- X
- X *cli->windowState = winState;
- X
- X if (cli->isFocus)
- X ClientSetWindowState(cli);
- X}
- X
- X/*
- X * ClientUpdateWindowState - handle PropertyNotify on _SUN_WINDOW_STATE
- X */
- Xvoid
- XClientUpdateWindowState(cli,event)
- X Client *cli;
- X XPropertyEvent *event;
- X{
- X if (!DoingWindowState)
- X return;
- X
- X if (event->state == PropertyNewValue) {
- X ClientGetWindowState(cli);
- X } else {
- X if (cli->windowState)
- X MemFree((char *)cli->windowState);
- X cli->windowState = (OLWindowState *)NULL;
- X ClientDefaultWindowState(cli->dpy);
- X }
- X}
- X
- X/* ClientSendProtocol - send a protocol message to a client
- X */
- Xvoid *
- XClientSendProtocol(cli,proto,evtime)
- XClient *cli;
- XAtom proto;
- XTime evtime;
- X{
- X XEvent clientEvent;
- X
- X clientEvent.xclient.type = ClientMessage;
- X clientEvent.xclient.message_type = AtomProtocols;
- X clientEvent.xclient.format = 32;
- X clientEvent.xclient.display = cli->dpy;
- X clientEvent.xclient.window = ClientPane(cli);
- X clientEvent.xclient.data.l[0] = proto;
- X clientEvent.xclient.data.l[1] = evtime;
- X
- X XSendEvent(cli->dpy, clientEvent.xclient.window, False,
- X NoEventMask, &clientEvent);
- X return NULL;
- X}
- X
- X/* ClientShowProps - send a ClientMessage of type WM_SHOW_PROPERTIES
- X */
- Xvoid
- XClientShowProps(cli)
- XClient *cli;
- X{
- X XEvent clientEvent;
- X
- X clientEvent.xclient.type = ClientMessage;
- X clientEvent.xclient.message_type = AtomShowProperties;
- X clientEvent.xclient.format = 32;
- X clientEvent.xclient.display = cli->dpy;
- X clientEvent.xclient.window = PANEWINOFCLIENT(cli);
- X
- X XSendEvent(cli->dpy, clientEvent.xclient.window, False,
- X NoEventMask, &clientEvent);
- X}
- X
- X/* ClientKill - a client must be killed. If it can handle the DELETE_WINDOW
- X * protocol, use it; otherwise, if we are forcing the client to go
- X * away, kill it.
- X */
- Xvoid *
- XClientKill(cli,pforce)
- XClient *cli;
- XBool pforce;
- X{
- X if (cli->framewin == NULL)
- X return NULL;
- X
- X if (cli->protocols & DELETE_WINDOW) {
- X ClientSendProtocol(cli,AtomDeleteWindow,LastEventTime);
- X } else {
- X if (pforce && ! cli->flags & CLOlwmOwned)
- X XKillClient(cli->dpy,ClientPane(cli));
- X else
- X if (GRV.Beep == BeepAlways)
- X XBell(cli->dpy, 100);
- X }
- X return NULL;
- X}
- X
- X/* ClientShutdown - a client must be shut down. Force the client
- X * the go away without any further user interaction.
- X */
- Xvoid *
- XClientShutdown(cli,junk)
- XClient *cli;
- Xvoid *junk;
- X{
- X /* Only kill non-olwm owned clients */
- X if (! cli->flags & CLOlwmOwned)
- X XKillClient(cli->dpy,ClientPane(cli));
- X return NULL;
- X}
- X
- X
- X/* UnparentClient - while exiting OLWM: unmap all icons that are on the
- X * screen. Reparent all windows back to the root, suitably offset
- X * according to their window-gravities. Also remap all non-withdrawn
- X * windows, and remove all Withdrawn windows from the save-set (so
- X * they don't get remapped. REMIND: We have to do this because
- X * Withdrawn windows are still left reparented inside the frame; this
- X * shouldn't be the case.
- X */
- X/*ARGSUSED*/
- Xvoid *
- XUnparentClient(cli,junk)
- XClient *cli;
- Xvoid *junk;
- X{
- X WinPaneFrame *frameInfo;
- X WinPane *paneInfo;
- X Window pane;
- X
- X /* if no framewin then it's probably a root window */
- X if (cli->framewin == NULL)
- X return NULL;
- X
- X if (cli->wmState == IconicState)
- X {
- X IconHide(cli, cli->iconwin);
- X }
- X
- X frameInfo = cli->framewin;
- X paneInfo = (WinPane*)(frameInfo->fcore.panewin);
- X pane = paneInfo->core.self;
- X FrameUnparentPane(cli, frameInfo, paneInfo);
- X
- X if (cli->wmState == DontCareState)
- X {
- X if (!(cli->flags & CLOlwmOwned))
- X XChangeSaveSet(cli->dpy, pane, SetModeDelete);
- X }
- X else
- X {
- X XMapWindow(cli->dpy,pane);
- X }
- X
- X return NULL;
- X}
- X
- X/*
- X * addClient -- add this client structure to the list of active clients
- X */
- Xstatic void
- XaddClient(cli)
- XClient *cli;
- X{
- X List *l = ActiveClientList;
- X Client *tc;
- X
- X /* First look to see if window is already listed. */
- X for(tc = ListEnum(&l); tc != NULL; tc = ListEnum(&l))
- X {
- X if (tc == cli)
- X return;
- X }
- X
- X /* Wasn't present, add to list. */
- X ActiveClientList = ListCons(cli, ActiveClientList);
- X}
- X
- X/*
- X * removeClient -- remove this client structure from the list of active
- X * clients.
- X */
- Xstatic void
- XremoveClient(cli)
- XClient *cli;
- X{
- X List **l;
- X
- X for (l = &ActiveClientList ; *l != NULL; l = &((*l)->next))
- X {
- X if ((*l)->value == cli)
- X {
- X ListDestroyCell(l);
- X return;
- X }
- X }
- X}
- X
- X/*
- X * DestroyClient -- destroy all resources associated with this client, and
- X * remove external references to this client. If this is the current client,
- X * and we are in click-to-type, set the focus to the topmost client *after*
- X * having destroyed this client.
- X */
- Xvoid
- XDestroyClient(cli)
- XClient *cli;
- X{
- X Bool setfocus = False;
- X Display *dpy = cli->dpy;
- X ScreenInfo *scrInfo = cli->scrInfo;
- X List *l;
- X Client *tcli;
- X
- X UnTrackSubwindows(cli, True);
- X if (IsSelected(cli))
- X RemoveSelection(cli);
- X
- X if (cli == CurrentClient) {
- X ClientSetCurrent(NoFocusWinInfo->core.client);
- X /* purge the old client from lastCurrentClient */
- X /* REMIND need a better interface */
- X lastCurrentClient = NULL;
- X
- X setfocus = !GRV.FocusFollowsMouse;
- X }
- X
- X removeClient(cli);
- X
- X /*
- X * Run through the remaining clients and remove any references to this
- X * client from their warp-back records.
- X */
- X l = ActiveClientList;
- X while (tcli = ListEnum(&l)) {
- X if (tcli->framewin != NULL &&
- X tcli->warpInfo.warpBackClient == cli)
- X {
- X tcli->framewin->pointerIsWarped = False;
- X }
- X }
- X
- X /* destroy the window resources associated with the client */
- X WinCallDestroy(cli);
- X
- X GroupRemove(cli->groupid, cli);
- X
- X /* free up the client structure resources */
- X if (cli->wmDecors)
- X MemFree(cli->wmDecors);
- X if (cli->normHints)
- X MemFree(cli->normHints);
- X if (cli->wmHints)
- X MemFree(cli->wmHints);
- X if (cli->wmInstance)
- X MemFree(cli->wmInstance);
- X if (cli->wmClass)
- X MemFree(cli->wmClass);
- X if (cli->windowState)
- X MemFree(cli->windowState);
- X
- X /* REMIND what's to be done with followers here? */
- X
- X#ifdef DEBUG
- X memset(cli, 0, sizeof(Client));
- X#endif /* DEBUG */
- X
- X MemFree(cli);
- X
- X if (setfocus)
- X ClientFocusTopmost(dpy, scrInfo, CurrentTime);
- X}
- X
- X/*
- X * ClientConfigure - a configure request event has been received on the
- X * pane. Configure the windows accordingly.
- X */
- Xvoid
- XClientConfigure(cli,win,pxcre)
- XClient *cli;
- XWinGeneric *win;
- XXConfigureRequestEvent *pxcre;
- X{
- X XWindowChanges winChange;
- X
- X if ((cli == NULL) || (win == NULL))
- X {
- X /* We don't know about this window, or it's withdrawn
- X * convert the request into an XConfigureWindow
- X * call. We do not look at the hints to see if
- X * the resize is in the proper increments, but since
- X * the app is asking for the reconfigure this seems
- X * right.
- X */
- X winChange.x = pxcre->x;
- X winChange.y = pxcre->y;
- X winChange.width = pxcre->width;
- X winChange.height = pxcre->height;
- X winChange.border_width = pxcre->border_width;
- X winChange.stack_mode = pxcre->detail;
- X winChange.sibling = pxcre->above;
- X
- X XConfigureWindow(pxcre->display,
- X pxcre->window,
- X /* lint will warn: this is a long, not int */
- X (int) pxcre->value_mask,
- X &winChange );
- X }
- X else /* cli->wmState == NormalState or IconicState */
- X {
- X WinCallConfig(cli->dpy,win,pxcre);
- X }
- X}
- X
- X/*
- X * ClientSetWMState -- set the contents of the WM_STATE property,
- X * given the information in the WinInfo struct.
- X */
- Xvoid
- XClientSetWMState( cli )
- X Client *cli;
- X{
- X WinIconFrame *iconWinInfo = cli->iconwin;
- X Window pane = PANEWINOFCLIENT(cli);
- X Window icon;
- X
- X if (cli->framewin->core.self ==
- X cli->scrInfo->vdm->client->framewin->core.self)
- X return;
- X if (iconWinInfo) {
- X if ( iconWinInfo->fcore.panewin )
- X icon = iconWinInfo->fcore.panewin->core.self;
- X else
- X icon = iconWinInfo->core.self;
- X } else {
- X icon = None;
- X }
- X
- X PropSetWMState(cli->dpy,pane,cli->wmState,icon);
- X}
- X
- X
- X/* ===== Drag-and-Drop Interest Property ================================== */
- X
- X
- X#define DRAGDROP_VERSION 0
- X#define INTEREST_RECT 0
- X#define INTEREST_WINDOW 1
- X#define SITE_DEFAULT (1<<2)
- X#define SITE_FORWARD (1<<3)
- X
- X/*
- X * Get the next word from the `data' array, indexed by `cur'. If this causes
- X * us to go beyond `nitems', return silently.
- X */
- X#define NEXTWORD(dest) do { \
- X if (++cur >= nitems) { \
- X XFree((char *)data); \
- X return; \
- X } \
- X (dest) = data[cur]; \
- X } while (0)
- X
- X#define INCR(by) do { \
- X cur += (by); \
- X if (cur >= nitems) \
- X return; \
- X } while (0)
- X
- X
- Xstatic struct {
- X unsigned long
- X version,
- X nsites,
- X wid,
- X sid,
- X flags,
- X areatype,
- X nelts,
- X rx, ry, rw, rh;
- X} forwardingInterest = {
- X 0, /* version */
- X 1, /* nsites */
- X 0, /* window id -- to be filled in */
- X 0, /* site id -- to be filled in */
- X 0, /* flags -- to be filled in */
- X INTEREST_RECT, /* areatype */
- X 1, /* number of rects */
- X 0, 0, 0, 0 /* rectangle -- to be filled in */
- X};
- X#define FI_LENGTH \
- X (sizeof(forwardingInterest)/sizeof(unsigned long))
- X
- X
- X/*
- X * ClientProcessDragDropInterest - read the clients drag'n'drop interest
- X * property, and put an interest containing the default site onto the frame
- X * window and the icon window. If we encounter an error reading the property,
- X * do nothing and return silently.
- X */
- Xvoid
- XClientProcessDragDropInterest(cli, state)
- X Client *cli;
- X int state; /* PropertyNewValue or PropertyDelete */
- X{
- X unsigned long *data;
- X int nitems, remain, nsites, i, areatype, nelts;
- X int cur = 0;
- X Window wid;
- X unsigned long sid, flags;
- X
- X if (state == PropertyDelete) {
- X DeleteProperty(cli->dpy, cli->framewin,
- X AtomSunDragDropInterest);
- X if (cli->iconwin != NULL)
- X DeleteProperty(cli->dpy, cli->iconwin,
- X AtomSunDragDropInterest);
- X return;
- X }
- X
- X data = GetWindowProperty(cli->dpy, PANEWINOFCLIENT(cli),
- X AtomSunDragDropInterest, 0L, 1000000L, AtomSunDragDropInterest,
- X 32, &nitems, &remain);
- X
- X if (data == NULL)
- X return;
- X
- X if (data[cur] != DRAGDROP_VERSION) {
- X XFree((char *)data);
- X return;
- X }
- X
- X NEXTWORD(nsites);
- X for (i=0; i<nsites; ++i) {
- X NEXTWORD(wid);
- X NEXTWORD(sid);
- X NEXTWORD(flags);
- X NEXTWORD(areatype);
- X switch (areatype) {
- X case INTEREST_RECT:
- X NEXTWORD(nelts);
- X INCR(4*nelts);
- X break;
- X case INTEREST_WINDOW:
- X NEXTWORD(nelts);
- X INCR(nelts);
- X break;
- X default:
- X /* unknown area type; just return */
- X XFree((char *)data);
- X return;
- X }
- X if (flags & SITE_DEFAULT) {
- X forwardingInterest.wid = wid;
- X forwardingInterest.sid = sid;
- X forwardingInterest.flags = flags & ~SITE_DEFAULT;
- X forwardingInterest.flags |= SITE_FORWARD;
- X
- X /* write the property on the frame */
- X
- X forwardingInterest.rx = 0;
- X forwardingInterest.ry = 0;
- X forwardingInterest.rw = cli->framewin->core.width;
- X forwardingInterest.rh = cli->framewin->core.height;
- X ChangeProperty(cli->dpy, cli->framewin,
- X AtomSunDragDropInterest, AtomSunDragDropInterest,
- X 32, PropModeReplace,
- X (unsigned char *) &forwardingInterest, FI_LENGTH);
- X
- X /* write the property on the icon */
- X if (cli->iconwin != NULL) {
- X forwardingInterest.rx = 0;
- X forwardingInterest.ry = 0;
- X forwardingInterest.rw = cli->iconwin->core.width;
- X forwardingInterest.rh = cli->iconwin->core.height;
- X ChangeProperty(cli->dpy, cli->iconwin,
- X AtomSunDragDropInterest, AtomSunDragDropInterest,
- X 32, PropModeReplace,
- X (unsigned char *) &forwardingInterest, FI_LENGTH);
- X }
- X break;
- X }
- X }
- X XFree((char *)data);
- X}
- X
- X/*
- X * ClientUpdateDragDropInterest - handle PropertyNotify on DragDropInterest
- X */
- Xvoid
- XClientUpdateDragDropInterest(cli,event)
- X Client *cli;
- X XPropertyEvent *event;
- X{
- X ClientProcessDragDropInterest(cli,event->state);
- X}
- X
- X
- X/* ClientCreate -- allocate and initialise a client structure
- X */
- XClient *
- XClientCreate(dpy,screen)
- X Display *dpy;
- X int screen;
- X{
- X Client *cli = MemNew(Client);
- X
- X cli->wmState = DontCareState;
- X cli->dpy = dpy;
- X cli->screen = screen;
- X cli->scrInfo = GetScrInfoOfScreen(screen);
- X /* all other fields set to zero by allocation function */
- X addClient(cli);
- X return cli;
- X}
- X
- X/* ClientPane - return the pane window of a client
- X */
- XWindow
- XClientPane(cli)
- XClient *cli;
- X{
- X WinPaneFrame *wf;
- X WinPane *wp;
- X
- X if ((wf = cli->framewin) == NULL)
- X return NULL;
- X if ((wp = (WinPane *)(wf->fcore.panewin)) == NULL)
- X return NULL;
- X return wp->core.self;
- X}
- X
- X
- X/*
- X * ClientOpenCloseToggle
- X * Perform the appropriate open/close action.
- X */
- Xvoid
- XClientOpenCloseToggle(cli)
- XClient *cli;
- X{
- X /*
- X * If we are a pop-up (have a pushpin) or are transient,
- X * then dismiss.
- X */
- X if ((cli->wmDecors->flags & WMDecorationPushPin)
- X || cli->transientFor != 0) {
- X ClientKill(cli,False);
- X
- X /* else switch the state from/to normal/iconic */
- X } else {
- X switch (cli->wmState) {
- X case NormalState:
- X StateNormIcon(cli);
- X break;
- X case IconicState:
- X StateIconNorm(cli);
- X break;
- X default:
- X break;
- X }
- X }
- X}
- X
- X/*
- X * ClientStickUnstickToggle
- X * Perform the appropriate Stick/Unstick action.
- X */
- Xvoid
- XClientStickUnstickToggle(cli)
- XClient *cli;
- X{
- X MakeSticky(cli, !cli->sticky);
- X if (cli->groupmask == GROUP_LEADER)
- X GroupApply(cli->groupid, MakeSticky, cli->sticky, GROUP_DEPENDENT);
- X}
- X
- X/*
- X * ClientFullRestoreSizeToggle
- X * Call both frame and icon full/restore toggle functions.
- X */
- Xvoid
- XClientFullRestoreSizeToggle(cli)
- XClient *cli;
- X{
- X if (cli->wmDecors->flags & WMDecorationResizeable) {
- X (WinFunc(cli->framewin,fcore.fullrestoreToggle))(cli);
- X (WinFunc(cli->iconwin,fcore.fullrestoreToggle))(cli);
- X }
- X}
- X
- X/*
- X * ClientMove
- X * Moves the client to a new x,y position.
- X */
- Xvoid
- XClientMove(cli,trigger)
- X Client *cli;
- X XEvent *trigger;
- X{
- X UserMoveWindows(cli, trigger);
- X}
- X
- X/*
- X * ClientResize
- X * Resizes the client to a new w,h size.
- X */
- Xvoid
- XClientResize(cli,trigger,which,callback,cbarg)
- X Client *cli;
- X XEvent *trigger;
- X WhichResize which;
- X void (*callback)();
- X void *cbarg;
- X{
- X if (cli->wmDecors->flags & WMDecorationResizeable)
- X UserResizeWin(cli, trigger, which, callback, cbarg);
- X}
- X
- X
- X/*
- X * ClientRaiseTransients
- X *
- X * Raise any transient windows associated with this client. Return the
- X * client for the bottommost transient window. This is useful so that the
- X * parent window can be restacked just below the bottommost transient. If
- X * there are no transient windows, returns NULL.
- X *
- X * REMIND raises all transient windows in the order they are encountered in
- X * the active client list, and returns the first one found. Ideally, this
- X * should preserve the stacking order of the transients.
- X */
- XClient *
- XClientRaiseTransients(cli)
- X Client *cli;
- X{
- X List *l = ActiveClientList;
- X Client *tc;
- X Client *first = NULL;
- X
- X if (!GRV.KeepTransientsAbove)
- X return NULL;
- X
- X while (tc = ListEnum(&l)) {
- X if (tc->transientFor == PANEWINOFCLIENT(cli)) {
- X RaiseWindow(tc->framewin);
- X if (first == NULL)
- X first = tc;
- X }
- X }
- X return first;
- X}
- X
- X
- X/*
- X * ClientLowerTransients
- X *
- X * Restack any transient windows associated with this client to be just above
- X * this client's frame.
- X *
- X * REMIND this lowers all transient windows in the order they are encountered
- X * in the active client list. Ideally, this should preserve the stacking
- X * order of the transients.
- X */
- Xvoid
- XClientLowerTransients(cli)
- X Client *cli;
- X{
- X List *l = ActiveClientList;
- X Client *tc;
- X XWindowChanges xwc;
- X
- X if (!GRV.KeepTransientsAbove)
- X return;
- X
- X xwc.stack_mode = Above;
- X xwc.sibling = cli->framewin->core.self;
- X while (tc = ListEnum(&l)) {
- X if (tc->transientFor == PANEWINOFCLIENT(cli)) {
- X ConfigureWindow(tc->dpy, tc->framewin,
- X CWSibling | CWStackMode, &xwc);
- X }
- X }
- X}
- X
- X
- X/*
- X * ClientFront
- X *
- X * Moves the appropriate client window to the front of the window hierarchy.
- X * If this window has any transient windows, move them in front first.
- X */
- Xvoid
- XClientFront(cli)
- XClient *cli;
- X{
- X Client *firsttransient;
- X XWindowChanges xwc;
- X
- X switch (cli->wmState) {
- X case NormalState:
- X firsttransient = ClientRaiseTransients(cli);
- X if (firsttransient != NULL) {
- X xwc.sibling = firsttransient->framewin->core.self;
- X xwc.stack_mode = Below;
- X ConfigureWindow(cli->dpy, cli->framewin,
- X CWSibling | CWStackMode, &xwc);
- X } else {
- X RaiseWindow(cli->framewin);
- X }
- X break;
- X case IconicState:
- X RaiseWindow(cli->iconwin);
- X break;
- X default:
- X break;
- X }
- X}
- X
- X
- X/*
- X * ClientBack
- X *
- X * Moves the appropriate client window to the back of the window hierarchy.
- X * If this is a transient window, move its parent window to the back first,
- X * and then move this window just in front of it.
- X *
- X * REMIND this isn't optimal behavior for transient windows, but it does
- X * ensure that transient windows always remain in front of their parents.
- X */
- Xvoid
- XClientBack(cli)
- XClient *cli;
- X{
- X WinGeneric *owner;
- X Window ownerwin;
- X XWindowChanges xwc;
- X
- X switch (cli->wmState) {
- X case NormalState:
- X if (cli->transientFor != 0 && GRV.KeepTransientsAbove) {
- X owner = WIGetInfo(cli->transientFor);
- X if (owner == NULL ||
- X owner->core.kind != WIN_PANE) {
- X LowerWindow(cli->framewin);
- X } else {
- X ownerwin = owner->core.client->framewin->core.self;
- X LowerWindow(owner->core.client->framewin);
- X xwc.sibling = ownerwin;
- X xwc.stack_mode = Above;
- X ConfigureWindow(cli->dpy, cli->framewin,
- X CWSibling | CWStackMode, &xwc);
- X }
- X } else {
- X LowerWindow(cli->framewin);
- X }
- X break;
- X case IconicState:
- X LowerWindow(cli->iconwin);
- X break;
- X default:
- X break;
- X }
- X}
- X
- X
- X/*
- X * ClientToggleStacking
- X *
- X * Moves the appropriate client window to the front of the window hierarchy if
- X * it is obscured, otherwise move it to the back of the hierarchy if it
- X * obscures any other window. REMIND: doesn't deal with transient windows at
- X * all.
- X */
- Xvoid
- XClientToggleStacking(cli)
- XClient *cli;
- X{
- X XWindowChanges xwc;
- X WinGeneric *win;
- X
- X switch (cli->wmState) {
- X case NormalState:
- X win = (WinGeneric *) cli->framewin;
- X break;
- X case IconicState:
- X win = (WinGeneric *) cli->iconwin;
- X break;
- X }
- X
- X xwc.stack_mode = Opposite;
- X ConfigureWindow(cli->dpy, win, CWStackMode, &xwc);
- X}
- X
- X
- X/*
- X * ClientRefresh
- X * Refresh the window. We do this by creating a window on top
- X * of the window to refresh and then immediately destroy it.
- X * Refresh either icon or frame windows.
- X */
- Xvoid
- XClientRefresh(cli)
- XClient *cli;
- X{
- X Window w,cliwin;
- X int cliwidth,cliheight;
- X XSetWindowAttributes xswa;
- X
- X /* Chose which window to refresh */
- X switch (cli->wmState) {
- X case NormalState:
- X cliwin = cli->framewin->core.self;
- X cliwidth = cli->framewin->core.width;
- X cliheight = cli->framewin->core.height;
- X break;
- X case IconicState:
- X cliwin = cli->iconwin->core.self;
- X cliwidth = cli->iconwin->core.width;
- X cliheight = cli->iconwin->core.height;
- X break;
- X default:
- X return;
- X /*NOTREACHED*/
- X break;
- X }
- X
- X /* if we should refresh all windows */
- X if (GRV.RefreshRecursively) {
- X RecursiveRefresh(cli->dpy,cliwin);
- X
- X /* or just the top/main window */
- X } else {
- X w = XCreateWindow(cli->dpy,
- X cliwin, 0, 0, cliwidth, cliheight, 0,
- X CopyFromParent, InputOutput, CopyFromParent,
- X 0, &xswa);
- X XMapRaised(cli->dpy,w);
- X XDestroyWindow(cli->dpy,w);
- X }
- X}
- X
- X/*
- X * ClientFlashOwner
- X * Find group leader frame, bring it to the top and then
- X * flash its title bar.
- X *
- X * REMIND: make sure transient windows get treated properly
- X * before or after (which? not sure) the leader is raised.
- X */
- Xvoid
- XClientFlashOwner(cli)
- XClient *cli;
- X{
- X Client *cliLead = GroupLeader(cli->groupid);
- X if (cliLead && cliLead->framewin) {
- X RaiseWindow(cliLead->framewin);
- X WinCallDraw((WinGeneric *)cliLead->framewin);
- X FrameFlashTitleBar(cliLead->framewin);
- X }
- X}
- X
- X/*
- X * Toggle the pushpin of this client's window. Returns False if this client's
- X * window has no pin, otherwise, returns True.
- X */
- XBool
- XClientTogglePin(cli)
- X Client *cli;
- X{
- X WinPushPin *pin;
- X
- X if (cli->framewin == NULL || !ClientIsPinnable(cli))
- X return False;
- X
- X pin = (WinPushPin *)cli->framewin->winDeco;
- X PushPinTogglePinState(cli->dpy,pin,True);
- X return True;
- X}
- X
- X
- X/* ClientInBox -- given a bounding box, apply a function to all clients
- X * which fall inside the rectangle
- X */
- Xvoid *
- XClientInBox(cli, close)
- XClient *cli;
- XClientInBoxClosure *close;
- X{
- X int x, y, w, h;
- X
- X if (cli->screen != close->screen)
- X return NULL;
- X
- X if (cli->framewin == NULL)
- X return NULL;
- X
- X if (cli->wmState == IconicState)
- X {
- X x = cli->iconwin->core.x;
- X y = cli->iconwin->core.y;
- X w = cli->iconwin->core.width;
- X h = cli->iconwin->core.height;
- X }
- X else
- X {
- X x = cli->framewin->core.x;
- X y = cli->framewin->core.y;
- X w = cli->framewin->core.width;
- X h = cli->framewin->core.height;
- X }
- X
- X if ((x >= close->bx) &&
- X (y >= close->by) &&
- X ((x + w) <= (close->bx + close->bw)) &&
- X ((y + h) <= (close->by + close->bh)))
- X (close->func)(cli, close->timestamp);
- X
- X return NULL;
- X}
- X
- X/*
- X * ClientSetBusy -- the busy state has (possibly) been changed for a client.
- X * if the client is going from normal to busy:
- X * mark the client as busy
- X * put up a busy window
- X * if the client is going from busy to normal:
- X * mark the client as unbusy
- X * take down a busy window (if it exists)
- X */
- Xvoid
- XClientUpdateBusy(cli,event)
- X Client *cli;
- X XPropertyEvent *event;
- X{
- X int *newBusyPtr;
- X int newBusy;
- X unsigned long nItems, remain;
- X
- X if (event->state == PropertyNewValue) {
- X newBusyPtr = GetWindowProperty(cli->dpy, PANEWINOFCLIENT(cli),
- X AtomWindowBusy, 0L, LONG_LENGTH(*newBusyPtr),
- X XA_INTEGER, 32, &nItems, &remain);
- X
- X if (newBusyPtr == NULL) {
- X /* property not found or has the wrong type */
- X newBusy = 0;
- X } else {
- X if (nItems != LONG_LENGTH(newBusy) || remain != 0) {
- X /* got a property, but it is invalid */
- X newBusy = 0;
- X } else {
- X /* valid property */
- X newBusy = *newBusyPtr;
- X }
- X XFree((char *)newBusyPtr);
- X }
- X } else {
- X /* property was deleted */
- X newBusy = 0;
- X }
- X
- X /*
- X * Losing busy
- X */
- X if (cli->isBusy && (newBusy == 0)) {
- X cli->isBusy = False;
- X if (cli->isFocus)
- X ClientSetFocus(cli,True,event->time);
- X FrameSetBusy(cli->framewin, False);
- X }
- X /*
- X * Else Gaining busy
- X */
- X else if (!cli->isBusy && (newBusy == 1)) {
- X cli->isBusy = True;
- X FrameSetBusy(cli->framewin, True);
- X if (cli->isFocus)
- X ClientSetFocus(cli,True,event->time);
- X }
- X}
- X
- X
- X/*
- X * REMIND this function should be removed when menu/menuinfos
- X * are reorged.
- X */
- Xvoid
- XDestroyPinnedMenuClients()
- X{
- X List *l = ActiveClientList;
- X Client *cli;
- X
- X
- X for (cli = ListEnum(&l); cli != NULL; cli = ListEnum(&l)) {
- X if (cli->framewin && cli->framewin->fcore.panewin &&
- X cli->framewin->fcore.panewin->core.kind == WIN_PINMENU) {
- X#ifdef DEBUG
- X printf("DestroyPinnedMenuClients: destroyed %x\n",cli);
- X#endif
- X DestroyClient(cli);
- X }
- X }
- X}
- X
- X
- X/* ===== focus stuff ====================================================== */
- X
- X
- X/*
- X * Focus Change Inhibition.
- X *
- X * If focus changing is inhibited, information about focus changing is stored
- X * in the FocusInhibitRecord instead of being used to set the focus. If
- X * several focus changes occur while focus changing is inhibited, only
- X * information for the latest change is stored. When focus changing becomes
- X * uninhibited, the information is used to set the focus for real. This
- X * prevents unnecessary focus changing. REMIND: focus inhibition doesn't
- X * occur when the focus is set to the NoFocus window. This isn't too bad, as
- X * no highlighting occurs when this happens.
- X */
- X
- Xstatic struct FocusInhibitRecord {
- X Bool inhibited;
- X Client *cli;
- X Bool sendTF;
- X Time evtime;
- X} fir;
- X
- X
- X/*
- X * ClientInhibitFocus -- inhibit or uninhibit focus changing.
- X */
- Xvoid
- XClientInhibitFocus(inhibit)
- X Bool inhibit;
- X{
- X if (inhibit) {
- X fir.inhibited = True;
- X fir.cli = NULL;
- X } else {
- X fir.inhibited = False;
- X if (fir.cli != NULL)
- X ClientSetFocus(fir.cli, fir.sendTF, fir.evtime);
- X fir.cli = NULL;
- X }
- X}
- X
- X
- X/*
- X * ClientSetFocus -- possibly set the focus to this client. If focus changing
- X * is inhibited, store information in the inhibit record. Otherwise, set the
- X * focus normally. If the client is GloballyActive, we only send TakeFocus
- X * messages if sendTF is true. If the client has a different focus mode
- X * sendTF is ignored. If the client is a NoInput client, set the focus to the
- X * frame itself. REMIND: this works, if a little bizarre. The frame doesn't
- X * select for keystrokes, so they fall to the root. The root event handler
- X * ends up beeping, which is OK.
- X */
- Xvoid
- XClientSetFocus(cli,sendTF,evtime)
- XClient *cli;
- XBool sendTF;
- XTime evtime;
- X{
- X if (fir.inhibited) {
- X fir.cli = cli;
- X fir.sendTF = sendTF;
- X fir.evtime = evtime;
- X return;
- X }
- X
- X if (cli->wmState == IconicState) {
- X if (cli->iconwin != NULL)
- X XSetInputFocus(cli->dpy, cli->iconwin->core.self,
- X RevertToParent, evtime);
- X } else {
- X switch (cli->focusMode)
- X {
- X case NoInput:
- X XSetInputFocus(cli->dpy, cli->framewin->core.self,
- X RevertToParent, evtime);
- X break;
- X
- X case Passive:
- X case LocallyActive:
- X XSetInputFocus(cli->dpy, PANEWINOFCLIENT(cli),
- X RevertToParent, evtime);
- X break;
- X
- X case GloballyActive:
- X if (sendTF)
- X {
- X ClientSendProtocol(cli, AtomTakeFocus, evtime);
- X }
- X break;
- X }
- X }
- X}
- X
- X
- X/*
- X * Current Client.
- X *
- X * The current client is used by the mouseless functions. These functions
- X * maintain the current and previously-current client. If cli is already the
- X * current client, don't do anything. This is necessary because this may be
- X * called when a client is activated explicitly (from ClientActivate) or
- X * implicitly (when a globally active client takes the focus). Therefore, if
- X * ClientActivate activates a globally active client, this function will be
- X * called twice.
- X *
- X * Eventually, this may change to be a "ring-buffer" history of clients.
- X *
- X * REMIND: the notion of the current client may be a vestige from the time
- X * when some objects (like icons and pinned menus) didn't take the focus.
- X * Activating one of these items would set the focus to the NoFocus window,
- X * but set the current client to that particular client. Thus, having the
- X * focus was not the same as being the current client. This distinction may
- X * no longer be true, in which case it is sufficient to keep track of the
- X * client that has the focus, without the separate notion of a current client.
- X * One possible problem may occur with buggy Globally Active clients that
- X * don't take the focus when requested. If we rely on the focus to keep track
- X * of the current client, we may get "stuck" if the next client fails to take
- X * the focus when requested.
- X */
- Xvoid
- XClientSetCurrent(cli)
- X Client *cli;
- X{
- X if (cli != CurrentClient) {
- X lastCurrentClient = CurrentClient;
- X CurrentClient = cli;
- X }
- X}
- X
- X
- XClient *
- XClientGetLastCurrent()
- X{
- X return lastCurrentClient;
- X}
- X
- X
- X/*
- X * Client Activation.
- X *
- X * Activate the named client. The difference between this and ClientSetFocus
- X * is that this function selects and raises the client's window in addition to
- X * setting the focus. Further, this function works on iconic clients as well
- X * as open ones. This function sets the current client explicitly. We would
- X * rely on the resulting focus change to set the current client, except that
- X * a globally active client may decline the focus when it is asked to take it.
- X *
- X * REMIND this shouldn't have to deal with selections at all. However,
- X * icons and headerless windows currently have no way to indicate that they
- X * have the focus. Therefore, select them.
- X */
- Xvoid
- XClientActivate(dpy, cli, time)
- X Display *dpy;
- X Client *cli;
- X Time time;
- X{
- X /*
- X * If the current client is selected, assume it was selected because it
- X * was made the active client, and deselect it. (See REMIND above.)
- X */
- X if (CurrentClient != NULL && CurrentClient->isSelected)
- X ClearSelections(dpy);
- X
- X /*
- X * If we are being asked to activate a NULL client, or a client without a
- X * frame (i.e. a root client), activate the NoFocus client.
- X */
- X if (cli == NULL) {
- X NoFocusTakeFocus(dpy, time, NULL);
- X } else if (cli->framewin == NULL) {
- X NoFocusTakeFocus(dpy, time, cli->scrInfo);
- X } else {
- X ClientSetFocus(cli, True, time);
- X
- X /*
- X * If the client is iconic or has no header, select it to show that it
- X * is the active client. (See REMIND above.)
- X */
- X if (cli->wmState == IconicState ||
- X !(cli->wmDecors->flags & WMDecorationHeader)) {
- X ClearSelections(dpy);
- X AddSelection(cli, time);
- X }
- X
- X if (GRV.RaiseOnActivate)
- X ClientFront(cli);
- X
- X ClientSetCurrent(cli);
- X }
- X}
- X
- X
- X/*
- X * Set the focus to the topmost window on the given screen.
- X */
- Xvoid
- XClientFocusTopmost(dpy, scrinfo, time)
- X Display *dpy;
- X ScreenInfo *scrinfo;
- X Time time;
- X{
- X Window wjunk;
- X Window *children;
- X unsigned int nchildren;
- X int i;
- X Client *topframeclient = NULL;
- X Client *topiconclient = NULL;
- X WinGeneric *win;
- X
- X if (0 == XQueryTree(dpy, scrinfo->rootid, &wjunk, &wjunk,
- X &children, &nchildren))
- X {
- X return;
- X }
- X
- X /*
- X * QueryTree returns children on bottom-to-top order, so search backward,
- X * looking for the topmost frame and icon.
- X */
- X for (i = nchildren-1; i >= 0; --i) {
- X win = WIGetInfo(children[i]);
- X if (win != NULL) {
- X if (win->core.kind == WIN_FRAME &&
- X win->core.client->wmState == NormalState &&
- X topframeclient == NULL)
- X {
- X topframeclient = win->core.client;
- X }
- X
- X if (win->core.kind == WIN_ICON &&
- X win->core.client->wmState == IconicState &&
- X topiconclient == NULL)
- X {
- X topiconclient = win->core.client;
- X }
- X
- X if (topframeclient != NULL && topiconclient != NULL)
- X break;
- X }
- X }
- X
- X if (topframeclient != NULL)
- X ClientSetFocus(topframeclient, True, time);
- X else if (topiconclient != NULL)
- X ClientSetFocus(topiconclient, True, time);
- X else
- X NoFocusTakeFocus(dpy, time, scrinfo);
- X
- X XFree((char *) children);
- X}
- X
- X/* ===== Client Property Changes ================================== */
- X
- Xtypedef struct {
- X Atom *propAtom;
- X void (*updateFunc)();
- X} ClientPropUpdate;
- X
- Xstatic ClientPropUpdate propUpdateTable[] = {
- X &AtomWMName, FrameUpdateHeader,
- X &AtomLeftFooter, FrameUpdateFooter,
- X &AtomRightFooter, FrameUpdateFooter,
- X &AtomWMIconName, IconUpdateName,
- X &AtomColorMapWindows, ColorUpdateColorMapWindows,
- X &AtomProtocols, StateUpdateWMProtocols,
- X &AtomWMNormalHints, StateUpdateWMNormalHints,
- X &AtomWMHints, StateUpdateWMHints,
- X &AtomWindowBusy, ClientUpdateBusy,
- X &AtomSunWindowState, ClientUpdateWindowState,
- X &AtomSunDragDropInterest, ClientUpdateDragDropInterest,
- X &AtomWinAttr, StateUpdateWinAttr,
- X &AtomDecorAdd, StateUpdateDecorAdd,
- X &AtomDecorDel, StateUpdateDecorDel,
- X};
- X#define NPROPUPDATETABLE (sizeof(propUpdateTable)/sizeof(ClientPropUpdate))
- X
- X/* ClientDistributeProperty -- a property of the client has changed.
- X * Forward the change notification to the appropriate handler.
- X */
- Xvoid
- XClientDistributeProperty(cli, event)
- X Client *cli;
- X XPropertyEvent *event;
- X{
- X int i;
- X
- X for (i=0; i<NPROPUPDATETABLE; i++) {
- X if (event->atom == *propUpdateTable[i].propAtom) {
- X (propUpdateTable[i].updateFunc)(cli,event);
- X break;
- X }
- X }
- X}
- END_OF_FILE
- if test 37162 -ne `wc -c <'client.c'`; then
- echo shar: \"'client.c'\" unpacked with wrong size!
- fi
- # end of 'client.c'
- fi
- if test -f 'events.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'events.h'\"
- else
- echo shar: Extracting \"'events.h'\" \(3632 characters\)
- sed "s/^X//" >'events.h' <<'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#ifndef _OLWM_EVENT_H
- X#define _OLWM_EVENT_H
- X
- X#ident "@(#)events.h 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)events.h 26.11 91/09/14 SMI"
- X *
- X */
- X
- X/* global functions */
- Xextern void EventLoop();
- Xextern int PropagateEventToParent();
- Xextern void PropagatePressEventToChild();
- Xextern Time LastEventTime;
- Xextern Bool AwaitEvents();
- Xextern void GrabKeys();
- Xextern void RefreshKeyGrabs();
- Xextern void GrabButtons();
- Xextern void RefreshButtonGrabs();
- Xextern void UpdateBindings();
- Xextern void InitEvents();
- Xextern void InitBindings();
- X
- X/* interposition */
- Xextern void InstallInterposer();
- Xextern void UninstallInterposer();
- X
- Xenum {
- X DISPOSE_DISPATCH,
- X DISPOSE_USED,
- X DISPOSE_DEFER,
- X};
- X
- X/* keyboard mapping */
- Xextern KeySym *KbdMap;
- Xextern int MinKeyCode;
- Xextern int MaxKeyCode;
- Xextern int KeySymsPerKeyCode;
- X
- X/* modifiers and modifier masks */
- X
- Xenum {
- X MOD_CONSTRAIN,
- X MOD_WMGRAB,
- X MOD_REDUCE,
- X MOD_INVERT,
- X MOD_SETDEFAULT,
- X MOD_IGNORE,
- X MOD_MASK_COUNT /* must be last */
- X};
- X
- Xextern unsigned int ModMaskMap[MOD_MASK_COUNT];
- Xextern unsigned int FindModifierMask();
- X
- X/* mouse binding match states */
- Xtypedef enum {
- X MATCH_NONE, /* no binding matches at all */
- X MATCH_INCOMPLETE, /* partial match */
- X MATCH_AMBIG, /* more than one exact match */
- X MATCH_PREFIX, /* exact match, but also a prefix for another */
- X MATCH_EXACT, /* exact match, not a prefix */
- X} MouseMatchState;
- X
- X/* semantic actions */
- Xtypedef enum {
- X ACTION_NONE,
- X ACTION_SELECT,
- X ACTION_ADJUST,
- X ACTION_MENU,
- X ACTION_HELP,
- X ACTION_STOP,
- X ACTION_PROPS,
- X ACTION_FRONT,
- X ACTION_OPEN,
- X ACTION_EXEC_DEFAULT,
- X ACTION_FOCUS_HELP,
- X ACTION_SET_DEFAULT,
- X ACTION_UP,
- X ACTION_DOWN,
- X ACTION_LEFT,
- X ACTION_RIGHT,
- X ACTION_JUMP_UP,
- X ACTION_JUMP_DOWN,
- X ACTION_JUMP_LEFT,
- X ACTION_JUMP_RIGHT,
- X ACTION_ROW_START,
- X ACTION_ROW_END,
- X ACTION_DATA_START,
- X ACTION_DATA_END,
- X ACTION_FIRST_CONTROL,
- X ACTION_LAST_CONTROL,
- X ACTION_TOGGLE_PIN,
- X ACTION_CANCEL, /* REMIND does this differ from STOP? */
- X ACTION_NEXT_ELEMENT,
- X ACTION_PREVIOUS_ELEMENT,
- X ACTION_UPLEFT,
- X ACTION_UPRIGHT,
- X ACTION_DOWNLEFT,
- X ACTION_DOWNRIGHT,
- X ACTION_HOME,
- X ACTION_JUMP_UPLEFT,
- X ACTION_JUMP_UPRIGHT,
- X ACTION_JUMP_DOWNLEFT,
- X ACTION_JUMP_DOWNRIGHT,
- X ACTION_HALF_UP,
- X ACTION_HALF_DOWN,
- X ACTION_HALF_LEFT,
- X ACTION_HALF_RIGHT,
- X ACTION_HALF_UPLEFT,
- X ACTION_HALF_UPRIGHT,
- X ACTION_HALF_DOWNLEFT,
- X ACTION_HALF_DOWNRIGHT,
- X ACTION_GOTO_1,
- X ACTION_GOTO_2,
- X ACTION_GOTO_3,
- X ACTION_GOTO_4,
- X ACTION_GOTO_5,
- X ACTION_GOTO_6,
- X ACTION_GOTO_7,
- X ACTION_GOTO_8,
- X ACTION_GOTO_9,
- X ACTION_GOTO_10,
- X ACTION_VIRTUAL
- X} SemanticAction;
- X
- X/* convert a button number to a button mask */
- X#define ButtonToMask(b) (1<<(b+7))
- X
- X#define AnyButtonMask \
- X (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
- X
- X/* given a ButtonRelease event, determines whether all buttons are now up. */
- X#define AllButtonsUp(e) \
- X (!((e)->xbutton.state & ~ButtonToMask((e)->xbutton.button) & AnyButtonMask))
- X
- X/* given a ButtonPress event, determine whether it's the first button down. */
- X#define FirstButtonDown(e) \
- X (((e)->xbutton.state & AnyButtonMask) == 0)
- X
- X/* timeouts */
- Xtypedef void (*TimeoutFunc)();
- Xextern void TimeoutRequest(); /* int time, TimeoutFunc f, void *closure */
- Xextern void TimeoutCancel(); /* no params */
- X
- X#endif /* _OLWM_EVENT_H */
- END_OF_FILE
- if test 3632 -ne `wc -c <'events.h'`; then
- echo shar: \"'events.h'\" unpacked with wrong size!
- fi
- # end of 'events.h'
- fi
- if test -f 'winpush.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'winpush.c'\"
- else
- echo shar: Extracting \"'winpush.c'\" \(10989 characters\)
- sed "s/^X//" >'winpush.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#ident "@(#)winpush.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)winpush.c 26.19 91/09/14 SMI"
- 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
- 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
- X/***************************************************************************
- X* global data
- X***************************************************************************/
- X
- Xextern Atom AtomDeleteWindow;
- Xextern Atom AtomPushpinState;
- Xextern void FrameAllowEvents();
- X
- X/***************************************************************************
- X* private data
- X***************************************************************************/
- X
- Xstatic ClassPushPin classPushPin;
- Xstatic Bool pushpinStateAfterPress; /* State of the pushpin
- X * after the user pressed
- X * the mouse button. */
- Xstatic SemanticAction currentAction = ACTION_NONE;
- Xvoid PushPinChangePinState();
- X
- X/***************************************************************************
- X* private functions
- X***************************************************************************/
- X
- X/* locallyChangePushPinState -- temporarily change the pushpin state,
- X * while tracking a button press over the pin. The permanent change
- X * will be made later.
- X */
- Xstatic void
- XlocallyChangePushPinState(dpy,winInfo,newState)
- XDisplay *dpy;
- XWinPushPin *winInfo;
- XBool newState;
- X{
- X if (winInfo->pushpinin != newState)
- X {
- X winInfo->pushpinin = newState;
- X (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
- X }
- X}
- X
- X
- X/*
- X * eventButtonPress - handle button press events on the pushpin window
- X */
- Xstatic int
- XeventButtonPress(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPushPin *winInfo;
- X{
- X SemanticAction a = ResolveMouseBinding(dpy, event, 0L);
- X FrameAllowEvents(winInfo->core.client, event->xbutton.time);
- X switch (a) {
- X case ACTION_SELECT:
- X case ACTION_ADJUST:
- X locallyChangePushPinState(dpy, winInfo, !(winInfo->pushpinin));
- X pushpinStateAfterPress = winInfo->pushpinin;
- X currentAction = a;
- X break;
- X }
- X}
- X
- X/*
- X * eventButtonRelease - handle button release events on the pushpin window
- X */
- Xstatic int
- XeventButtonRelease(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPushPin *winInfo;
- X{
- X FrameAllowEvents(winInfo->core.client, event->xbutton.time);
- X if (!AllButtonsUp(event))
- X return;
- X
- X /*
- X * If pushpinStateAfterPress equals the current pin state, we know
- X * that the user really wants to change the pin state. If they are
- X * not equal, the user has released the button outside the pin, so
- X * there should be no change of state.
- X */
- X if (pushpinStateAfterPress == winInfo->pushpinin) {
- X PushPinChangePinState(dpy, winInfo,
- X currentAction == ACTION_SELECT);
- X }
- X currentAction = ACTION_NONE;
- X}
- X
- X/*
- X * eventMotionNotify - handle pointer moves
- X */
- Xstatic int
- XeventMotionNotify(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPushPin *winInfo;
- X{
- X Bool fInWindow;
- X Graphics_info *gisNormal = WinGI(winInfo,NORMAL_GINFO);
- X
- X if (!event->xmotion.same_screen)
- X return;
- X if (currentAction != ACTION_SELECT && currentAction != ACTION_ADJUST)
- X return;
- X
- X /* When the user moves the cursor off the pushpin
- X * while s/he has the button down we should pull
- X * the button out. If the user moves back onto the
- X * pushpin put the pin back in. So,
- X *
- X * if (cursor is off the pushpin) and (pin is in)
- X * OR
- X * (cursor is on the pushpin) and (pin is out)
- X * then
- X * change the state of the pushpin.
- X */
- X fInWindow = !((event->xmotion.x < 0) ||
- X (event->xmotion.y < 0) ||
- X (event->xmotion.x >= PushPinOut_Width(gisNormal)) ||
- X (event->xmotion.y >= PushPinOut_Height(gisNormal)));
- X locallyChangePushPinState(dpy, winInfo,
- X fInWindow?pushpinStateAfterPress:!pushpinStateAfterPress);
- X}
- X
- X
- X/*
- X * drawPushPin -- draw the pushpin window
- X */
- X/*ARGSUSED*/
- Xstatic int
- XdrawPushPin(dpy, winInfo)
- XDisplay *dpy;
- XWinPushPin *winInfo;
- X{
- X Client *cli = winInfo->core.client;
- X Graphics_info *gis;
- X int focusLines = (GRV.FocusFollowsMouse ? 1 : 0) ^
- X (GRV.InvertFocusHighlighting ? 1 : 0);
- X
- X if (cli->isFocus)
- X gis = WinGI(winInfo, INPUTFOCUS_GINFO);
- X else gis = WinGI(winInfo,NORMAL_GINFO);
- X /* If the titlebar is in reverse video we need to
- X * draw the pushpin in reverse video also.
- X */
- X if (Win3D(winInfo)) {
- X /*
- X * REMIND
- X * We need to erase the background here to BG2. We can't use
- X * OLGX_ERASE because olgx erases only in BG1. So, we draw an
- X * filled, invoked box that is just larger than the pin
- X * window, so that the border doesn't show.
- X */
- X
- X olgx_draw_box(gis, winInfo->core.self, -1, -1,
- X winInfo->core.width+2,
- X winInfo->core.height+2,
- X ((cli->isFocus) && !focusLines) ?
- X OLGX_INVOKED : OLGX_NORMAL,
- X True);
- X } else {
- X GC gc;
- X
- X if (cli->isFocus && !focusLines) {
- X gc = WinGC(winInfo, FOREGROUND_GC);
- X gis = WinGI(winInfo, REVPIN_GINFO);
- X } else {
- X gc = WinGC(winInfo, WINDOW_GC);
- X }
- X XFillRectangle(dpy, winInfo->core.self, gc, 0, 0,
- X winInfo->core.width, winInfo->core.height);
- X }
- X if (winInfo->core.client->isBusy)
- X {
- X XFillRectangle(dpy, winInfo->core.self, WinGC(winInfo,BUSY_GC),
- X 0, 0, winInfo->core.width, winInfo->core.height);
- X }
- X olgx_draw_pushpin(gis, winInfo->core.self, 0, 0,
- X ((winInfo->pushpinin) ? OLGX_PUSHPIN_IN : OLGX_PUSHPIN_OUT));
- X}
- X
- X
- X/*
- X * DestroyPushPin -- destroy the pushpin window resources and free any allocated
- X * data.
- X */
- Xstatic int
- XdestroyPushPin(dpy, winInfo)
- XDisplay *dpy;
- XWinPushPin *winInfo;
- X{
- X /* free our data and throw away window */
- X DestroyWindow(winInfo);
- X MemFree(winInfo);
- X}
- X
- X/*
- X * focusselectPushPin - the focus or selection state has changed
- X */
- Xstatic int
- XfocusselectPushPin(dpy, winInfo, selected)
- XDisplay *dpy;
- XWinPushPin *winInfo;
- XBool selected;
- X{
- X (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
- X}
- X
- X/*
- X * heightfuncPushPin - recomputes the correct height of the window
- X */
- Xstatic int
- XheightfuncPushPin(win, pxcre)
- XWinPushPin *win;
- XXConfigureRequestEvent *pxcre;
- X{
- X return PushPinOut_Width(WinGI(win,NORMAL_GINFO));
- X}
- X
- X/*
- X * widthfuncPushPin - recomputes the correct width of the window
- X */
- Xstatic int
- XwidthfuncPushPin(win, pxcre)
- XWinPushPin *win;
- XXConfigureRequestEvent *pxcre;
- X{
- X return PushPinOut_Height(WinGI(win,NORMAL_GINFO));
- X}
- X
- X/***************************************************************************
- X* global functions
- X***************************************************************************/
- X
- X/*
- X * MakePushPin -- create the pushpin window. Return a WinGeneric structure.
- X */
- XWinPushPin *
- XMakePushPin(dpy, par, pane, x, y)
- XDisplay *dpy;
- XWinGeneric *par;
- XWindow pane;
- Xint x,y;
- X{
- X WinPushPin *w;
- X Window win;
- X unsigned long valuemask;
- X XSetWindowAttributes attributes;
- X Graphics_info *gisNormal = WinGI(par,NORMAL_GINFO);
- X
- X attributes.event_mask = ButtonMotionMask | ButtonReleaseMask |
- X ButtonPressMask | ExposureMask;
- X attributes.win_gravity = NorthWestGravity;
- X valuemask = CWEventMask | CWWinGravity;
- X
- X win = XCreateWindow(dpy, par->core.self,
- X x, y,
- X PushPinOut_Width(gisNormal),
- X PushPinOut_Height(gisNormal),
- X 0,
- X CopyFromParent,
- X CopyFromParent,
- X CopyFromParent,
- X valuemask,
- X &attributes);
- X
- X /* create the associated structure */
- X w = MemNew(WinPushPin);
- X w->core.self = win;
- X w->class = &classPushPin;
- X w->core.kind = WIN_PUSHPIN;
- X WinAddChild(par,w);
- X w->core.children = NULL;
- X w->core.client = par->core.client;
- X w->core.x = x;
- X w->core.y = y;
- X w->core.width = PushPinOut_Width(gisNormal);
- X w->core.height = PushPinOut_Height(gisNormal);
- X w->core.dirtyconfig = CWX | CWY | CWWidth | CWHeight;
- X w->core.exposures = NULL;
- X w->core.helpstring = "olwm:PushPin";
- X
- X /* Determine initial state of push pin. */
- X w->pushpinin =
- X (par->core.client->wmDecors->pushpin_initial_state == PIN_IN);
- X
- X /* Register the push-pin state. */
- X XChangeProperty(dpy, pane,
- X AtomPushpinState,
- X XA_INTEGER, 32,
- X PropModeReplace,
- X (unsigned char *)&(w->pushpinin), 1);
- X
- X /* register the window */
- X WIInstallInfo(w);
- X
- X MapRaised(w);
- X
- X return w;
- X}
- X
- Xvoid
- XPushPinInit(dpy)
- XDisplay *dpy;
- X{
- X classPushPin.core.kind = WIN_PUSHPIN;
- X classPushPin.core.xevents[Expose] = WinEventExpose;
- X classPushPin.core.xevents[ButtonPress] = eventButtonPress;
- X classPushPin.core.xevents[ButtonRelease] = eventButtonRelease;
- X classPushPin.core.xevents[MotionNotify] = eventMotionNotify;
- X classPushPin.core.focusfunc = focusselectPushPin;
- X classPushPin.core.drawfunc = drawPushPin;
- X classPushPin.core.destroyfunc = destroyPushPin;
- X classPushPin.core.selectfunc = focusselectPushPin;
- X classPushPin.core.newconfigfunc = WinNewConfigFunc;
- X classPushPin.core.newposfunc = WinNewPosFunc;
- X classPushPin.core.setconfigfunc = WinSetConfigFunc;
- X classPushPin.core.createcallback = NULL;
- X classPushPin.core.heightfunc = heightfuncPushPin;
- X classPushPin.core.widthfunc = widthfuncPushPin;
- X}
- X
- X
- X/*
- X * Permanently change the push pin state.
- X */
- Xvoid
- XPushPinChangePinState(dpy, winInfo, sendDelete)
- X Display *dpy;
- X WinPushPin *winInfo;
- X Bool sendDelete;
- X{
- X Client *cli = winInfo->core.client;
- X
- X (WinFunc(winInfo,core.drawfunc))(dpy, winInfo);
- X
- X /* Tell the client that the state of its push-pin has changed. */
- X XChangeProperty(dpy, PANEWINOFCLIENT(cli),
- X AtomPushpinState,
- X XA_INTEGER, 32,
- X PropModeReplace,
- X (unsigned char *)&(winInfo->pushpinin), 1);
- X
- X if (!winInfo->pushpinin && sendDelete)
- X ClientKill(winInfo->core.client,False);
- X}
- X
- X/*
- X * Sets the pin state to a new state (if different that current state)
- X */
- Xvoid
- XPushPinSetPinState(dpy,winInfo,newState,sendDelete)
- X Display *dpy;
- X WinPushPin *winInfo;
- X int newState;
- X Bool sendDelete;
- X{
- X if (newState == winInfo->pushpinin)
- X return;
- X
- X winInfo->pushpinin = newState;
- X PushPinChangePinState(dpy,winInfo,sendDelete);
- X}
- X
- X/*
- X * Toggles the pin state
- X */
- Xvoid
- XPushPinTogglePinState(dpy,winInfo,sendDelete)
- X Display *dpy;
- X WinPushPin *winInfo;
- X Bool sendDelete;
- X{
- X winInfo->pushpinin = !winInfo->pushpinin;
- X PushPinChangePinState(dpy,winInfo,sendDelete);
- X}
- END_OF_FILE
- if test 10989 -ne `wc -c <'winpush.c'`; then
- echo shar: \"'winpush.c'\" unpacked with wrong size!
- fi
- # end of 'winpush.c'
- fi
- echo shar: End of archive 7 \(of 21\).
- cp /dev/null ark7isdone
- 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
-