From: Jason Woofenden Date: Sat, 18 Apr 2015 00:40:42 +0000 (-0400) Subject: buffer key presses between spawn and window open X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=commitdiff_plain;h=9e9918ad967382660aea6bd7e9634f5995de04e0 buffer key presses between spawn and window open --- diff --git a/dwm.c b/dwm.c index 5e9b184..dc9f318 100644 --- a/dwm.c +++ b/dwm.c @@ -177,6 +177,7 @@ static long getstate(Window w); static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, Bool focused); static void grabkeys(void); +static void grab_typing_keys(void); static void incnmaster(const Arg *arg); static void keypress(XEvent *e); static void killclient(const Arg *arg); @@ -200,6 +201,7 @@ static void restack(Monitor *m); static void run(void); static void scan(void); static Bool sendevent(Client *c, Atom proto); +static void send_keycode(KeyCode key); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); @@ -240,6 +242,9 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); /* variables */ +static KeyCode key_buffer[100]; +static int key_buffer_len = 0; +static Bool key_buffering = False; static const char broken[] = "broken"; static char stext[256]; static int screen; @@ -1056,6 +1061,32 @@ grabkeys(void) { for(j = 0; j < LENGTH(modifiers); j++) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, True, GrabModeAsync, GrabModeAsync); + if(key_buffering) + grab_typing_keys(); + } +} + +void +grab_typing_keys(void) { + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeySym typing_keys[] = { + XK_space, XK_Return, XK_period, XK_slash, XK_minus, XK_apostrophe, + XK_A, XK_B, XK_C, XK_D, XK_E, XK_F, XK_G, XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, XK_P, XK_Q, XK_R, XK_S, XK_T, XK_U, XK_V, + XK_W, XK_X, XK_Y, XK_Z, XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, + XK_7, XK_8, XK_9, + }; + + KeyCode code; + + for(i = 0; i < LENGTH(typing_keys); i++) + if((code = XKeysymToKeycode(dpy, typing_keys[i]))) + for(j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); } } @@ -1077,18 +1108,60 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { #endif /* XINERAMA */ void +send_keycode(KeyCode key) { + XKeyEvent event; + if(!selmon->sel) { + return; + } + event.display = dpy; + event.root = root; + event.window = selmon->sel->win; + event.subwindow = None; + event.same_screen = True; + event.x = 1; + event.y = 1; + event.x_root = 1; + event.y_root = 1; + event.time = CurrentTime; + event.state = 0; // modifiers + event.keycode = key; + event.type = KeyPress; + XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event); + event.type = KeyRelease; + XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event); +} + +void keypress(XEvent *e) { unsigned int i; KeySym keysym; XKeyEvent *ev; + Bool called = False; ev = &e->xkey; keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) - && keys[i].func) + && keys[i].func) { keys[i].func(&(keys[i].arg)); + called = True; + } + if(!called) { + if(key_buffering) { + if(key_buffer_len == LENGTH(key_buffer)) { + // buffer full, bail + key_buffer_len = 0; + key_buffering = False; + grabkeys(); // stop grabbing typing keys + } else { + key_buffer[key_buffer_len] = (KeyCode)ev->keycode; + key_buffer_len += 1; + } + } else { + send_keycode(ev->keycode); + } + } } void @@ -1111,6 +1184,7 @@ manage(Window w, XWindowAttributes *wa) { Client *c, *t = NULL; Window trans = None; XWindowChanges wc; + int i; if(!(c = calloc(1, sizeof(Client)))) die("fatal: could not malloc() %u bytes\n", sizeof(Client)); @@ -1167,6 +1241,16 @@ manage(Window w, XWindowAttributes *wa) { arrange(c->mon); XMapWindow(dpy, c->win); focus(c); + if(key_buffering) { + key_buffering = False; + grabkeys(); // stop grabbing typing keys + if(key_buffer_len > 0) { + for(i = 0; i < key_buffer_len; ++i) { + send_keycode(key_buffer[i]); + } + } + key_buffer_len = 0; + } } void @@ -1725,6 +1809,9 @@ spawn(const Arg *arg) { } if(arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; + key_buffering = True; + key_buffer_len = 0; + grab_typing_keys(); if(fork() == 0) { if(dpy) close(ConnectionNumber(dpy));