diff --git a/patch/keymodes.c b/patch/keymodes.c new file mode 100644 index 0000000..45af3c5 --- /dev/null +++ b/patch/keymodes.c @@ -0,0 +1,143 @@ +/* function implementations */ +void +clearcmd(const Arg *arg) +{ + unsigned int i; + + for (i = 0; i < LENGTH(cmdkeysym); i++) { + cmdkeysym[i] = 0; + cmdmod[i] = 0; + } +} + +void +grabkeys(void) +{ + if (keymode == INSERTMODE) { + grabdefkeys(); + } else if (keymode == COMMANDMODE) { + XUngrabKey(dpy, AnyKey, AnyModifier, root); + XGrabKey(dpy, AnyKey, AnyModifier, root, + True, GrabModeAsync, GrabModeAsync); + } +} + +int +isprotodel(Client *c) +{ + int n; + Atom *protocols; + int ret = 0; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!ret && n--) + ret = protocols[n] == wmatom[WMDelete]; + XFree(protocols); + } + return ret; +} + + +void +keypress(XEvent *e) +{ + unsigned int i, j; + Arg a = {0}; + Bool ismatch = False, maybematch = False; + KeySym keysym; + XKeyEvent *ev; + + if (keymode == INSERTMODE) + keydefpress(e); + else if (keymode == COMMANDMODE) { + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + if (keysym < XK_Shift_L || keysym > XK_Hyper_R) { + for (i = 0; i < LENGTH(cmdkeys); i++) + if (keysym == cmdkeys[i].keysym + && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state) + && cmdkeys[i].func) { + cmdkeys[i].func(&(cmdkeys[i].arg)); + ismatch = True; + break; + } + if (!ismatch) { + for (j = 0; j < LENGTH(cmdkeysym); j++) + if (cmdkeysym[j] == 0) { + cmdkeysym[j] = keysym; + cmdmod[j] = ev->state; + break; + } + for (i = 0; i < LENGTH(commands); i++) { + for (j = 0; j < LENGTH(cmdkeysym); j++) { + if (cmdkeysym[j] == commands[i].keysym[j] + && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j])) + ismatch = True; + else if (cmdkeysym[j] == 0 + && cmdmod[j] == 0) { + ismatch = False; + maybematch = True; + break; + } else { + ismatch = False; + break; + } + } + if (ismatch) { + if (commands[i].func) + commands[i].func(&(commands[i].arg)); + clearcmd(&a); + break; + } + + } + if (!maybematch) + clearcmd(&a); + } + } + } +} + +void +onlyclient(const Arg *arg) +{ + Client *c; + XEvent ev; + + if (!selmon->sel) + return; + for (c = selmon->clients; c; c = c->next) { + if (c != selmon->sel && ISVISIBLE(c)) { + if (isprotodel(c)) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = wmatom[WMDelete]; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + else { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, c->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + } + } +} + +void +setkeymode(const Arg *arg) +{ + Arg a = {0}; + + if (!arg) + return; + keymode = arg->ui; + clearcmd(&a); + grabkeys(); +} \ No newline at end of file diff --git a/patch/keymodes.h b/patch/keymodes.h new file mode 100644 index 0000000..3a13163 --- /dev/null +++ b/patch/keymodes.h @@ -0,0 +1,21 @@ +#define COMMANDMODE 1 +#define INSERTMODE 2 + +typedef struct { + unsigned int mod[4]; + KeySym keysym[4]; + void (*func)(const Arg *); + const Arg arg; +} Command; + +static void clearcmd(const Arg *arg); +static void grabkeys(void); +static int isprotodel(Client *c); +static void keypress(XEvent *e); +static void onlyclient(const Arg *arg); +static void setkeymode(const Arg *arg); + +/* variables */ +static unsigned int cmdmod[4]; +static unsigned int keymode = INSERTMODE; +static KeySym cmdkeysym[4]; \ No newline at end of file