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);
+}