From 33883da028e2eae2cc5c70b445e0d78434d11ac9 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Tue, 4 Apr 2017 01:28:33 -0400 Subject: [PATCH] cleanup, buffer KeyRelease events too --- dwm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/dwm.c b/dwm.c index aa8a8f5..fa48fb0 100644 --- a/dwm.c +++ b/dwm.c @@ -180,6 +180,7 @@ static void grabbuttons(Client *c, Bool focused); static void grabkeys(void); static void incnmaster(const Arg *arg); static void keypress(XEvent *e); +static void keyrelease(XEvent *e); static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); static void mappingnotify(XEvent *e); @@ -201,7 +202,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, unsigned int state); +static void send_key_event(int type, KeyCode key, unsigned int state); static void sendmon(Client *c, Monitor *m); static void setclientstate(Client *c, long state); static void setfocus(Client *c); @@ -246,6 +247,7 @@ static void zoom(const Arg *arg); typedef struct { KeyCode keycode; unsigned int state; + int type; } BufferedKey; static BufferedKey key_buffer[200]; static int key_buffer_len = 0; @@ -267,6 +269,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [Expose] = expose, [FocusIn] = focusin, [KeyPress] = keypress, + [KeyRelease] = keyrelease, [MappingNotify] = mappingnotify, [MapRequest] = maprequest, [MotionNotify] = motionnotify, @@ -1064,6 +1067,7 @@ void grabkeys(void) { updatenumlockmask(); //XUngrabKey(dpy, AnyKey, AnyModifier, root); + // FIXME key grabbing causes FocusOut events, which confuses programs (they only get keypresses when they don't have focus) XGrabKey(dpy, AnyKey, AnyModifier, root, True, GrabModeAsync, GrabModeAsync); } @@ -1085,11 +1089,18 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { #endif /* XINERAMA */ void -send_keycode(KeyCode key, unsigned int state) { +send_key_event(int type, KeyCode key, unsigned int state) { + int mask; + if (type == KeyPress) { + mask = KeyPressMask; + } else { + mask = KeyReleaseMask; + } XKeyEvent event; if(!selmon->sel) { return; } + event.type = type; event.display = dpy; event.root = root; event.window = selmon->sel->win; @@ -1102,10 +1113,8 @@ send_keycode(KeyCode key, unsigned int state) { event.time = CurrentTime; event.state = state; // 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); + event.same_screen = True; + XSendEvent(event.display, event.window, True, mask, (XEvent *)&event); } void @@ -1116,6 +1125,7 @@ keypress(XEvent *e) { Bool called = False; ev = &e->xkey; + // fprintf(stderr, "key DOWN %i\n", ev->keycode); keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym @@ -1132,16 +1142,38 @@ keypress(XEvent *e) { key_buffering = False; } else { key_buffer[key_buffer_len].keycode = (KeyCode)ev->keycode; - key_buffer[key_buffer_len].state = (KeyCode)ev->state; + key_buffer[key_buffer_len].state = ev->state; + key_buffer[key_buffer_len].type = KeyPress; key_buffer_len += 1; } } else { - send_keycode(ev->keycode, ev->state); + send_key_event(KeyPress, (KeyCode)ev->keycode, ev->state); } } } void +keyrelease(XEvent *e) { + XKeyEvent *ev; + ev = &e->xkey; + // fprintf(stderr, "key UP %i\n", ev->keycode); + if(key_buffering) { + if(key_buffer_len == LENGTH(key_buffer)) { + // buffer full, bail + key_buffer_len = 0; + key_buffering = False; + } else { + key_buffer[key_buffer_len].keycode = (KeyCode)ev->keycode; + key_buffer[key_buffer_len].state = ev->state; + key_buffer[key_buffer_len].type = KeyRelease; + key_buffer_len += 1; + } + } else { + send_key_event(KeyRelease, (KeyCode)ev->keycode, ev->state); + } +} + +void killclient(const Arg *arg) { if(!selmon->sel) return; @@ -1224,10 +1256,8 @@ manage(Window w, XWindowAttributes *wa) { XMapWindow(dpy, c->win); focus(c); if(key_buffering) { - if(key_buffer_len > 0) { - for(i = 0; i < key_buffer_len; ++i) { - send_keycode(key_buffer[i].keycode, key_buffer[i].state); - } + for(i = 0; i < key_buffer_len; ++i) { + send_key_event(key_buffer[i].type, key_buffer[i].keycode, key_buffer[i].state); } key_buffer_len = 0; key_buffering = False; @@ -1237,6 +1267,7 @@ manage(Window w, XWindowAttributes *wa) { void mappingnotify(XEvent *e) { XMappingEvent *ev = &e->xmapping; + // fprintf(stderr, "MapNotify\n"); XRefreshKeyboardMapping(ev); if(ev->request == MappingKeyboard) @@ -1248,6 +1279,7 @@ maprequest(XEvent *e) { static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; + // fprintf(stderr, "MapRequest\n"); if(!XGetWindowAttributes(dpy, ev->window, &wa)) return; if(wa.override_redirect) { @@ -1550,9 +1582,14 @@ run(void) { XEvent ev; /* main event loop */ XSync(dpy, False); - while(running && !XNextEvent(dpy, &ev)) - if(handler[ev.type]) + while(running && !XNextEvent(dpy, &ev)) { + if(handler[ev.type]) { + // fprintf(stderr, "handling event type %i\n", ev.type); handler[ev.type](&ev); /* call handler */ + } else { + // fprintf(stderr, "evt type %i\n", ev.type); + } + } } void -- 1.7.10.4