Allow ignoring repeat events for a keybind
authorMikael Magnusson <mikachu@gmail.com>
Fri, 16 Sep 2016 04:11:54 +0000 (06:11 +0200)
committerMikael Magnusson <mikachu@gmail.com>
Fri, 16 Sep 2016 04:11:54 +0000 (06:11 +0200)
openbox/actions/execute.c
openbox/config.c
openbox/event.c
openbox/keyboard.c
openbox/keyboard.h
openbox/keytree.c
openbox/keytree.h
openbox/misc.h

index 2f76c45..1e9dae7 100644 (file)
@@ -264,7 +264,8 @@ static gboolean run_func(ObActionsData *data, gpointer options)
 
     /* If there is a keyboard grab going on then we need to cancel
        it so the application can grab things */
-    if (data->uact != OB_USER_ACTION_MENU_SELECTION)
+    if (data->uact != OB_USER_ACTION_MENU_SELECTION &&
+        data->uact != OB_USER_ACTION_KEYBOARD_KEY_NO_REPEAT)
         event_cancel_all_key_grabs();
 
     e = NULL;
index 8fd2dc0..e732011 100644 (file)
@@ -450,12 +450,14 @@ static void parse_key(xmlNodePtr node, GList *keylist)
     xmlNodePtr n;
     gboolean is_chroot = FALSE;
     gboolean grab = TRUE;
+    gboolean repeat = FALSE;
 
     if (!obt_xml_attr_string(node, "key", &keystring))
         return;
 
     obt_xml_attr_bool(node, "chroot", &is_chroot);
     obt_xml_attr_bool(node, "grab", &grab);
+    obt_xml_attr_bool(node, "repeat", &repeat);
 
     keys = g_strsplit(keystring, " ", 0);
     for (key = keys; *key; ++key) {
@@ -473,7 +475,7 @@ static void parse_key(xmlNodePtr node, GList *keylist)
 
                 action = actions_parse(n);
                 if (action)
-                    keyboard_bind(keylist, action, grab);
+                    keyboard_bind(keylist, action, grab, !repeat);
                 n = obt_xml_find_node(n->next, "action");
             }
         }
@@ -1009,7 +1011,7 @@ static void bind_default_keyboard(void)
     };
     for (it = binds; it->key; ++it) {
         GList *l = g_list_append(NULL, g_strdup(it->key));
-        keyboard_bind(l, actions_parse_string(it->actname), TRUE);
+        keyboard_bind(l, actions_parse_string(it->actname), TRUE, TRUE);
     }
 }
 
index d48d32b..6af88dc 100644 (file)
@@ -159,6 +159,10 @@ void event_startup(gboolean reconfig)
     IceAddConnectionWatch(ice_watch, NULL);
 #endif
 
+#ifdef XKB
+    XkbSetDetectableAutoRepeat(obt_display, True, NULL);
+#endif
+
     client_add_destroy_notify(focus_delay_client_dest, NULL);
 }
 
index 2ce664a..5861361 100644 (file)
@@ -41,6 +41,7 @@ KeyBindingTree *keyboard_firstnode = NULL;
 static ObPopup *popup = NULL;
 static KeyBindingTree *curpos;
 static guint chain_timer = 0;
+static guint repeat_key = 0;
 
 static void grab_keys(gboolean grab)
 {
@@ -132,14 +133,14 @@ void keyboard_chroot(GList *keylist)
        chroot binding. so add it to the tree then. */
     if (!tree_chroot(keyboard_firstnode, keylist)) {
         KeyBindingTree *tree;
-        if (!(tree = tree_build(keylist, TRUE)))
+        if (!(tree = tree_build(keylist, TRUE, TRUE)))
             return;
         tree_chroot(tree, keylist);
         tree_assimilate(tree);
     }
 }
 
