wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 8ef8918f0989d37cabf57a40ce16c68d4c5e79bc
parent b5ef87ab192daa3c8b2d04f2587e189ad83c1647
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Fri, 10 Feb 2006 21:05:17 +0100

added kb.c, sorry


Diffstat:
cmd/wm/kb.c | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cmd/wm/spawn.c | 27+++++++++++++++++++++++++++
2 files changed, 293 insertions(+), 0 deletions(-)

diff --git a/cmd/wm/kb.c b/cmd/wm/kb.c @@ -0,0 +1,266 @@ +/* + * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + * See LICENSE file for license details. + */ + +#include <string.h> +#include <stdlib.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> + +#include "wm.h" + +#define NUM_MASKS 8 + +void +init_lock_modifiers() +{ + XModifierKeymap *modmap; + KeyCode num_lock; + static int masks[NUM_MASKS] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask + }; + int i; + + num_lock_mask = 0; + modmap = XGetModifierMapping(dpy); + num_lock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock")); + + if(modmap && modmap->max_keypermod > 0) { + int max = NUM_MASKS * modmap->max_keypermod; + for(i = 0; i < max; i++) { + if(num_lock && (modmap->modifiermap[i] == num_lock)) { + num_lock_mask = masks[i / modmap->max_keypermod]; + } + } + } + XFreeModifiermap(modmap); + + valid_mask = 255 & ~(num_lock_mask | LockMask); +} + +static unsigned long +blitz_strtomod(char *val) +{ + unsigned long mod = 0; + if (strstr(val, "Shift")) + mod |= ShiftMask; + if (strstr(val, "Control")) + mod |= ControlMask; + if (strstr(val, "Mod1") || strstr(val, "Alt")) + mod |= Mod1Mask; + if (strstr(val, "Mod2")) + mod |= Mod2Mask; + if (strstr(val, "Mod3")) + mod |= Mod3Mask; + if (strstr(val, "Mod4")) + mod |= Mod4Mask; + if (strstr(val, "Mod5")) + mod |= Mod5Mask; + return mod; +} + +void +grab_key(Key *k) +{ + XGrabKey(dpy, k->key, k->mod, root, + True, GrabModeAsync, GrabModeAsync); + if(num_lock_mask) { + XGrabKey(dpy, k->key, k->mod | num_lock_mask, root, + True, GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root, + True, GrabModeAsync, GrabModeAsync); + } + XSync(dpy, False); +} + +void +ungrab_key(Key *k) +{ + XUngrabKey(dpy, k->key, k->mod, root); + if(num_lock_mask) { + XUngrabKey(dpy, k->key, k->mod | num_lock_mask, root); + XUngrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root); + } + XSync(dpy, False); +} + +Key * +create_key(char *name) +{ + char buf[128]; + char *seq[8]; + char *kstr; + size_t i, toks; + static unsigned short id = 1; + Key *k = 0, *r = 0; + + if((k = name_to_key(name))) + return k; + + cext_strlcpy(buf, name, sizeof(buf)); + toks = cext_tokenize(seq, 8, buf, ','); + + for(i = 0; i < toks; i++) { + if(!k) + r = k = cext_emallocz(sizeof(Key)); + else { + k->next = cext_emallocz(sizeof(Key)); + k = k->next; + } + cext_strlcpy(k->name, name, sizeof(k->name)); + kstr = strrchr(seq[i], '-'); + if(kstr) + kstr++; + else + kstr = seq[i]; + k->key = XKeysymToKeycode(dpy, XStringToKeysym(kstr)); + k->mod = blitz_strtomod(seq[i]); + } + r->id = id++; + key = (Key **)cext_array_attach((void **)key, r, sizeof(Key *), &keysz); + nkey++; + return r; +} + +void +destroy_key(Key *k) +{ + cext_array_detach((void **)key, k, &keysz); + nkey--; + if(k->next) + destroy_key(k->next); + free(k); +} + +static void +next_keystroke(unsigned long *mod, KeyCode *key) +{ + XEvent e; + KeySym sym; + *mod = 0; + do { + XMaskEvent(dpy, KeyPressMask, &e); + *mod |= e.xkey.state & valid_mask; + *key = (KeyCode) e.xkey.keycode; + sym = XKeycodeToKeysym(dpy, e.xkey.keycode, 0); + } while(IsModifierKey(sym)); +} + +static void +emulate_key_press(unsigned long mod, KeyCode key) +{ + XEvent e; + Window client_win; + int revert; + + XGetInputFocus(dpy, &client_win, &revert); + + e.xkey.type = KeyPress; + e.xkey.time = CurrentTime; + e.xkey.window = client_win; + e.xkey.display = dpy; + e.xkey.state = mod; + e.xkey.keycode = key; + XSendEvent(dpy, client_win, True, KeyPressMask, &e); + e.xkey.type = KeyRelease; + XSendEvent(dpy, client_win, True, KeyReleaseMask, &e); + XSync(dpy, False); +} + +static Key ** +match_keys(Key **t, size_t n, unsigned long mod, KeyCode keycode, Bool next, size_t *nres) +{ + Key **result = nil; + size_t ressz = 0; + size_t i = 0; + *nres = 0; + for(i = 0; i < n; i++) { + Key *k = next ? t[i]->next : t[i]; + if(k && (k->mod == mod) && (k->key == keycode)) { + result = (Key **)cext_array_attach((void **)result, k, sizeof(Key *), &ressz); + (*nres)++; + } + } + return result; +} + +static void +handle_key_seq(Window w, Key **done, size_t ndone) +{ + unsigned long mod; + KeyCode key; + Key **found = nil; + size_t nfound = 0; + char buf[128]; + + next_keystroke(&mod, &key); + + found = match_keys(done, ndone, mod, key, True, &nfound); + if((done[0]->mod == mod) && (done[0]->key == key)) + emulate_key_press(mod, key); /* double key */ + else { + switch(nfound) { + case 0: + XBell(dpy, 0); + return; /* grabbed but not found */ + case 1: + if(!found[0]->next) { + snprintf(buf, sizeof(buf), "K %s\n", found[0]->name); + do_pend_fcall(buf); + break; + } + default: + handle_key_seq(w, found, nfound); + break; + } + } + free(found); +} + +void +handle_key(Window w, unsigned long mod, KeyCode keycode) +{ + size_t nfound; + char buf[128]; + Key **found = match_keys(key, nkey, mod, keycode, False, &nfound); + switch(nfound) { + case 0: + XBell(dpy, 0); + return; /* grabbed but not found */ + case 1: + if(!found[0]->next) { + snprintf(buf, sizeof(buf), "K %s\n", found[0]->name); + do_pend_fcall(buf); + break; + } + default: + XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime); + handle_key_seq(w, found, nfound); + XUngrabKeyboard(dpy, CurrentTime); + XSync(dpy, False); + break; + } + free(found); +} + +Key * +name_to_key(char *name) +{ + size_t i; + for(i = 0; i < nkey; i++) + if(!strncmp(key[i]->name, name, sizeof(key[i]->name))) + return key[i]; + return nil; +} + +int +kid_to_index(unsigned short id) +{ + int i; + for(i = 0; i < nkey; i++) + if(key[i]->id == id) + return i; + return -1; +} diff --git a/cmd/wm/spawn.c b/cmd/wm/spawn.c @@ -0,0 +1,27 @@ +/* + * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + * See LICENSE file for license details. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "wm.h" + +void +spawn(char *cmd) +{ + if(fork() == 0) { + if(fork() == 0) { + setsid(); + close(ConnectionNumber(dpy)); + execlp("rc", "rc", "-c", cmd, (char *) 0); + perror("failed"); + exit(1); + } + exit(0); + } + wait(0); +}