From a041d9898e6d699bd8c0c25482ec574feb03c547 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Sat, 29 May 2021 12:54:47 +0200 Subject: First commit This is the original state of the released tarball for JWM 1.8, which will serve as my starting point for further modifications. --- src/key.c | 452 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 src/key.c (limited to 'src/key.c') diff --git a/src/key.c b/src/key.c new file mode 100644 index 0000000..b6e9ee6 --- /dev/null +++ b/src/key.c @@ -0,0 +1,452 @@ +/*************************************************************************** + * Key input functions. + * Copyright (C) 2004 Joe Wingbermuehle + ***************************************************************************/ + +#include "jwm.h" +#include "key.h" +#include "main.h" +#include "client.h" +#include "root.h" +#include "error.h" +#include "tray.h" +#include "misc.h" + +typedef enum { + MASK_NONE = 0, + MASK_ALT = 1, + MASK_CTRL = 2, + MASK_SHIFT = 4, + MASK_HYPER = 8, + MASK_META = 16, + MASK_SUPER = 32 +} MaskType; + +typedef struct KeyNode { + + /* These are filled in when the configuration file is parsed */ + int key; + unsigned int mask; + KeySym symbol; + char *command; + struct KeyNode *next; + + /* This is filled in by StartupKeys if it isn't already set. */ + KeyCode code; + + /* This is filled in by StartupKeys. */ + unsigned int state; + +} KeyNode; + +typedef struct LockNode { + KeySym symbol; + unsigned int mask; +} LockNode; + +static XModifierKeymap *modmap; + +static LockNode mods[] = { + { XK_Caps_Lock, 0 }, + { XK_Num_Lock, 0 } +}; + +static KeyNode *bindings; +static unsigned int modifierMask; + +static unsigned int GetModifierMask(KeySym key); +static unsigned int ParseModifierString(const char *str); +static KeySym ParseKeyString(const char *str); +static int ShouldGrab(KeyType key); +static void GrabKey(KeyNode *np); + +/*************************************************************************** + ***************************************************************************/ +void InitializeKeys() { + + bindings = NULL; + modifierMask = 0; + +} + +/*************************************************************************** + ***************************************************************************/ +void StartupKeys() { + + KeyNode *np; + int x; + + modmap = JXGetModifierMapping(display); + + for(x = 0; x < sizeof(mods) / sizeof(mods[0]); x++) { + mods[x].mask = GetModifierMask(mods[x].symbol); + modifierMask |= mods[x].mask; + } + + for(np = bindings; np; np = np->next) { + + np->state = 0; + if(np->mask & MASK_ALT) { + np->state |= GetModifierMask(XK_Alt_L); + } + if(np->mask & MASK_CTRL) { + np->state |= GetModifierMask(XK_Control_L); + } + if(np->mask & MASK_SHIFT) { + np->state |= GetModifierMask(XK_Shift_L); + } + if(np->mask & MASK_HYPER) { + np->state |= GetModifierMask(XK_Hyper_L); + } + if(np->mask & MASK_META) { + np->state |= GetModifierMask(XK_Meta_L); + } + if(np->mask & MASK_SUPER) { + np->state |= GetModifierMask(XK_Super_L); + } + + if(!np->code) { + np->code = JXKeysymToKeycode(display, np->symbol); + } + + if(ShouldGrab(np->key)) { + GrabKey(np); + } + + } + + JXFreeModifiermap(modmap); + +} + +/*************************************************************************** + ***************************************************************************/ +void ShutdownKeys() { + + ClientNode *np; + int layer; + + for(layer = 0; layer < LAYER_COUNT; layer++) { + for(np = nodes[layer]; np; np = np->next) { + JXUngrabKey(display, AnyKey, AnyModifier, np->window); + } + } + + JXUngrabKey(display, AnyKey, AnyModifier, rootWindow); + +} + +/*************************************************************************** + ***************************************************************************/ +void DestroyKeys() { + + KeyNode *np; + + while(bindings) { + np = bindings->next; + if(bindings->command) { + Release(bindings->command); + } + Release(bindings); + bindings = np; + } + +} + +/*************************************************************************** + ***************************************************************************/ +void GrabKey(KeyNode *np) { + + TrayType *tp; + int x; + int index, maxIndex; + unsigned int mask; + + maxIndex = 1 << (sizeof(mods) / sizeof(mods[0])); + for(index = 0; index < maxIndex; index++) { + + mask = 0; + for(x = 0; x < sizeof(mods) / sizeof(mods[0]); x++) { + if(index & (1 << x)) { + mask |= mods[x].mask; + } + } + + mask |= np->state; + JXGrabKey(display, np->code, mask, + rootWindow, True, GrabModeAsync, GrabModeAsync); + for(tp = GetTrays(); tp; tp = tp->next) { + JXGrabKey(display, np->code, mask, + tp->window, True, GrabModeAsync, GrabModeAsync); + } + + } + +} + +/*************************************************************************** + ***************************************************************************/ +KeyType GetKey(const XKeyEvent *event) { + + KeyNode *np; + unsigned int state; + + state = event->state & ~modifierMask; + for(np = bindings; np; np = np->next) { + if(np->state == state && np->code == event->keycode) { + return np->key; + } + } + + return KEY_NONE; + +} + +/*************************************************************************** + ***************************************************************************/ +void RunKeyCommand(const XKeyEvent *event) { + + KeyNode *np; + + for(np = bindings; np; np = np->next) { + if(np->state == event->state && np->code == event->keycode) { + RunCommand(np->command); + return; + } + } + +} + +/*************************************************************************** + ***************************************************************************/ +void ShowKeyMenu(const XKeyEvent *event) { + + KeyNode *np; + int button; + + for(np = bindings; np; np = np->next) { + if(np->state == event->state && np->code == event->keycode) { + button = atoi(np->command); + if(button >= 0 && button <= 9) { + ShowRootMenu(button, 0, 0); + } + return; + } + } + +} + +/*************************************************************************** + ***************************************************************************/ +int ShouldGrab(KeyType key) { + switch(key & 0xFF) { + case KEY_NEXT: + case KEY_NEXT_STACKED: + case KEY_CLOSE: + case KEY_MIN: + case KEY_MAX: + case KEY_SHADE: + case KEY_MOVE: + case KEY_RESIZE: + case KEY_ROOT: + case KEY_WIN: + case KEY_DESKTOP: + case KEY_EXEC: + case KEY_RESTART: + case KEY_EXIT: + return 1; + default: + return 0; + } +} + +/*************************************************************************** + ***************************************************************************/ +void GrabKeys(ClientNode *np) { + + KeyNode *kp; + + for(kp = bindings; kp; kp = kp->next) { + if(ShouldGrab(kp->key)) { + JXGrabKey(display, kp->code, kp->state, + np->window, True, GrabModeAsync, GrabModeAsync); + } + } + +} + +/*************************************************************************** + ***************************************************************************/ +unsigned int GetModifierMask(KeySym key) { + + KeyCode temp; + int x; + + temp = JXKeysymToKeycode(display, key); + for(x = 0; x < 8 * modmap->max_keypermod; x++) { + if(modmap->modifiermap[x] == temp) { + return 1 << (x / modmap->max_keypermod); + } + } + + Warning("modifier not found for keysym 0x%0x", key); + + return 0; + +} + +/*************************************************************************** + ***************************************************************************/ +unsigned int ParseModifierString(const char *str) { + unsigned int mask; + int x; + + if(!str) { + return MASK_NONE; + } + + mask = MASK_NONE; + for(x = 0; str[x]; x++) { + switch(str[x]) { + case 'A': + mask |= MASK_ALT; + break; + case 'C': + mask |= MASK_CTRL; + break; + case 'S': + mask |= MASK_SHIFT; + break; + case 'H': + mask |= MASK_HYPER; + break; + case 'M': + mask |= MASK_META; + break; + case 'P': + mask |= MASK_SUPER; + break; + default: + Warning("invalid modifier: \"%c\"", str[x]); + break; + } + } + + return mask; + +} + +/*************************************************************************** + ***************************************************************************/ +KeySym ParseKeyString(const char *str) { + + KeySym symbol; + + symbol = JXStringToKeysym(str); + if(symbol == NoSymbol) { + Warning("invalid key symbol: \"%s\"", str); + } + + return symbol; + +} + +/*************************************************************************** + ***************************************************************************/ +void InsertBinding(KeyType key, const char *modifiers, + const char *stroke, const char *code, const char *command) { + + KeyNode *np; + unsigned int mask; + char *temp; + int offset; + KeySym sym; + + mask = ParseModifierString(modifiers); + + if(stroke && strlen(stroke) > 0) { + + for(offset = 0; stroke[offset]; offset++) { + if(stroke[offset] == '#') { + + temp = CopyString(stroke); + + for(temp[offset] = '1'; temp[offset] <= '9'; temp[offset]++) { + + sym = ParseKeyString(temp); + if(sym == NoSymbol) { + Release(temp); + return; + } + + np = Allocate(sizeof(KeyNode)); + np->next = bindings; + bindings = np; + + np->key = key | ((temp[offset] - '1' + 1) << 8); + np->mask = mask; + np->symbol = sym; + np->command = NULL; + np->code = 0; + + } + + Release(temp); + + return; + } + } + + sym = ParseKeyString(stroke); + if(sym == NoSymbol) { + return; + } + + np = Allocate(sizeof(KeyNode)); + np->next = bindings; + bindings = np; + + np->key = key; + np->mask = mask; + np->symbol = sym; + np->command = CopyString(command); + np->code = 0; + + } else if(code && strlen(code) > 0) { + + np = Allocate(sizeof(KeyNode)); + np->next = bindings; + bindings = np; + + np->key = key; + np->mask = mask; + np->symbol = NoSymbol; + np->command = CopyString(command); + np->code = atoi(code); + + } else { + + Warning("neither key nor keycode specified for Key"); + + } + +} + +/*************************************************************************** + ***************************************************************************/ +void ValidateKeys() { + + KeyNode *kp; + int bindex; + + for(kp = bindings; kp; kp = kp->next) { + if((kp->key & 0xFF) == KEY_ROOT && kp->command) { + bindex = atoi(kp->command); + if(!IsRootMenuDefined(bindex)) { + Warning("key binding: root menu %d not defined", bindex); + } + } + } + +} + -- cgit v1.2.3