X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=fa48fb00fa46a4a8b01bc7940c92aec9ee6f2bf1;hp=e1a787010147ec3f64831fdceecced493c01e114;hb=33883da028e2eae2cc5c70b445e0d78434d11ac9;hpb=b29acc15f62b09628f5a37038076388eb2c7a71f diff --git a/dwm.c b/dwm.c index e1a7870..fa48fb0 100644 --- a/dwm.c +++ b/dwm.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMWindowTypeDialog, NetClientList, NetSupportingWMCheck, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, - ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + ClkClientWin, ClkRootWin, ClkAnywhere, ClkLast }; /* clicks */ typedef union { int i; @@ -179,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); @@ -200,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); @@ -245,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; @@ -266,6 +269,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [Expose] = expose, [FocusIn] = focusin, [KeyPress] = keypress, + [KeyRelease] = keyrelease, [MappingNotify] = mappingnotify, [MapRequest] = maprequest, [MotionNotify] = motionnotify, @@ -499,6 +503,18 @@ buttonpress(XEvent *e) { Client *c; Monitor *m; XButtonPressedEvent *ev = &e->xbutton; + Bool called = False; + + for(i = 0; i < LENGTH(buttons); i++) { + if(buttons[i].click == ClkAnywhere && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) { + buttons[i].func(&buttons[i].arg); + called = True; + } + } + if (called) { + return; + } click = ClkRootWin; /* focus monitor if necessary */ @@ -509,15 +525,20 @@ buttonpress(XEvent *e) { } if(ev->window == selmon->barwin) { return; - } - else if((c = wintoclient(ev->window))) { + } else if((c = wintoclient(ev->window))) { focus(c); click = ClkClientWin; } - for(i = 0; i < LENGTH(buttons); i++) + for(i = 0; i < LENGTH(buttons); i++) { if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) { + if (click == ClkTagBar && buttons[i].arg.i == 0) { + buttons[i].func(&arg); + } else { + buttons[i].func(&buttons[i].arg); + } + } + } } void @@ -1029,16 +1050,16 @@ grabbuttons(Client *c, Bool focused) { XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if(focused) { for(i = 0; i < LENGTH(buttons); i++) - if(buttons[i].click == ClkClientWin) + if(buttons[i].click == ClkClientWin || buttons[i].click == ClkAnywhere) for(j = 0; j < LENGTH(modifiers); j++) XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); - } - else + } else { XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); + } } } @@ -1046,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); } @@ -1067,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; @@ -1084,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 @@ -1098,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 @@ -1114,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; @@ -1206,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; @@ -1219,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) @@ -1230,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) { @@ -1532,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