diff --git a/x.c b/x.c index 2ad74d3..4248082 100644 --- a/x.c +++ b/x.c @@ -458,6 +458,53 @@ static void setopacity(Window win, unsigned long opacity) + /* + * Returns the modifier which is NumLock. + */ +static KeySym x_numlock_mod() +{ + const KeyCode nl = XKeysymToKeycode(xctx.dpy, XStringToKeysym("Num_Lock")); + + int mod; + KeySym sym = 0; + XModifierKeymap * map = XGetModifierMapping(xctx.dpy); + + for (mod = 0; mod < 8; mod++) { + for (int j = 0; j < map->max_keypermod; j++) { + if (map->modifiermap[mod*map->max_keypermod+j] == nl) { + switch (mod) { + case ShiftMapIndex: + sym = ShiftMask; + break; + case LockMapIndex: + sym = LockMask; + break; + case ControlMapIndex: + sym = ControlMask; + break; + case Mod1MapIndex: + sym = Mod1Mask; + break; + case Mod2MapIndex: + sym = Mod2Mask; + break; + case Mod3MapIndex: + sym = Mod3Mask; + break; + case Mod4MapIndex: + sym = Mod4Mask; + break; + case Mod5MapIndex: + sym = Mod5Mask; + break; + } + } + } + } + + XFreeModifiermap(map); + return sym; +} /* * Helper function to use glib's mainloop mechanic @@ -488,6 +535,7 @@ gboolean x_mainloop_fd_dispatch(GSource * source, GSourceFunc callback, gpointer user_data) { XEvent ev; + unsigned int state; while (XPending(xctx.dpy) > 0) { XNextEvent(xctx.dpy, &ev); switch (ev.type) { @@ -508,10 +556,13 @@ gboolean x_mainloop_fd_dispatch(GSource * source, GSourceFunc callback, } break; case KeyPress: + state = ev.xkey.state; + /* NumLock is also encoded in the state. Remove it. */ + state &= ~x_numlock_mod(); if (settings.close_ks.str && XLookupKeysym(&ev.xkey, 0) == settings.close_ks.sym - && settings.close_ks.mask == ev.xkey.state) { + && settings.close_ks.mask == state) { if (displayed) { notification *n = g_queue_peek_head(displayed); if (n) @@ -521,19 +572,19 @@ gboolean x_mainloop_fd_dispatch(GSource * source, GSourceFunc callback, if (settings.history_ks.str && XLookupKeysym(&ev.xkey, 0) == settings.history_ks.sym - && settings.history_ks.mask == ev.xkey.state) { + && settings.history_ks.mask == state) { history_pop(); } if (settings.close_all_ks.str && XLookupKeysym(&ev.xkey, 0) == settings.close_all_ks.sym - && settings.close_all_ks.mask == ev.xkey.state) { + && settings.close_all_ks.mask == state) { move_all_to_history(); } if (settings.context_ks.str && XLookupKeysym(&ev.xkey, 0) == settings.context_ks.sym - && settings.context_ks.mask == ev.xkey.state) { + && settings.context_ks.mask == state) { context_menu(); } break; @@ -926,9 +977,12 @@ int x_shortcut_grab(keyboard_shortcut * ks) x_shortcut_setup_error_handler(); - if (ks->is_valid) + if (ks->is_valid) { XGrabKey(xctx.dpy, ks->code, ks->mask, root, true, GrabModeAsync, GrabModeAsync); + XGrabKey(xctx.dpy, ks->code, ks->mask | x_numlock_mod() , root, + true, GrabModeAsync, GrabModeAsync); + } if (x_shortcut_tear_down_error_handler()) { fprintf(stderr, "Unable to grab key \"%s\"\n", ks->str); @@ -945,8 +999,10 @@ void x_shortcut_ungrab(keyboard_shortcut * ks) { Window root; root = RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); - if (ks->is_valid) + if (ks->is_valid) { XUngrabKey(xctx.dpy, ks->code, ks->mask, root); + XUngrabKey(xctx.dpy, ks->code, ks->mask | x_numlock_mod(), root); + } } /*