home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!sun-barr!ames!pasteur!nntp
- From: scott.oaks@East.Sun.COM (Scott Oaks)
- Newsgroups: comp.sources.x
- Subject: v15i152: OpenLook Virtual Window Mgr (3.0), Part06/21
- Message-ID: <1992Feb4.135555.7121@pasteur.Berkeley.EDU>
- Date: 4 Feb 92 13:55:55 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: 2006
- Approved: dcmartin@msi.com
- Nntp-Posting-Host: postgres.berkeley.edu
-
- Submitted-by: scott.oaks@East.Sun.COM (Scott Oaks)
- Posting-number: Volume 15, Issue 152
- Archive-name: olvwm-3.0/part06
-
- # 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 6 (of 21)."
- # Contents: defaults.h evbind.c winpane.c
- # Wrapped by dcmartin@fascet on Tue Jan 14 05:54:43 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'defaults.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'defaults.h'\"
- else
- echo shar: Extracting \"'defaults.h'\" \(771 characters\)
- sed "s/^X//" >'defaults.h' <<'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 "@(#)defaults.h 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)defaults.h 26.7 91/09/14 SMI"
- X *
- X */
- X
- X/*
- X * default constants
- X */
- X#define DEFWORKSPACECOLOR "#40a0c0"
- X#define DEFWINDOWCOLOR "#cccccc"
- X#define DEFFOREGROUNDCOLOR "#000000"
- X#define DEFBACKGROUNDCOLOR "#ffffff"
- X#define DEFBORDERCOLOR "#000000"
- X
- X#define DEFVIRTUALFORECOLOR "#cccccc"
- X#define DEFVIRTUALBACKCOLOR "#40a0c0"
- X#define DEFVIRTUALFONTCOLOR "#ffffff"
- X#define DEFVIRTUALGRIDCOLOR "#ffffff"
- X#define DEFVIRTUALPIXMAPCOLOR "#000000"
- X
- X#define DEFAULTFONT "9x15"
- X
- Xvoid SetAllDBValues();
- END_OF_FILE
- if test 771 -ne `wc -c <'defaults.h'`; then
- echo shar: \"'defaults.h'\" unpacked with wrong size!
- fi
- # end of 'defaults.h'
- fi
- if test -f 'evbind.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'evbind.c'\"
- else
- echo shar: Extracting \"'evbind.c'\" \(38223 characters\)
- sed "s/^X//" >'evbind.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1991 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 "@(#)evbind.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)evbind.c 1.21 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/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#include "kbdfuncs.h"
- X#include "resources.h"
- X
- X
- X/* ===== externs ========================================================== */
- X
- Xextern List *ScreenInfoList;
- X
- X/* ===== private data ===================================================== */
- X
- Xstatic XrmQuark kbdCmdInstanceQ;
- Xstatic XrmQuark kbdCmdClassQ;
- Xstatic XrmQuark modInstanceQ;
- Xstatic XrmQuark modClassQ;
- X
- X/* ===== Modifier Binding ================================================= */
- X
- X
- Xunsigned int ModMaskMap[MOD_MASK_COUNT];
- X
- Xtypedef struct {
- X char *rsrc_name;
- X char *dflt_binding;
- X int mapindex;
- X} ModDescriptor;
- X
- XModDescriptor ModDescriptorTable[] = {
- X
- X /* rsrc_name default mapindex */
- X { "Constrain", "Control", MOD_CONSTRAIN },
- X { "WMGrab", "Alt", MOD_WMGRAB },
- X { "Reduce", "Meta", MOD_REDUCE },
- X { "Invert", "Shift", MOD_INVERT },
- X { "SetDefault", "Control", MOD_SETDEFAULT },
- X { "Ignore", "Lock,Num_Lock,mod5,Mode_switch", MOD_IGNORE }
- X
- X};
- X#define NMODBINDINGS (sizeof(ModDescriptorTable)/sizeof(ModDescriptor))
- X
- X
- X/*
- X * establishModBindings
- X *
- X * Read through the modifier descriptor table and fill in the modifier mask
- X * map with modifier masks found in the server's modifier mask map.
- X */
- Xstatic void
- XestablishModBindings(dpy, newDB)
- X Display *dpy;
- X XrmDatabase newDB;
- X{
- X XrmQuark classlist[4], instlist[4];
- X char *s;
- X XrmRepresentation rep;
- X XrmValue value;
- X ModDescriptor *d;
- X unsigned int polyStringToModifier();
- X static XrmBinding bindings[] =
- X { XrmBindTightly, XrmBindTightly, XrmBindTightly };
- X
- X classlist[0] = OpenWinQ;
- X classlist[1] = modClassQ;
- X classlist[3] = NULLQUARK;
- X
- X instlist[0] = TopInstanceQ;
- X instlist[1] = modInstanceQ;
- X instlist[3] = NULLQUARK;
- X
- X for (d = ModDescriptorTable; d < ModDescriptorTable + NMODBINDINGS; ++d) {
- X
- X classlist[2] = instlist[2] = XrmStringToQuark(d->rsrc_name);
- X
- X if (XrmQGetResource(newDB, instlist, classlist, &rep, &value))
- X s = (char *) value.addr;
- X else {
- X /*
- X * Use olwm binding -- see resources.c
- X */
- X classlist[0] = OlwmQ;
- X if (XrmQGetResource(newDB, instlist, classlist, &rep, &value))
- X s = (char *) value.addr;
- X else s = d->dflt_binding;
- X classlist[0] = OpenWinQ;
- X }
- X
- X ModMaskMap[d->mapindex] = polyStringToModifier(dpy, s);
- X }
- X}
- X
- X
- X/* ===== Mouse Binding ==================================================== */
- X
- X
- X/*
- X * Table of mouse bindings.
- X *
- X * REMIND
- X *
- X * At a future time, this table will be changeable via resources. For now,
- X * it's specified as a compile-time constant.
- X */
- X
- Xtypedef struct {
- X int state;
- X int button;
- X SemanticAction action;
- X} MouseBinding;
- X
- XMouseBinding MouseBindingTable[] = {
- X /* state, button, action */
- X { 0, Button1, ACTION_SELECT },
- X { 0, Button2, ACTION_ADJUST },
- X { 0, Button3, ACTION_MENU },
- X { ButtonToMask(1), Button2, ACTION_MENU },
- X { ButtonToMask(2), Button1, ACTION_MENU },
- X { ShiftMask, Button1, ACTION_ADJUST },
- X { ControlMask, Button3, ACTION_MENU },
- X { ControlMask|ButtonToMask(1), Button2, ACTION_MENU },
- X { ControlMask|ButtonToMask(2), Button1, ACTION_MENU },
- X};
- X#define NMOUSEBINDINGS (sizeof(MouseBindingTable)/sizeof(MouseBinding))
- X
- X
- X/*
- X * searchMouseBindings
- X *
- X * Search the mouse binding table and return information about what was found.
- X * Return values of MATCH_NONE, MATCH_INCOMPLETE, and MATCH_AMBIG mean that no
- X * action is available for the given event. MATCH_PREFIX and MATCH_EXACT
- X * indicate that an action is available; this action is returned in the area
- X * pointed to by the action parameter.
- X */
- Xstatic MouseMatchState
- XsearchMouseBindings(pe, action)
- X XButtonEvent *pe;
- X SemanticAction *action;
- X{
- X int i;
- X int nexact = 0; /* number of exact matches */
- X int nprefix = 0; /* number of prefix matches */
- X int lastexact = 0; /* index of last exact match */
- X unsigned int modmask = (pe->state | ButtonToMask(pe->button));
- X
- X for (i=0; i<NMOUSEBINDINGS; ++i) {
- X if (pe->state == MouseBindingTable[i].state &&
- X pe->button == MouseBindingTable[i].button) {
- X lastexact = i;
- X ++nexact;
- X } else if (modmask == MouseBindingTable[i].state) {
- X ++nprefix;
- X }
- X }
- X
- X if (nexact == 0 && nprefix == 0)
- X return MATCH_NONE;
- X if (nexact == 0 && nprefix > 0)
- X return MATCH_INCOMPLETE;
- X if (nexact > 1)
- X return MATCH_AMBIG;
- X
- X /* at this point, we know there is exactly one exact match */
- X *action = MouseBindingTable[lastexact].action;
- X if (nprefix == 0)
- X return MATCH_EXACT;
- X else
- X return MATCH_PREFIX;
- X}
- X
- X
- X/*
- X * checkChording
- X *
- X * Scan the input queue for button events that will disambiguate a single
- X * action from a chorded action. If there aren't any events in the queue,
- X * wait for them until a certain timeout period has elapsed. Return value
- X * indicates whether a ButtonPress was seen further ahead in the event stream,
- X * which indicates that this event is part of a chorded sequence. The timeout
- X * parameter is updated with the amount of time remaining.
- X */
- Xstatic Bool
- XcheckChording(dpy, timeout, pr)
- X Display *dpy;
- X struct timeval timeout;
- X XButtonEvent *pr;
- X{
- X XEvent e;
- X int n;
- X
- X while (1) {
- X /*
- X * Check for data on the connection. Scan it for disambiguating
- X * events. Note that MotionNotify events within the move threshold
- X * are discarded.
- X */
- X n = XEventsQueued(dpy, QueuedAfterReading);
- X if (n > 0 && XCheckMaskEvent(dpy,
- X ButtonPressMask|ButtonReleaseMask|ButtonMotionMask, &e)) {
- X switch (e.type) {
- X case ButtonPress:
- X XPutBackEvent(dpy, &e);
- X return True;
- X case ButtonRelease:
- X XPutBackEvent(dpy, &e);
- X return False;
- X case MotionNotify:
- X if (ABS(pr->x_root - e.xmotion.x_root) > GRV.MoveThreshold ||
- X ABS(pr->y_root - e.xmotion.y_root) > GRV.MoveThreshold) {
- X XPutBackEvent(dpy, &e);
- X return False;
- X }
- X break;
- X }
- X }
- X
- X if (!AwaitEvents(dpy, &timeout))
- X return False;
- X }
- X}
- X
- X
- X/*
- X * ResolveMouseBinding
- X *
- X * Given a mouse button press event, determines whether this event completes
- X * an event sequence that binds to an action. If the button press is a prefix
- X * of a chording sequence, and this press falls within the chording time of
- X * the initial button press, checkChording is called to disambiguate the event
- X * stream. Returns a proper action if the action is complete, otherwise
- X * returns ACTION_NONE. All callers should ensure that no action is taken
- X * when this routine returns ACTION_NONE.
- X */
- XSemanticAction
- XResolveMouseBinding(dpy, pevent, ignoremask)
- X Display *dpy;
- X XEvent *pevent;
- X unsigned long ignoremask;
- X{
- X MouseMatchState m;
- X struct timeval timeout;
- X SemanticAction a;
- X static Time firstpresstime;
- X XEvent e;
- X
- X /* copy *pevent to e, masking off ignored bits from the state */
- X e = *pevent;
- X e.xbutton.state &= ~(ignoremask |
- X ModMaskMap[MOD_IGNORE] |
- X ModMaskMap[MOD_WMGRAB]);
- X
- X /* Chording is in msec. Convert to sec/usec for timeval. */
- X timeout.tv_usec = GRV.MouseChordTimeout * 1000;
- X if (timeout.tv_usec >= 1000000) {
- X timeout.tv_sec = timeout.tv_usec / 1000000;
- X timeout.tv_usec %= 1000000;
- X } else {
- X timeout.tv_sec = 0;
- X }
- X
- X if (FirstButtonDown(&e)) {
- X firstpresstime = e.xbutton.time;
- X } else {
- X if (e.xbutton.time - firstpresstime > GRV.MouseChordTimeout)
- X return ACTION_NONE;
- X }
- X
- X m = searchMouseBindings(&e, &a);
- X if ((m == MATCH_PREFIX && !checkChording(dpy, timeout, &e))
- X || m == MATCH_EXACT) {
- X return a;
- X } else {
- X return ACTION_NONE;
- X }
- X}
- X
- X
- X/* ===== Keyboard Binding ================================================= */
- X
- X/*
- X * Table of default keyboard descriptors. This table contains information
- X * necessary to initialize keyboard bindings and customize them based on
- X * resources.
- X */
- X
- X#define NULLFUNC ((void (*)())0)
- X
- Xextern void HandleHelpKey();
- X
- Xstatic void keySuspend();
- Xstatic void keyResume();
- Xstatic void keyQuoteNext();
- X
- Xstatic unsigned long mouselessMaskTable[] = { KD_SUNVIEW, KD_BASIC, KD_FULL };
- X
- XKeyDescriptor KeyDescriptorTable[] = {
- X
- X/*
- X rsrc_name dflt_binding function
- X action flags
- X */
- X
- X{
- X "Stop", "L1,Escape", NULLFUNC,
- X ACTION_STOP, KD_ALWAYS
- X}, {
- X "DefaultAction", "Return,Return+Meta,KP_Enter", NULLFUNC,
- X ACTION_EXEC_DEFAULT, KD_ALWAYS
- X}, {
- X "Select", "space", NULLFUNC,
- X ACTION_SELECT, KD_ALWAYS
- X}, {
- X "Adjust", "Insert+Alt", NULLFUNC,
- X ACTION_ADJUST, KD_ALWAYS
- X}, {
- X "Menu", "space+Alt", NULLFUNC,
- X ACTION_MENU, KD_ALWAYS
- X}, {
- X "InputFocusHelp", "question,question+Ctrl", NULLFUNC,
- X ACTION_FOCUS_HELP, KD_ALWAYS
- X}, {
- X "Up", "Up", NULLFUNC,
- X ACTION_UP, KD_ALWAYS,
- X}, {
- X "Down", "Down", NULLFUNC,
- X ACTION_DOWN, KD_ALWAYS,
- X}, {
- X "Left", "Left", NULLFUNC,
- X ACTION_LEFT, KD_ALWAYS
- X}, {
- X "Right", "Right", NULLFUNC,
- X ACTION_RIGHT, KD_ALWAYS
- X}, {
- X "JumpUp", "Up+Ctrl", NULLFUNC,
- X ACTION_JUMP_UP, KD_ALWAYS
- X}, {
- X "JumpDown", "Down+Ctrl", NULLFUNC,
- X ACTION_JUMP_DOWN, KD_ALWAYS
- X}, {
- X "JumpLeft", "Left+Ctrl", NULLFUNC,
- X ACTION_JUMP_LEFT, KD_ALWAYS
- X}, {
- X "JumpRight", "Right+Ctrl", NULLFUNC,
- X ACTION_JUMP_RIGHT, KD_ALWAYS
- X}, {
- X "RowStart", "Home,R7", NULLFUNC,
- X ACTION_ROW_START, KD_ALWAYS
- X}, {
- X "RowEnd", "End,R13", NULLFUNC,
- X ACTION_ROW_END, KD_ALWAYS
- X}, {
- X "DataStart", "Home+Ctrl", NULLFUNC,
- X ACTION_DATA_START, KD_ALWAYS
- X}, {
- X "DataEnd", "End+Ctrl", NULLFUNC,
- X ACTION_DATA_END, KD_ALWAYS
- X}, {
- X "FirstControl", "bracketleft+Ctrl", NULLFUNC,
- X ACTION_FIRST_CONTROL, KD_ALWAYS
- X}, {
- X "LastControl", "bracketright+Ctrl", NULLFUNC,
- X ACTION_LAST_CONTROL, KD_ALWAYS
- X}, {
- X "NextElement", "Tab,Tab+Ctrl", NULLFUNC,
- X ACTION_NEXT_ELEMENT, KD_ALWAYS
- X}, {
- X "PreviousElement", "Tab+Shift,Tab+Shift+Ctrl", NULLFUNC,
- X ACTION_PREVIOUS_ELEMENT, KD_ALWAYS
- X}, {
- X "Open", "L7+Alt", NULLFUNC,
- X ACTION_OPEN, KD_ALWAYS
- X}, {
- X "Help", "Help", HandleHelpKey,
- X ACTION_HELP, KD_BASIC_FULL
- X}, {
- X "LockColormap", "L2+Ctrl", KeyLockColormap,
- X ACTION_NONE, KD_BASIC_FULL
- X}, {
- X "UnlockColormap", "L4+Ctrl", KeyUnlockColormap,
- X ACTION_NONE, KD_BASIC_FULL
- X}, {
- X "Front", "L5+Alt", KeyFrontFocus,
- X ACTION_FRONT, KD_BASIC_FULL
- X}, {
- X "FocusToPointer", "j+Shift+Alt", KeyFocusToPointer,
- X ACTION_NONE, KD_FULL
- X}, {
- X "NextApp", "n+Alt", KeyNextApp,
- X ACTION_NONE, KD_FULL
- X}, {
- X "PreviousApp", "N+Alt", KeyPrevApp,
- X ACTION_NONE, KD_FULL
- X}, {
- X "ToggleInput", "t+Alt", KeyToggleInput,
- X ACTION_NONE, KD_FULL
- X}, {
- X "NextWindow", "w+Alt", KeyNextWindow,
- X ACTION_NONE, KD_FULL
- X}, {
- X "PreviousWindow", "W+Alt", KeyPrevWindow,
- X ACTION_NONE, KD_FULL
- X}, {
- X "TogglePin", "Insert+Meta", KeyTogglePin,
- X ACTION_TOGGLE_PIN, KD_FULL
- X}, {
- X "SuspendMouseless", "z+Alt", keySuspend,
- X ACTION_NONE, KD_BASIC_FULL
- X}, {
- X "ResumeMouseless", "Z+Alt", keyResume,
- X ACTION_NONE, KD_IMMUNE | KD_BASIC_FULL
- X}, {
- X "QuoteNextKey", "q+Alt", keyQuoteNext,
- X ACTION_NONE, KD_BASIC_FULL
- X}, {
- X "Refresh", "F8+Alt", KeyRefresh,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Back", "F5+Alt", KeyBackFocus,
- X ACTION_NONE, KD_FULL
- X}, {
- X "OpenClose", "F2+Alt", KeyOpenCloseFocus,
- X ACTION_NONE, KD_FULL
- X}, {
- X "FullRestore", "F3+Alt", KeyFullRestore,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Quit", "F9+Alt", KeyQuit,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Owner", "F10+Alt", KeyOwner,
- X ACTION_NONE, KD_FULL
- X}, {
- X "WorkspaceMenu", "M+Alt", KeyWorkspaceMenu,
- X ACTION_NONE, KD_FULL
- X}, {
- X "WindowMenu", "m+Alt", KeyWindowMenu,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Move", "F6+Alt", KeyMove,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Resize", "F7+Alt", KeyResize,
- X ACTION_NONE, KD_FULL
- X}, {
- X "Properties", "F4+Alt", KeyProperties,
- X ACTION_NONE, KD_FULL
- X}, {
- X "OpenClosePointer", "L7", KeyOpenClosePointer,
- X ACTION_NONE, KD_ALWAYS
- X}, {
- X "RaiseLower", "L5", KeyRaiseLowerPointer,
- X ACTION_NONE, KD_ALWAYS
- X},
- X
- X/*
- X * Keymappings for the virtual desktop. The keypad keys are mapped
- X * in a clockwise fashion around the arrow keys. These keys with a meta
- X * modifier are grabbed and are always active, otherwise they fall through
- X * to the no focus window which moves the vdm
- X *
- X * We don't have a nofocus action for R7 and R13 since they already have
- X * an action above
- X */
- X { "VirtualUp", "Up+Meta", KeyMoveVDM,
- X ACTION_UP, KD_ALWAYS },
- X { "HalfUp", "Up+Shift", NULLFUNC,
- X ACTION_HALF_UP, KD_ALWAYS },
- X { "VirtualHalfUp", "Up+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_UP, KD_ALWAYS },
- X { "VirtualJumpUp", "Up+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_UP, KD_ALWAYS },
- X
- X { "VirtualDown", "Down+Meta", KeyMoveVDM,
- X ACTION_DOWN, KD_ALWAYS },
- X { "HalfDown", "Down+Shift", NULLFUNC,
- X ACTION_HALF_DOWN, KD_ALWAYS },
- X { "VirtualHalfDown", "Down+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_DOWN, KD_ALWAYS },
- X { "VirtualJumpDown", "Down+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_DOWN, KD_ALWAYS },
- X
- X { "VirtualLeft", "Left+Meta", KeyMoveVDM,
- X ACTION_LEFT, KD_ALWAYS },
- X { "HalfLeft", "Left+Shift", NULLFUNC,
- X ACTION_HALF_LEFT, KD_ALWAYS },
- X { "VirtualHalfLeft", "Left+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_LEFT, KD_ALWAYS },
- X { "VirtualJumpLeft", "Left+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_LEFT, KD_ALWAYS },
- X
- X { "VirtualRight", "Right+Meta", KeyMoveVDM,
- X ACTION_RIGHT, KD_ALWAYS },
- X { "HalfRight", "Right+Shift", NULLFUNC,
- X ACTION_HALF_RIGHT, KD_ALWAYS },
- X { "VirtualHalfRight", "Right+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_RIGHT, KD_ALWAYS },
- X { "VirtualJumpRight", "Right+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_RIGHT, KD_ALWAYS },
- X
- X { "VirtualUpLeft", "R7+Meta", KeyMoveVDM,
- X ACTION_UPLEFT, KD_ALWAYS },
- X { "JumpUpLeft", "R7+Ctrl", NULLFUNC,
- X ACTION_JUMP_UPLEFT, KD_ALWAYS },
- X { "VirtualJumpUpLeft", "R7+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_UPLEFT, KD_ALWAYS },
- X { "HalfUpLeft", "R7+Shift", NULLFUNC,
- X ACTION_HALF_UPLEFT, KD_ALWAYS },
- X { "VirtualHalfUpLeft", "R7+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_UPLEFT, KD_ALWAYS },
- X
- X { "VirtualUpRight", "R9+Meta", KeyMoveVDM,
- X ACTION_UPRIGHT, KD_ALWAYS },
- X { "UpRight", "R9", NULLFUNC,
- X ACTION_UPRIGHT, KD_ALWAYS },
- X { "JumpUpRight", "R9+Ctrl", NULLFUNC,
- X ACTION_JUMP_UPRIGHT, KD_ALWAYS },
- X { "VirtualJumpUpRight", "R9+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_UPRIGHT, KD_ALWAYS },
- X { "HalfUpRight", "R9+Shift", NULLFUNC,
- X ACTION_HALF_UPRIGHT, KD_ALWAYS },
- X { "VirtualHalfUpRight", "R9+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_UPRIGHT, KD_ALWAYS },
- X
- X { "VirtualDownLeft", "R13+Meta", KeyMoveVDM,
- X ACTION_DOWNLEFT, KD_ALWAYS },
- X { "JumpDownLeft", "R13+Ctrl", NULLFUNC,
- X ACTION_JUMP_DOWNLEFT, KD_ALWAYS },
- X { "VirtualJumpDownLeft", "R13+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_DOWNLEFT, KD_ALWAYS },
- X { "HalfDownLeft", "R13+Shift", NULLFUNC,
- X ACTION_HALF_DOWNLEFT, KD_ALWAYS },
- X { "VirtualHalfDownLeft", "R13+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_DOWNLEFT, KD_ALWAYS },
- X
- X { "VirtualDownRight", "R15+Meta", KeyMoveVDM,
- X ACTION_DOWNRIGHT, KD_ALWAYS },
- X { "DownRight", "R15", NULLFUNC,
- X ACTION_DOWNRIGHT, KD_ALWAYS },
- X { "JumpDownRight", "R15+Ctrl", NULLFUNC,
- X ACTION_JUMP_DOWNRIGHT, KD_ALWAYS },
- X { "VirtualJumpDownRight", "R15+Ctrl+Meta", KeyMoveVDM,
- X ACTION_JUMP_DOWNRIGHT, KD_ALWAYS },
- X { "HalfDownRight", "R15+Shift", NULLFUNC,
- X ACTION_HALF_DOWNRIGHT, KD_ALWAYS },
- X { "VirtualHalfDownRight", "R15+Shift+Meta", KeyMoveVDM,
- X ACTION_HALF_DOWNRIGHT, KD_ALWAYS },
- X
- X { "VirtualHome", "R11+Meta", KeyMoveVDM,
- X ACTION_HOME, KD_ALWAYS },
- X { "GoHome", "R11", NULLFUNC,
- X ACTION_HOME, KD_ALWAYS },
- X
- X { "VirtualScreen1", "F1+Meta", KeyMoveVDM,
- X ACTION_GOTO_1, KD_ALWAYS },
- X { "Screen1", "F1", NULLFUNC,
- X ACTION_GOTO_1, KD_ALWAYS },
- X { "VirtualScreen2", "F2+Meta", KeyMoveVDM,
- X ACTION_GOTO_2, KD_ALWAYS },
- X { "Screen2", "F2", NULLFUNC,
- X ACTION_GOTO_2, KD_ALWAYS },
- X { "VirtualScreen3", "F3+Meta", KeyMoveVDM,
- X ACTION_GOTO_3, KD_ALWAYS },
- X { "Screen3", "F3", NULLFUNC,
- X ACTION_GOTO_3, KD_ALWAYS },
- X { "VirtualScreen4", "F4+Meta", KeyMoveVDM,
- X ACTION_GOTO_4, KD_ALWAYS },
- X { "Screen4", "F4", NULLFUNC,
- X ACTION_GOTO_4, KD_ALWAYS },
- X { "VirtualScreen5", "F5+Meta", KeyMoveVDM,
- X ACTION_GOTO_5, KD_ALWAYS },
- X { "Screen5", "F5", NULLFUNC,
- X ACTION_GOTO_5, KD_ALWAYS },
- X { "VirtualScreen6", "F6+Meta", KeyMoveVDM,
- X ACTION_GOTO_6, KD_ALWAYS },
- X { "Screen6", "F6", NULLFUNC,
- X ACTION_GOTO_6, KD_ALWAYS },
- X { "VirtualScreen7", "F7+Meta", KeyMoveVDM,
- X ACTION_GOTO_7, KD_ALWAYS },
- X { "Screen7", "F7", NULLFUNC,
- X ACTION_GOTO_7, KD_ALWAYS },
- X { "VirtualScreen8", "F8+Meta", KeyMoveVDM,
- X ACTION_GOTO_8, KD_ALWAYS },
- X { "Screen8", "F8", NULLFUNC,
- X ACTION_GOTO_8, KD_ALWAYS },
- X { "VirtualScreen9", "F9+Meta", KeyMoveVDM,
- X ACTION_GOTO_9, KD_ALWAYS },
- X { "Screen9", "F9", NULLFUNC,
- X ACTION_GOTO_9, KD_ALWAYS },
- X { "VirtualScreen10", "F10+Meta", KeyMoveVDM,
- X ACTION_GOTO_10, KD_ALWAYS },
- X { "Screen10", "F10", NULLFUNC,
- X ACTION_GOTO_10, KD_ALWAYS },
- X};
- X
- X#define NUMKEYDESCRIPTORS (sizeof(KeyDescriptorTable)/sizeof(KeyDescriptor))
- X
- X
- Xtypedef struct {
- X unsigned int modstate;
- X KeyCode keycode;
- X KeyDescriptor *desc;
- X} KeyBinding;
- X
- X
- Xtypedef struct {
- X KeySym sym;
- X unsigned int mod;
- X} modsym;
- X
- X
- X#define KEYBINDING_TABLE_SIZE 60
- X#define KEYBINDING_TABLE_INCR 20
- X
- Xstatic KeyBinding *KeyBindingTable = NULL;
- Xstatic KeyBinding *activeKey = NULL;
- Xstatic int bindingTableCount = 0;
- Xstatic int bindingTableSize = 0;
- Xstatic Bool suspended = False;
- Xstatic Bool quotenext = False;
- X
- X
- X/*
- X * Suspension and resumption of Mouseless functions.
- X */
- Xstatic void
- XkeySuspend(dpy, ke)
- X Display *dpy;
- X XKeyEvent *ke;
- X{
- X if (ke->type != KeyPress)
- X return;
- X suspended = True;
- X}
- X
- X
- Xstatic void
- XkeyResume(dpy, ke)
- X Display *dpy;
- X XKeyEvent *ke;
- X{
- X if (ke->type != KeyPress)
- X return;
- X suspended = False;
- X}
- X
- X
- XBool
- XIsMouselessSuspended()
- X{
- X return suspended;
- X}
- X
- Xstatic void
- XkeyQuoteNext(dpy, ke)
- X Display *dpy;
- X XKeyEvent *ke;
- X{
- X /*
- X * Turn on quotenext on the release. If we set it on the press,
- X * the subsequent release would turn it off!
- X */
- X if (ke->type != KeyRelease)
- X return;
- X quotenext = True;
- X}
- X
- X
- X/*
- X * Add a binding to the key binding table.
- X */
- Xvoid
- XAddKeyBinding(kc, mod, desc)
- X KeyCode kc;
- X unsigned int mod;
- X KeyDescriptor *desc;
- X{
- X KeyBinding *b;
- X
- X if (bindingTableCount == bindingTableSize) {
- X bindingTableSize += KEYBINDING_TABLE_INCR;
- X KeyBindingTable = MemRealloc(KeyBindingTable,
- X bindingTableSize*sizeof(KeyBinding));
- X }
- X
- X b = &KeyBindingTable[bindingTableCount];
- X b->keycode = kc;
- X b->modstate = mod;
- X b->desc = desc;
- X ++bindingTableCount;
- X}
- X
- X
- X/*
- X * Keysym aliasing. Provides aliases for modifier keysyms. Allows an alias
- X * to represent a mask or to be a synonym for up to two keysyms. The keysyms
- X * are only looked at if the mask value is zero.
- X */
- X
- Xtypedef struct {
- X char *alias;
- X unsigned int mask;
- X KeySym sym1, sym2;
- X} KeysymAlias;
- X
- Xstatic KeysymAlias KeysymAliasTable[] = {
- X /* alias mask sym1 sym2 */
- X { "Any", AnyModifier, 0, 0 },
- X { "Shift", ShiftMask, 0, 0 },
- X { "Lock", LockMask, 0, 0 },
- X { "Control", ControlMask, 0, 0 },
- X { "Ctrl", ControlMask, 0, 0 },
- X { "Ctl", ControlMask, 0, 0 },
- X { "Meta", 0, XK_Meta_L, XK_Meta_R },
- X { "Alt", 0, XK_Alt_L, XK_Alt_R },
- X { "Super", 0, XK_Super_L, XK_Super_R },
- X { "Hyper", 0, XK_Hyper_L, XK_Hyper_R }
- X};
- X#define NUMALIASES (sizeof(KeysymAliasTable)/sizeof(KeysymAlias))
- X
- X
- X/*
- X * Takes a word and presumes that it names a keysym. Looks up this keysym in
- X * the modifier mapping table and returns the corresponding modifier mask. If
- X * the string doesn't name a valid keysym, returns 0. If the keysym is not a
- X * modifier, returns 0. If the word is "Any", returns AnyModifier. Several
- X * aliases are supported for well-known modifiers, e.g. "Meta" for "Meta_L" or
- X * "Meta_R". REMIND: If a keysym is on several keys, and only some of the
- X * keys are modifiers, this function may fail to find the modifier mask.
- X */
- Xunsigned int
- XstringToModifier(dpy, word)
- X Display *dpy;
- X char *word;
- X{
- X KeySym ks;
- X KeyCode kc;
- X KeysymAlias *ksa;
- X int modnum;
- X
- X ks = XStringToKeysym(word);
- X
- X if (ks != NoSymbol) {
- X kc = XKeysymToKeycode(dpy, ks);
- X
- X if (kc == 0)
- X return 0;
- X else
- X return FindModifierMask(kc);
- X }
- X
- X /*
- X * It's not a valid keysym name, so try a bunch of aliases. First,
- X * Allow "mod1" ... "mod5" as synonyms for Mod1Mask ... Mod5Mask.
- X */
- X
- X if (1 == sscanf(word, "mod%d", &modnum) &&
- X modnum >= 1 && modnum <= 5)
- X {
- X return (1 << (Mod1MapIndex + modnum - 1));
- X }
- X
- X /* look through the alias table for masks or keysyms */
- X
- X kc = 0;
- X for (ksa = KeysymAliasTable; ksa < KeysymAliasTable + NUMALIASES;
- X ++ksa)
- X {
- X if (0 == strcmp(word, ksa->alias)) {
- X if (ksa->mask != 0)
- X return ksa->mask;
- X
- X kc = XKeysymToKeycode(dpy, ksa->sym1);
- X
- X if (kc == 0)
- X kc = XKeysymToKeycode(dpy, ksa->sym2);
- X
- X if (kc == 0)
- X return 0;
- X else
- X return FindModifierMask(kc);
- X }
- X }
- X
- X return 0;
- X}
- X
- X
- X/*
- X * Parses a comma-separated string into words, gets the modifier mask for
- X * each, ORs them together and returns the result.
- X */
- Xunsigned int
- XpolyStringToModifier(dpy, str)
- X Display *dpy;
- X char *str;
- X{
- X char buf[200];
- X unsigned int result = 0;
- X char *word;
- X
- X /* make a copy first, because strtok riddles the string with nulls. */
- X strcpy(buf, str);
- X word = strtok(buf, ",");
- X while (word != NULL) {
- X result |= stringToModifier(dpy, word);
- X word = strtok(NULL, ",");
- X }
- X return result;
- X}
- X
- X
- X#define MAX_MAPPINGS 6
- X
- X/*
- X * Parses a key specification of the form
- X * keymod[,keymod[,...]]
- X * where keymod is
- X * keysym[+modifier[+...]]
- X */
- Xstatic int
- XparseKeySpec(dpy, specifier, syms)
- X char *specifier;
- X modsym *syms;
- X{
- X char spec[200];
- X char *mapping[MAX_MAPPINGS];
- X char *keysym_string, *mod_string;
- X KeySym keysym;
- X int k;
- X int modmask, newmod;
- X int nbound = 0;
- X char buffer[200];
- X
- X /* make a copy first, because strtok riddles the string with nulls. */
- X strcpy(spec, specifier);
- X
- X /* break apart comma-separated mappings */
- X mapping[0] = strtok(spec, ",");
- X for (k = 1; k < MAX_MAPPINGS; ++k) {
- X mapping[k] = strtok(NULL, ",");
- X if (mapping[k] == NULL)
- X break;
- X }
- X
- X /* for each mapping, break into keysym and modifier components */
- X for (k = 0; k < MAX_MAPPINGS && mapping[k]; ++k) {
- X keysym_string = strtok(mapping[k], "+");
- X if (!keysym_string) {
- X (void) sprintf(buffer, gettext("bad key mapping `%s'\n"),
- X mapping[k]);
- X ErrorWarning(buffer);
- X continue;
- X }
- X keysym = XStringToKeysym(keysym_string);
- X if (keysym == NoSymbol) {
- X (void) sprintf(buffer, gettext("can't find keysym for `%s'\n"),
- X keysym_string);
- X ErrorWarning(buffer);
- X continue;
- X }
- X
- X /*
- X * If the keysym is upper case alphabetic, add a shift mask. If it's
- X * lower case, convert it to upper case.
- X */
- X modmask = 0;
- X if (XK_A <= keysym && keysym <= XK_Z)
- X modmask = ShiftMask;
- X if (XK_a <= keysym && keysym <= XK_z)
- X keysym -= (XK_a - XK_A);
- X
- X while (1) {
- X mod_string = strtok(NULL, "+");
- X if (!mod_string)
- X break;
- X newmod = stringToModifier(dpy, mod_string);
- X if (newmod == 0) {
- X /*
- X * We couldn't find a modifier; ignore this binding. We can't
- X * use continue, because we want to continue an outer loop.
- X */
- X goto nobinding;
- X }
- X modmask |= newmod;
- X }
- X syms[nbound].sym = keysym;
- X syms[nbound].mod = modmask;
- X ++nbound;
- X nobinding: ;
- X } /* for each mapping */
- X return nbound;
- X}
- X
- X
- X/*
- X * Run through the table of key descriptors and establish key bindings for
- X * each descriptor. First, the resource database is probed for a customized
- X * key binding specification. If one isn't found, the default key binding
- X * specification is used. Then, this specification is parsed into an array of
- X * keysym/modifier pairs. For each pair, the keyboard mapping table is
- X * searched for the keysym and an entry is made into the binding table for
- X * each instance of the keysym in the mapping table. Thus, if a keysym
- X * appears on more than one keystation, a key binding entry is created for
- X * each.
- X *
- X * If a resource is found, it is always used. If no resource is found, the
- X * default specification is used only if the current mouseless setting has
- X * this binding enabled. So, setting mouseless to Basic or SunView will
- X * disable most key bindings. However, if you add a specific resource, it
- X * will always be honored.
- X */
- Xstatic void
- XestablishKeyBindings(dpy)
- X Display *dpy;
- X{
- X KeyDescriptor *d;
- X KeyBinding *kb;
- X modsym syms[MAX_MAPPINGS];
- X int nsyms;
- X int i, j;
- X int keytblsize = (MaxKeyCode-MinKeyCode+1) * KeySymsPerKeyCode;
- X XrmQuark classlist[4], namelist[4];
- X XrmQuark rep;
- X XrmValue value;
- X char *keyspec;
- X unsigned long mask;
- X
- X classlist[1] = kbdCmdClassQ;
- X classlist[3] = NULLQUARK;
- X
- X namelist[0] = TopInstanceQ;
- X namelist[1] = kbdCmdInstanceQ;
- X namelist[3] = NULLQUARK;
- X
- X mask = mouselessMaskTable[GRV.Mouseless];
- X
- X for (d=KeyDescriptorTable; d < KeyDescriptorTable+NUMKEYDESCRIPTORS;
- X ++d) {
- X classlist[0] = OpenWinQ;
- X classlist[2] = namelist[2] = XrmStringToQuark(d->rsrc_name);
- X if (XrmQGetResource(OlwmDB, namelist, classlist, &rep, &value)) {
- X keyspec = (char *) value.addr;
- X } else {
- X /*
- X * Use olwm binding; see resources.c
- X */
- X classlist[0] = OlwmQ;
- X if (XrmQGetResource(OlwmDB, namelist, classlist, &rep, &value))
- X keyspec = (char *) value.addr;
- X else if (mask & d->flags)
- X keyspec = d->dflt_binding;
- X else
- X continue;
- X }
- X nsyms = parseKeySpec(dpy, keyspec, syms);
- X for (i=0; i<nsyms; ++i) {
- X for (j=0; j<keytblsize; ++j) {
- X if (KbdMap[j] == syms[i].sym) {
- X AddKeyBinding(j/KeySymsPerKeyCode+MinKeyCode, syms[i].mod, d);
- X j += KeySymsPerKeyCode - (j % KeySymsPerKeyCode) - 1;
- X }
- X }
- X }
- X }
- X}
- X
- X
- X/*
- X * Issue or release passive grabs for the necessary keys on this particular
- X * root window. Run through the binding table and un/grab the key-modifier
- X * combination itself, and also combined with the Lock and NumLock (if any)
- X * modifier. There thus may be up to four actual grabs per key binding.
- X */
- Xstatic void
- XgrabRootKeys(dpy, root, grab)
- X Display *dpy;
- X Window root;
- X Bool grab; /* True = grab, False = release */
- X{
- X KeyBinding *k;
- X unsigned int NumLockMask =
- X FindModifierMask(XKeysymToKeycode(dpy, XK_Num_Lock));
- X for (k=KeyBindingTable; k < KeyBindingTable+bindingTableCount; ++k) {
- X if (k->desc->function != NULLFUNC) {
- X if (grab) {
- X XGrabKey(dpy, k->keycode, k->modstate,
- X root, False, GrabModeAsync, GrabModeSync);
- X XGrabKey(dpy, k->keycode, k->modstate | LockMask,
- X root, False, GrabModeAsync, GrabModeSync);
- X } else {
- X XUngrabKey(dpy, k->keycode, k->modstate, root);
- X XUngrabKey(dpy, k->keycode, k->modstate|LockMask, root);
- X }
- X if (NumLockMask != 0) {
- X if (grab) {
- X XGrabKey(dpy, k->keycode, k->modstate | NumLockMask,
- X root, False, GrabModeAsync, GrabModeSync);
- X XGrabKey(dpy, k->keycode,
- X k->modstate | NumLockMask | LockMask,
- X root, False, GrabModeAsync, GrabModeSync);
- X } else {
- X XUngrabKey(dpy, k->keycode, k->modstate | NumLockMask,
- X root);
- X XUngrabKey(dpy, k->keycode,
- X k->modstate | NumLockMask | LockMask, root);
- X }
- X }
- X }
- X }
- X}
- X
- X
- X/*
- X * Issue or release passive button grabs on this root window. Like
- X * grabRootKeys, has to deal with Lock and NumLock by issuing up to four
- X * separate grabs. Note: these are synchronous grabs. This relies on the
- X * root event handler to issue an AllowEvents or GrabPointer request.
- X */
- Xstatic void
- XgrabRootButtons(dpy, root, grab)
- X Display *dpy;
- X Window root;
- X Bool grab; /* True = grab, False = release */
- X{
- X unsigned int NumLockMask =
- X FindModifierMask(XKeysymToKeycode(dpy, XK_Num_Lock));
- X unsigned int eventmask =
- X ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
- X
- X if (ModMaskMap[MOD_WMGRAB] != 0) {
- X if (grab) {
- X XGrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB],
- X root, False, eventmask,
- X GrabModeSync, GrabModeSync, None, None);
- X XGrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | LockMask,
- X root, False, eventmask,
- X GrabModeSync, GrabModeSync, None, None);
- X } else {
- X XUngrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB],
- X root);
- X XUngrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | LockMask,
- X root);
- X }
- X
- X if (NumLockMask != 0) {
- X if (grab) {
- X XGrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | NumLockMask,
- X root, False, eventmask,
- X GrabModeSync, GrabModeSync, None, None);
- X XGrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | LockMask | NumLockMask,
- X root, False, eventmask,
- X GrabModeSync, GrabModeSync, None, None);
- X } else {
- X XUngrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | NumLockMask,
- X root);
- X XUngrabButton(dpy, AnyButton,
- X ModMaskMap[MOD_WMGRAB] | LockMask | NumLockMask,
- X root);
- X }
- X }
- X }
- X}
- X
- X
- X/* ===== public functions ================================================= */
- X
- X
- X/*
- X * Given a keyboard event, looks it up in the keyboard binding table. If a
- X * binding is found, returns the semantic action associated with that key. If
- X * no binding is found, returns ACTION_NONE.
- X */
- X
- XSemanticAction
- XFindKeyboardAction(dpy, event)
- X Display *dpy;
- X XEvent *event;
- X{
- X KeyBinding *k;
- X SemanticAction a = ACTION_NONE;
- X unsigned long ignore = ModMaskMap[MOD_IGNORE] | AnyButtonMask;
- X
- X for (k=KeyBindingTable; k < KeyBindingTable+bindingTableCount; ++k) {
- X if (k->keycode == event->xkey.keycode
- X && k->modstate == (event->xkey.state & ~ignore)) {
- X a = k->desc->action;
- X break;
- X }
- X }
- X return a;
- X}
- X
- X/*
- X * Keyboard actions added by olvwmrc are at the end of the list, but they
- X * should take precedence over previous ones. So this function does a
- X * similar search as above but starts at the end.
- X */
- XSemanticAction
- XFindNewKeyboardAction(dpy, event)
- X Display *dpy;
- X XEvent *event;
- X{
- X KeyBinding *k;
- X SemanticAction a = ACTION_NONE;
- X unsigned long ignore = ModMaskMap[MOD_IGNORE] | AnyButtonMask;
- X
- X for (k=KeyBindingTable+bindingTableCount-1; k >= KeyBindingTable; --k) {
- X if (k->keycode == event->xkey.keycode
- X && k->modstate == (event->xkey.state & ~ignore)) {
- X a = k->desc->action;
- X break;
- X }
- X }
- X return a;
- X}
- X
- X
- X/*
- X * Given a keyboard event, looks it up in the keyboard binding table.
- X * If a binding is found, executes the function bound to that key. Returns
- X * True if a function was found and called, otherwise False.
- X */
- XBool
- XExecuteKeyboardFunction(dpy, event)
- X Display *dpy;
- X XEvent *event;
- X{
- X KeyBinding *k;
- X void (*f)() = NULLFUNC;
- X unsigned long ignore = ModMaskMap[MOD_IGNORE] | AnyButtonMask;
- X
- X for (k=KeyBindingTable; k < KeyBindingTable+bindingTableCount; ++k) {
- X if (k->keycode == event->xkey.keycode
- X && k->modstate == (event->xkey.state & ~ignore)
- X && k->desc->function != NULLFUNC) {
- X f = k->desc->function;
- X break;
- X }
- X }
- X
- X /* If the user pressed the STOP key, clear active key. */
- X
- X if (f == NULLFUNC) {
- X if (FindKeyboardAction(dpy, event) == ACTION_STOP)
- X activeKey = NULL;
- X XAllowEvents(dpy, AsyncKeyboard, event->xkey.time);
- X return False;
- X }
- X
- X /* invariant: k points to a valid key binding */
- X
- X#ifdef notdef
- X /*
- X * On the first keypress, stash the active key binding; ignore subsequent
- X * keypresses. Ignore all key releases except the one corresponding to
- X * the active binding.
- X */
- X if (event->type == KeyPress) {
- X if (activeKey == NULL)
- X activeKey = k;
- X else
- X return False;
- X } else { /* KeyRelease */
- X if (k == activeKey)
- X activeKey = NULL;
- X else
- X return False; /* ignore it */
- X }
- X#endif
- X
- X if (suspended && !(k->desc->flags & KD_IMMUNE)) {
- X XAllowEvents(dpy, ReplayKeyboard, event->xkey.time);
- X return True;
- X }
- X
- X if (quotenext) {
- X XAllowEvents(dpy, ReplayKeyboard, event->xkey.time);
- X quotenext = False;
- X return True;
- X }
- X
- X if (event->type == KeyPress)
- X XAllowEvents(dpy, AsyncKeyboard, event->xkey.time);
- X
- X (*f)(dpy, event);
- X return True;
- X}
- X
- X
- X/* ===== Initialization =================================================== */
- X
- X/*
- X * Deal with key grabs on all root windows. If grab = True, grab the keys; if
- X * grab = False, release the keys. Note: the screens and the keyboard binding
- X * information must be initialized prior to calling this function.
- X */
- Xvoid
- XGrabKeys(dpy, grab)
- X Display *dpy;
- X Bool grab;
- X{
- X List *l = ScreenInfoList;
- X ScreenInfo *scr;
- X for (scr = ListEnum(&l); scr != NULL; scr = ListEnum(&l))
- X grabRootKeys(dpy, scr->rootid, grab);
- X}
- X
- X
- X/*
- X * Remove all key grabs, zero out the binding table, and rebuild it from the
- X * resource database. Then, re-establish key grabs.
- X */
- Xvoid
- XRefreshKeyGrabs(dpy)
- X Display *dpy;
- X{
- X GrabKeys(dpy, False);
- X bindingTableCount = 0;
- X establishKeyBindings(dpy);
- X ReInitOlvwmRC(dpy);
- X GrabKeys(dpy, True);
- X}
- X
- X
- X/*
- X * Deal with button grabs on all root windows. If grab = True, grab the
- X * buttons; if grab = False, release them.
- X */
- Xvoid
- XGrabButtons(dpy, grab)
- X Display *dpy;
- X Bool grab;
- X{
- X List *l = ScreenInfoList;
- X ScreenInfo *scr;
- X
- X for (scr = ListEnum(&l); scr != NULL; scr = ListEnum(&l))
- X grabRootButtons(dpy, scr->rootid, grab);
- X}
- X
- X
- X/*
- X * Remove all button grabs, regenerate the modifier mask table, and
- X * re-establish the button grabs.
- X */
- Xvoid
- XRefreshButtonGrabs(dpy)
- X Display *dpy;
- X{
- X GrabButtons(dpy, False);
- X establishModBindings(dpy, OlwmDB);
- X GrabButtons(dpy, True);
- X}
- X
- X
- X/*
- X * Update all bindings from a new resource database. Called whenever the
- X * resource database changes.
- X */
- Xvoid
- XUpdateBindings(dpy, newDB)
- X Display *dpy;
- X XrmDatabase newDB;
- X{
- X KeyDescriptor *d;
- X XrmQuark classlist[4], instlist[4];
- X XrmQuark rep;
- X XrmValue newvalue, oldvalue;
- X Bool regrab = False;
- X static XrmBinding bindings[] =
- X { XrmBindTightly, XrmBindTightly, XrmBindTightly };
- X
- X GrabButtons(dpy, False);
- X establishModBindings(dpy, newDB);
- X GrabButtons(dpy, True);
- X
- X /* run through the KeyDescriptorTable and probe resources */
- X
- X classlist[0] = OpenWinQ;
- X classlist[1] = kbdCmdClassQ;
- X classlist[3] = NULLQUARK;
- X
- X instlist[0] = TopInstanceQ;
- X instlist[1] = kbdCmdInstanceQ;
- X instlist[3] = NULLQUARK;
- X
- X for (d=KeyDescriptorTable; d < KeyDescriptorTable+NUMKEYDESCRIPTORS;
- X ++d) {
- X
- X classlist[2] = instlist[2] = XrmStringToQuark(d->rsrc_name);
- X
- X if (XrmQGetResource(newDB, instlist, classlist, &rep, &newvalue)) {
- X if (XrmQGetResource(OlwmDB, instlist, classlist, &rep, &oldvalue) &&
- X 0 == strcmp((char *) newvalue.addr, (char *) oldvalue.addr))
- X {
- X /* old and new values the same; ignore */
- X continue;
- X }
- X
- X regrab = True;
- X XrmQPutStringResource(&OlwmDB, bindings, instlist,
- X (char *) newvalue.addr);
- X }
- X else {
- X /*
- X * Use olwm binding; see resources.c
- X */
- X classlist[0] = OlwmQ;
- X if (XrmQGetResource(newDB, instlist, classlist, &rep, &newvalue)) {
- X if (XrmQGetResource(OlwmDB, instlist, classlist,
- X &rep, &oldvalue) &&
- X 0 == strcmp((char *) newvalue.addr, (char *) oldvalue.addr))
- X {
- X /* old and new values the same; ignore */
- X classlist[0] = OpenWinQ;
- X continue;
- X }
- X
- X regrab = True;
- X XrmQPutStringResource(&OlwmDB, bindings, instlist,
- X (char *) newvalue.addr);
- X classlist[0] = OpenWinQ;
- X }
- X }
- X }
- X
- X if (regrab)
- X RefreshKeyGrabs(dpy);
- X}
- X
- X
- X/*
- X * Initialize the event handling system, but don't do any key grabbing. This
- X * function is called exactly *once* at startup.
- X */
- Xvoid
- XInitBindings(dpy)
- X Display *dpy;
- X{
- X kbdCmdInstanceQ = XrmStringToQuark("keyboardCommand");
- X kbdCmdClassQ = XrmStringToQuark("KeyboardCommand");
- X
- X modInstanceQ = XrmStringToQuark("modifier");
- X modClassQ = XrmStringToQuark("Modifier");
- X
- X KeyBindingTable = MemCalloc(KEYBINDING_TABLE_SIZE,sizeof(KeyBinding));
- X bindingTableSize = KEYBINDING_TABLE_SIZE;
- X establishKeyBindings(dpy);
- X establishModBindings(dpy, OlwmDB);
- X}
- END_OF_FILE
- if test 38223 -ne `wc -c <'evbind.c'`; then
- echo shar: \"'evbind.c'\" unpacked with wrong size!
- fi
- # end of 'evbind.c'
- fi
- if test -f 'winpane.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'winpane.c'\"
- else
- echo shar: Extracting \"'winpane.c'\" \(12706 characters\)
- sed "s/^X//" >'winpane.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1989, 1990 Sun Microsystems, Inc. Sun design patents
- X * pending in the U.S. and foreign countries. See LEGAL_NOTICE
- X * file for terms of the license.
- X */
- X
- X#ident "@(#)winpane.c 1.1 olvwm version 1/3/92"
- X
- X/*
- X * Based on
- X#ident "@(#)winpane.c 26.14 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 AtomChangeState;
- Xextern Atom AtomColorMapWindows;
- Xextern Atom AtomOlwmTimestamp;
- Xextern Window NoFocusWin;
- Xextern void ColormapChange();
- X
- X/***************************************************************************
- X* private data
- X***************************************************************************/
- X
- X/* border width for reparented windows */
- X#define NORMAL_BORDERWIDTH 0
- X
- Xstatic ClassPane classPane;
- X
- X/***************************************************************************
- X* private functions
- X***************************************************************************/
- X
- X/*
- X * eventEnterLeaveNotify - The pointer has entered or left the window
- X */
- Xstatic int
- XeventEnterLeaveNotify(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPane *winInfo;
- X{
- X if (event->xany.type == EnterNotify)
- X ColorWindowCrossing(dpy, event, winInfo);
- X}
- X
- X/*
- X * eventColormapNotify
- X *
- X * Handle changes to this window's colormap attribute.
- X */
- Xstatic int
- XeventColormapNotify(dpy, event, winInfo)
- X Display *dpy;
- X XEvent *event;
- X WinPane *winInfo;
- X{
- X ColormapChange(dpy, event, (WinGeneric *)winInfo);
- X}
- X
- X/*
- X * eventUnmapNotify - the client is transitioning to withrdrawn
- X */
- Xstatic int
- XeventUnmapNotify(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPane *winInfo;
- X{
- X if (winInfo->pcore.pendingUnmaps > 0)
- X {
- X --winInfo->pcore.pendingUnmaps;
- X }
- X else
- X {
- X /* Mark current state */
- X StateWithdrawn(winInfo->core.client);
- X }
- X}
- X
- X
- X/*
- X * eventDestroyNotify - the pane window has disappeared
- X * This function can get called either during new state processing,
- X * or while app is iconic
- X */
- Xstatic int
- XeventDestroyNotify(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPane *winInfo;
- X{
- X StateWithdrawn(winInfo->core.client);
- X}
- X
- X
- X/*
- X * eventPropertyNotify - handle client messages, in particular iconic requests
- X */
- Xstatic int
- XeventPropertyNotify(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPane *winInfo;
- X{
- X ClientDistributeProperty(winInfo->core.client,event);
- X}
- X
- X/*
- X * eventClientMessage - handle client messages, in particular iconic requests
- X */
- Xstatic int
- XeventClientMessage(dpy, event, winInfo)
- XDisplay *dpy;
- XXEvent *event;
- XWinPane *winInfo;
- X{
- X Client *cli = winInfo->core.client;
- X
- X if (event->xclient.message_type == AtomChangeState)
- X {
- X if (event->xclient.data.l[0] == IconicState)
- X StateNormIcon(cli);
- X }
- X}
- X
- X
- X/*
- X * eventExtension - handle extension events
- X */
- Xstatic int
- XeventExtension(dpy, event, winInfo)
- X Display *dpy;
- X XEvent *event;
- X WinPane *winInfo;
- X{
- X#ifdef SHAPE
- X XShapeEvent *se;
- X Client *cli;
- X
- X if (event->xany.type == ShapeEventBase) {
- X /* it's a ShapeNotify event */
- X se = (XShapeEvent *) event;
- X if (se->kind != ShapeBounding)
- X return;
- X cli = winInfo->core.client;
- X
- X FrameUpdateShape(cli, cli->framewin);
- X }
- X#endif /* SHAPE */
- X}
- X
- X
- X/*
- X * drawPane -- draw the pane window
- X */
- X/*ARGSUSED*/ /* dpy arg will be used when multiple Displays supported */
- Xstatic int
- XdrawPane(dpy, winInfo)
- XDisplay *dpy;
- XWinGeneric *winInfo;
- X{
- X}
- X
- X
- X/*
- X * focusPane -- handle focus change
- X */
- Xstatic int
- XfocusPane(dpy, winInfo, focus)
- XDisplay *dpy;
- XWinGeneric *winInfo;
- XBool focus;
- X{
- X}
- X
- X/*
- X * DestroyPane -- destroy the pane window resources and free any allocated
- X * data.
- X */
- Xstatic int
- XdestroyPane(dpy, winInfo)
- XDisplay *dpy;
- XWinGeneric *winInfo;
- X{
- X /* free our data and throw away window */
- X WIUninstallInfo(winInfo->core.self);
- X MemFree(winInfo);
- X}
- X
- X/*
- X * setconfigPane -- change configuration of pane window
- X */
- X/*ARGSUSED*/ /* dpy arg will be used when multiple Displays supported */
- Xstatic int
- XsetconfigPane(dpy, winInfo)
- XDisplay *dpy;
- XWinPane *winInfo;
- X{
- X XConfigureEvent ce;
- X XWindowChanges xwc;
- X
- X if (winInfo->core.dirtyconfig)
- X {
- X xwc.x = winInfo->core.x;
- X xwc.y = winInfo->core.y;
- X xwc.width = winInfo->core.width;
- X xwc.height = winInfo->core.height;
- X ConfigureWindow(dpy, winInfo,
- X winInfo->core.dirtyconfig, &xwc);
- X winInfo->core.dirtyconfig &= ~(CWX|CWY|CWWidth|CWHeight);
- X }
- X
- X /* send synthetic configure notify in root coordinates */
- X ce.type = ConfigureNotify;
- X ce.serial = 0L;
- X ce.event = winInfo->core.self;
- X ce.window = winInfo->core.self;
- X WinRootPos(winInfo,&ce.x,&ce.y);
- X ce.x -= winInfo->pcore.oldBorderWidth;
- X ce.y -= winInfo->pcore.oldBorderWidth;
- X ce.width = winInfo->core.width;
- X ce.height = winInfo->core.height;
- X ce.border_width = winInfo->pcore.oldBorderWidth;
- X ce.above = None;
- X ce.override_redirect = False;
- X
- X XSendEvent(dpy, winInfo->core.self, False,
- X StructureNotifyMask, (XEvent *)&ce);
- X}
- X
- X
- X/*
- X * newconfigPane - compute a new configuration given an event
- X * Note: this function must *always* be called with a configure request
- X * event.
- X */
- Xstatic int
- XnewconfigPane(win, pxcre)
- XWinPane *win;
- XXConfigureRequestEvent *pxcre;
- X{
- X int oldWidth, oldHeight;
- X Client *cli = win->core.client;
- X int oldX, oldY;
- X WinPaneFrame *winFrame = cli->framewin;
- X void FrameMoveRelative();
- X int dwidth, dheight;
- X
- X if (pxcre == NULL)
- X return win->core.dirtyconfig;
- X
- X WinRootPos(win, &oldX, &oldY);
- X oldWidth = win->core.width;
- X oldHeight = win->core.height;
- X
- X if ((pxcre->value_mask & CWHeight) && (pxcre->height != oldHeight))
- X {
- X win->core.height = pxcre->height;
- X win->core.dirtyconfig |= CWHeight;
- X }
- X
- X if ((pxcre->value_mask & CWWidth) && (pxcre->width != oldWidth))
- X {
- X win->core.width = pxcre->width;
- X win->core.dirtyconfig |= CWWidth;
- X }
- X
- X if (pxcre->value_mask & CWBorderWidth)
- X {
- X win->pcore.oldBorderWidth = pxcre->border_width;
- X }
- X
- X if (pxcre->value_mask & (CWX | CWY))
- X {
- X FrameSetPosAbsolute(winFrame,
- X (pxcre->value_mask & CWX)?(pxcre->x):oldX,
- X (pxcre->value_mask & CWY)?(pxcre->y):oldY);
- X }
- X else
- X {
- X dwidth = oldWidth - win->core.width;
- X dheight = oldHeight - win->core.height;
- X if ((dwidth != 0) || (dheight!=0))
- X {
- X switch (cli->normHints->win_gravity)
- X {
- X case NorthWestGravity:
- X break;
- X case NorthGravity:
- X FrameMoveRelative(winFrame,dwidth/2,0);
- X break;
- X case NorthEastGravity:
- X FrameMoveRelative(winFrame,dwidth,0);
- X break;
- X case WestGravity:
- X FrameMoveRelative(winFrame,0,dheight/2);
- X break;
- X case CenterGravity:
- X FrameMoveRelative(winFrame,dwidth/2,dheight/2);
- X break;
- X case EastGravity:
- X FrameMoveRelative(winFrame,dwidth,dheight/2);
- X break;
- X case SouthWestGravity:
- X FrameMoveRelative(winFrame,0,dheight);
- X break;
- X case SouthGravity:
- X FrameMoveRelative(winFrame,dwidth/2,dheight);
- X break;
- X case SouthEastGravity:
- X FrameMoveRelative(winFrame,dwidth,dheight);
- X break;
- X }
- X }
- X }
- X
- X
- X if (pxcre->value_mask & (CWStackMode | CWSibling))
- X {
- X GFrameSetStack(winFrame, pxcre->value_mask, pxcre->detail, pxcre->above);
- X }
- X
- X return win->core.dirtyconfig;
- X}
- X
- X/*
- X * newposPane - move to a given position (relative to parent)
- X */
- Xstatic int
- XnewposPane(win,x,y)
- XWinPane *win;
- Xint x, y;
- X{
- X if (win->core.x != x)
- X {
- X win->core.x = x;
- X win->core.dirtyconfig |= CWX;
- X }
- X
- X if (win->core.y != y)
- X {
- X win->core.y = y;
- X win->core.dirtyconfig |= CWY;
- X }
- X
- X return win->core.dirtyconfig;
- X}
- X
- X/*
- X * setsizePane - set the pane to a particular size, and initiate a reconfigure
- X */
- Xstatic int
- XsetsizePane(win,w,h)
- XWinPane *win;
- Xint w, h;
- X{
- X if (win->core.width != w)
- X {
- X win->core.width = w;
- X win->core.dirtyconfig |= CWWidth;
- X }
- X
- X if (win->core.height != h)
- X {
- X win->core.height = h;
- X win->core.dirtyconfig |= CWHeight;
- X }
- X}
- X
- X/***************************************************************************
- X* global functions
- X***************************************************************************/
- X
- X/*
- X * MakePane -- create the pane window. Return a WinGeneric structure.
- X */
- XWinPane *
- XMakePane(cli,par,win,paneattrs)
- XClient *cli;
- XWinGeneric *par;
- XWindow win;
- XXWindowAttributes *paneattrs;
- X{
- X WinPane *w;
- X XSetWindowAttributes attributes;
- X long mask;
- X WinColormap *colorwin;
- X
- X /* this window may already be mentioned as a colourmap window.
- X * grab its colourmap window structure, and unhook it from the
- X * event dispatching table so we can register a new structure
- X * for the window. We will call another function at the end
- X * of pane processing to re-establish the relation between this
- X * window and other structures in the system.
- X */
- X colorwin = ColormapUnhook(win);
- X
- X /* create the associated structure */
- X w = MemNew(WinPane);
- X w->core.self = win;
- X w->class = &classPane;
- X w->core.kind = WIN_PANE;
- X WinAddChild(par,w);
- X w->core.children = NULL;
- X w->core.client = cli;
- X w->core.x = 0; /* gets fixed up later */
- X w->core.y = 0; /* gets fixed up later */
- X w->core.width = paneattrs->width;
- X w->core.height = paneattrs->height;
- X w->core.colormap = paneattrs->colormap;
- X w->core.dirtyconfig = CWX|CWY|CWWidth|CWHeight;
- X w->core.exposures = NULL;
- X w->pcore.oldBorderWidth = paneattrs->border_width;
- X w->pcore.oldSaveUnder = paneattrs->save_under;
- X w->core.helpstring = (char *)NULL; /* no help */
- X
- X cli->framewin->fcore.panewin = (WinGenericPane *)w;
- X
- X /* register the window */
- X WIInstallInfo(w);
- X
- X /* Put the window in the save set so it doesn't go away */
- X XChangeSaveSet(cli->dpy,win,SetModeInsert);
- X
- X /*
- X * Since the pane is reparented, save-unders are not useful.
- X * In the code above the save-under attribute is propogated to
- X * the frame, so it is safe to remove it here. But don't do this for
- X * InputOnly windows.
- X */
- X if (paneattrs->class == InputOutput) {
- X attributes.save_under = False;
- X XChangeWindowAttributes(cli->dpy, win,
- X (unsigned long) CWSaveUnder, &attributes);
- X
- X /*
- X * Change the border width if necessary. The border width of
- X * InputOnly windows is zero by definition.
- X */
- X if (paneattrs->border_width != NORMAL_BORDERWIDTH)
- X XSetWindowBorderWidth(cli->dpy, win, NORMAL_BORDERWIDTH);
- X }
- X
- X /*
- X * Focus Lenience. Be lenient about enforcing the requirement that
- X * clients set the input hint in WM_HINTS before they can get keyboard
- X * input. If this flag is set, and if the focus mode is NoInput, then
- X * force the mode to be passive. This way, if a client either fails
- X * to set the WM_HINTS.input field, or fails to write WM_HINTS at all,
- X * it can still get keyboard input.
- X *
- X * REMIND This kind of flag should be implemented on a
- X * client-by-client basis, not on a global basis.
- X */
- X if (GRV.FocusLenience && cli->focusMode == NoInput ) {
- X cli->focusMode = Passive;
- X }
- X
- X /* Reparent the pane */
- X XReparentWindow(cli->dpy, win, par->core.self,
- X w->core.x, w->core.y);
- X
- X /* we may have saved colourmap manipulation information at
- X * the beginning. Re-establish the connection between this window
- X * and other structures based on the old structure.
- X */
- X ColormapTransmogrify(colorwin, w);
- X
- X return w;
- X}
- X
- X/*
- X * PaneInit -- initialise the Pane class function vector
- X */
- Xvoid
- XPaneInit(dpy)
- XDisplay *dpy;
- X{
- X classPane.core.kind = WIN_PANE;
- X classPane.core.xevents[EnterNotify] = eventEnterLeaveNotify;
- X classPane.core.xevents[LeaveNotify] = eventEnterLeaveNotify;
- X classPane.core.xevents[ColormapNotify] = eventColormapNotify;
- X classPane.core.xevents[UnmapNotify] = eventUnmapNotify;
- X classPane.core.xevents[DestroyNotify] = eventDestroyNotify;
- X classPane.core.xevents[PropertyNotify] = eventPropertyNotify;
- X classPane.core.xevents[ClientMessage] = eventClientMessage;
- X classPane.core.extEventHdlr = eventExtension;
- X classPane.core.focusfunc = focusPane;
- X classPane.core.drawfunc = NULL;
- X classPane.core.destroyfunc = destroyPane;
- X classPane.core.selectfunc = NULL;
- X classPane.core.newconfigfunc = newconfigPane;
- X classPane.core.newposfunc = newposPane;
- X classPane.core.setconfigfunc = setconfigPane;
- X classPane.core.createcallback = NULL;
- X classPane.core.heightfunc = NULL;
- X classPane.core.widthfunc = NULL;
- X classPane.pcore.setsizefunc = setsizePane;
- X}
- END_OF_FILE
- if test 12706 -ne `wc -c <'winpane.c'`; then
- echo shar: \"'winpane.c'\" unpacked with wrong size!
- fi
- # end of 'winpane.c'
- fi
- echo shar: End of archive 6 \(of 21\).
- cp /dev/null ark6isdone
- 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
-