summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorgios Bitzes <geobijes@gmail.com>2015-02-16 03:03:26 +0200
committerGeorgios Bitzes <geobijes@gmail.com>2015-02-16 03:20:28 +0200
commit07df49a5afba5828709cf7f2bf67bb3817c604ce (patch)
treeab900d6ce681b7d9aeb74d5f96d980c0244419a6
parentfaf6a708dc4473657be4bd05479ad4f73ce54fee (diff)
Fix bugs relating to hotkeys with modifiers
This commit makes the following changes: 1) Fix a bad check introduced in dee0bfb, which checks the modstate of the event with the keysym of the switcher, not its modmask: modstate & ( switchers[i].keysym ) I think it was broken before as well, a binary AND between the two masks will not tell much about whether they are equal. Instead, the masks are now checked for equality after removing LockMask and NumlockMask. 2) Stop binding to AnyModifier when none is used. This conflicts with the case in which we want to bind different modes to the same key, but different modifiers. for example, rofi -key-run F2 -key-ssh alt+F2 -key-window shift+F2 Binding F2 with AnyModifier would prevent alt+F2 and shift+F2 from being used. 3) Remove UngrabKey from x11_grab_key to make the above example possible. 4) Refactor search for any of the global keybindings into function locate_switcher.
-rw-r--r--source/rofi.c50
-rw-r--r--source/x11-helper.c22
2 files changed, 35 insertions, 37 deletions
diff --git a/source/rofi.c b/source/rofi.c
index ba734741..f2d2c04b 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -544,6 +544,27 @@ inline static void menu_nav_down ( MenuState *state )
state->update = TRUE;
}
/**
+ * @param key the Key to match
+ * @param modstate the modifier state to match
+ *
+ * Return the index of the switcher that matches the key combination
+ * specified by key and modstate. Returns -1 if none was found
+ */
+extern unsigned int NumlockMask;
+static int locate_switcher( KeySym key, unsigned int modstate ) {
+ // ignore annoying modifiers
+ unsigned int modstate_filtered = modstate & ~(LockMask | NumlockMask);
+ for ( unsigned int i = 0; i < num_switchers; i++ ) {
+ if ( switchers[i].keystr != NULL ) {
+ if ( ( modstate_filtered == switchers[i].modmask ) &&
+ switchers[i].keysym == key ) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+/**
* @param state Internal state of the menu.
* @param key the Key being pressed.
* @param modstate the modifier state.
@@ -554,18 +575,7 @@ static void menu_keyboard_navigation ( MenuState *state, KeySym key, unsigned in
{
// pressing one of the global key bindings closes the switcher. this allows fast closing of the
// menu if an item is not selected
- for ( unsigned int i = 0; i < num_switchers; i++ ) {
- if ( switchers[i].keystr != NULL ) {
- if ( ( switchers[i].modmask == AnyModifier || modstate & ( switchers[i].keysym ) ) &&
- switchers[i].keysym == key ) {
- state->retv = MENU_CANCEL;
- state->quit = TRUE;
- state->prev_key = key;
- return;
- }
- }
- }
- if ( key == XK_Escape ) {
+ if ( locate_switcher( key, modstate ) != -1 || key == XK_Escape ) {
state->retv = MENU_CANCEL;
state->quit = TRUE;
}
@@ -1425,19 +1435,15 @@ static void run_switcher ( int do_fork, SwitcherMode mode )
*/
static void handle_keypress ( XEvent *ev )
{
- int index = -1;
+ int index;
KeySym key = XkbKeycodeToKeysym ( display, ev->xkey.keycode, 0, 0 );
- for ( unsigned int i = 0; i < num_switchers; i++ ) {
- if ( switchers[i].keystr != NULL ) {
- if ( ( switchers[i].modmask == AnyModifier || ( ev->xkey.state ) & ( switchers[i].keysym ) ) &&
- switchers[i].keysym == key ) {
- index = i;
- }
- }
- }
- if ( index >= 0 ) {
+ index = locate_switcher( key, ev->xkey.state );
+ if( index >= 0 ) {
run_switcher ( TRUE, index );
}
+ else {
+ fprintf ( stderr, "Warning: Unhandled keypress in global keyhandler, keycode = %u mask = %u\n", ev->xkey.keycode, ev->xkey.state );
+ }
}
diff --git a/source/x11-helper.c b/source/x11-helper.c
index 4f2de7b6..6ad19af5 100644
--- a/source/x11-helper.c
+++ b/source/x11-helper.c
@@ -257,21 +257,14 @@ void x11_grab_key ( Display *display, unsigned int modmask, KeySym key )
Screen *screen = DefaultScreenOfDisplay ( display );
Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) );
KeyCode keycode = XKeysymToKeycode ( display, key );
- XUngrabKey ( display, keycode, AnyModifier, root );
- if ( modmask != AnyModifier ) {
- // bind to combinations of mod and lock masks, so caps and numlock don't confuse people
- XGrabKey ( display, keycode, modmask, root, True, GrabModeAsync, GrabModeAsync );
- XGrabKey ( display, keycode, modmask | LockMask, root, True, GrabModeAsync, GrabModeAsync );
+ // bind to combinations of mod and lock masks, so caps and numlock don't confuse people
+ XGrabKey ( display, keycode, modmask, root, True, GrabModeAsync, GrabModeAsync );
+ XGrabKey ( display, keycode, modmask | LockMask, root, True, GrabModeAsync, GrabModeAsync );
- if ( NumlockMask ) {
- XGrabKey ( display, keycode, modmask | NumlockMask, root, True, GrabModeAsync, GrabModeAsync );
- XGrabKey ( display, keycode, modmask | NumlockMask | LockMask, root, True, GrabModeAsync, GrabModeAsync );
- }
- }
- else{
- // nice simple single key bind
- XGrabKey ( display, keycode, AnyModifier, root, True, GrabModeAsync, GrabModeAsync );
+ if ( NumlockMask ) {
+ XGrabKey ( display, keycode, modmask | NumlockMask, root, True, GrabModeAsync, GrabModeAsync );
+ XGrabKey ( display, keycode, modmask | NumlockMask | LockMask, root, True, GrabModeAsync, GrabModeAsync );
}
}
@@ -332,8 +325,7 @@ void x11_parse_key ( char *combo, unsigned int *mod, KeySym *key )
modmask |= Mod5Mask;
}
- // If no modifier mask is set, allow any modifier.
- *mod = modmask ? modmask : AnyModifier;
+ *mod = modmask;
// Skip modifier (if exist) and parse key.
char i = strlen ( combo );