-gboolean keyboard_bind(GList *keylist, ObActionsAct *action, gboolean grab)
+gboolean keyboard_bind(GList *keylist, ObActionsAct *action, gboolean grab, gboolean no_repeat)
 {
     KeyBindingTree *tree, *t;
     gboolean conflict;
@@ -147,7 +148,7 @@ gboolean keyboard_bind(GList *keylist, ObActionsAct *action, gboolean grab)
     g_assert(keylist != NULL);
     g_assert(action != NULL);
 
-    if (!(tree = tree_build(keylist, grab)))
+    if (!(tree = tree_build(keylist, grab, no_repeat)))
         return FALSE;
 
     if ((t = tree_find(tree, &conflict)) != NULL) {
@@ -218,15 +219,24 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
     KeyBindingTree *p;
     gboolean used;
     guint mods;
+    gboolean repeating = FALSE;
+
+    ob_debug("Saved key: %d, %sed key: %d", repeat_key, e->type == KeyPress ? "press" : "releas", e->xkey.keycode);
 
     if (e->type == KeyRelease) {
         grab_key_passive_count(-1);
+        repeat_key = 0;
         return FALSE;
     }
 
     g_assert(e->type == KeyPress);
     grab_key_passive_count(1);
 
+    if (repeat_key == e->xkey.keycode)
+        repeating = TRUE;
+    else
+        repeat_key = e->xkey.keycode;
+
     mods = obt_keyboard_only_modmasks(e->xkey.state);
 
     if (e->xkey.keycode == config_keyboard_reset_keycode &&
@@ -243,7 +253,7 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
     else
         p = curpos->first_child;
     while (p) {
-        if (p->key == e->xkey.keycode && p->state == mods) {
+        if (p->key == e->xkey.keycode && p->state == mods && !(p->no_repeat && repeating)) {
             /* if we hit a key binding, then close any open menus and run it */
             if (menu_frame_visible)
                 menu_frame_hide_all();
@@ -266,7 +276,9 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
                 if (it == NULL) /* reset if the actions are not interactive */
                     keyboard_reset_chains(0);
 
-                actions_run_acts(p->actions, OB_USER_ACTION_KEYBOARD_KEY,
+                actions_run_acts(p->actions,
+                                 p->no_repeat ? OB_USER_ACTION_KEYBOARD_KEY_NO_REPEAT
+                                              : OB_USER_ACTION_KEYBOARD_KEY,
                                  e->xkey.state, e->xkey.x_root, e->xkey.y_root,
                                  0, OB_FRAME_CONTEXT_NONE, client);
             }
@@ -295,7 +307,7 @@ static void node_rebind(KeyBindingTree *node)
         while (node->actions) {
             /* add each action, and remove them from the original tree so
                they don't get free'd on us */
-            keyboard_bind(node->keylist, node->actions->data, node->grab);
+            keyboard_bind(node->keylist, node->actions->data, node->grab, node->no_repeat);
             node->actions = g_slist_delete_link(node->actions, node->actions);
         }
 
@@ -326,6 +338,7 @@ void keyboard_startup(gboolean reconfig)
     grab_keys(TRUE);
     popup = popup_new();
     popup_set_text_align(popup, RR_JUSTIFY_CENTER);
+    repeat_key = 0;
 }
 
 void keyboard_shutdown(gboolean reconfig)
index 8569b97..f265812 100644 (file)
@@ -37,7 +37,7 @@ void keyboard_shutdown(gboolean reconfig);
 void keyboard_rebind(void);
 
 void keyboard_chroot(GList *keylist);
-gboolean keyboard_bind(GList *keylist, struct _ObActionsAct *action, gboolean grab);
+gboolean keyboard_bind(GList *keylist, struct _ObActionsAct *action, gboolean grab, gboolean no_repeat);
 void keyboard_unbind_all(void);
 
 gboolean keyboard_event(struct _ObClient *client, const XEvent *e);
index 87003a0..4747c26 100644 (file)
@@ -44,7 +44,7 @@ void tree_destroy(KeyBindingTree *tree)
     }
 }
 
-KeyBindingTree *tree_build(GList *keylist, gboolean grab)
+KeyBindingTree *tree_build(GList *keylist, gboolean grab, gboolean no_repeat)
 {
     GList *it;
     KeyBindingTree *ret = NULL, *p;
@@ -63,6 +63,7 @@ KeyBindingTree *tree_build(GList *keylist, gboolean grab)
                                           g_strdup(kit->data)); /* deep copy */
         ret->first_child = p;
         ret->grab = grab;
+        ret->no_repeat = no_repeat;
         if (p != NULL) p->parent = ret;
         translate_key(it->data, &ret->state, &ret->key);
     }
index 6b37606..e15872d 100644 (file)
@@ -24,6 +24,7 @@
 typedef struct KeyBindingTree {
     guint state;
     guint key;
+    gboolean no_repeat;
     gboolean grab;
     GList *keylist;
     GSList *actions; /* list of Action pointers */
@@ -38,7 +39,7 @@ typedef struct KeyBindingTree {
 } KeyBindingTree;
 
 void tree_destroy(KeyBindingTree *tree);
-KeyBindingTree *tree_build(GList *keylist, gboolean grab);
+KeyBindingTree *tree_build(GList *keylist, gboolean grab, gboolean no_repeat);
 void tree_assimilate(KeyBindingTree *node);
 KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict);
 gboolean tree_chroot(KeyBindingTree *tree, GList *keylist);
index 750dddd..becb9ee 100644 (file)
@@ -89,6 +89,7 @@ typedef enum {
 typedef enum {
     OB_USER_ACTION_NONE, /* being fired from inside another action and such */
     OB_USER_ACTION_KEYBOARD_KEY,
+    OB_USER_ACTION_KEYBOARD_KEY_NO_REPEAT,
     OB_USER_ACTION_MOUSE_PRESS,
     OB_USER_ACTION_MOUSE_RELEASE,
     OB_USER_ACTION_MOUSE_CLICK,