X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=fa48fb00fa46a4a8b01bc7940c92aec9ee6f2bf1;hp=b7f5a2650ac07a243f2f5a137c9fa490a01e0031;hb=33883da028e2eae2cc5c70b445e0d78434d11ac9;hpb=a719e4fd563ff0b04f2696365485ce5f46fbccdc diff --git a/dwm.c b/dwm.c index b7f5a26..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; @@ -177,9 +178,9 @@ 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 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); +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); @@ -243,7 +244,12 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); static void zoom(const Arg *arg); /* variables */ -static KeyCode key_buffer[100]; +typedef struct { + KeyCode keycode; + unsigned int state; + int type; +} BufferedKey; +static BufferedKey key_buffer[200]; static int key_buffer_len = 0; static Bool key_buffering = False; static const char broken[] = "broken"; @@ -263,6 +269,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [Expose] = expose, [FocusIn] = focusin, [KeyPress] = keypress, + [KeyRelease] = keyrelease, [MappingNotify] = mappingnotify, [MapRequest] = maprequest, [MotionNotify] = motionnotify, @@ -496,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 */ @@ -506,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 @@ -748,10 +772,11 @@ detachstack(Client *c) { for(i = nextvisible(c->mon->clients); i && i != c; i = nextvisible(i->next)) next_sel = i; // failing that, find first visible window (besides c) - if (!next_sel) + if (!next_sel) { for(i = nextvisible(c->mon->clients); i && i == c; i = nextvisible(i->next)); if (i != c) next_sel = i; + } c->mon->sel = next_sel; } if (prev) { @@ -1025,60 +1050,25 @@ 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); + } } } void grabkeys(void) { updatenumlockmask(); - { - unsigned int i, j; - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for(i = 0; i < LENGTH(keys); i++) - if((code = XKeysymToKeycode(dpy, keys[i].keysym))) - 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); - } + //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); } void @@ -1099,11 +1089,18 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { #endif /* XINERAMA */ void -send_keycode(KeyCode key) { +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; @@ -1114,12 +1111,10 @@ send_keycode(KeyCode key) { event.x_root = 1; event.y_root = 1; event.time = CurrentTime; - event.state = 0; // modifiers + 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 @@ -1130,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 @@ -1144,14 +1140,36 @@ keypress(XEvent *e) { // 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[key_buffer_len].keycode = (KeyCode)ev->keycode; + key_buffer[key_buffer_len].state = ev->state; + key_buffer[key_buffer_len].type = KeyPress; key_buffer_len += 1; } } else { - send_keycode(ev->keycode); + 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); } } @@ -1238,22 +1256,18 @@ manage(Window w, XWindowAttributes *wa) { XMapWindow(dpy, c->win); focus(c); if(key_buffering) { - // FIXME: try turning off buffering below where we send the virt keypresses - 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]); - } + 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; - // FIXME ie here + key_buffering = False; } } void mappingnotify(XEvent *e) { XMappingEvent *ev = &e->xmapping; + // fprintf(stderr, "MapNotify\n"); XRefreshKeyboardMapping(ev); if(ev->request == MappingKeyboard) @@ -1265,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) { @@ -1567,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 @@ -1799,7 +1819,6 @@ void kbspawn(const Arg *arg) { key_buffering = True; key_buffer_len = 0; - grab_typing_keys(); spawn(arg); }