From ee2db440ed419891ef373584963ea5874b62f4a2 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 16 Sep 2016 06:11:54 +0200 Subject: [PATCH] Allow ignoring repeat events for a keybind --- openbox/actions/execute.c | 3 ++- openbox/config.c | 6 ++++-- openbox/event.c | 4 ++++ openbox/keyboard.c | 25 +++++++++++++++++++------ openbox/keyboard.h | 2 +- openbox/keytree.c | 3 ++- openbox/keytree.h | 3 ++- openbox/misc.h | 1 + 8 files changed, 35 insertions(+), 12 deletions(-) diff --git a/openbox/actions/execute.c b/openbox/actions/execute.c index 2f76c45..1e9dae7 100644 --- a/openbox/actions/execute.c +++ b/openbox/actions/execute.c @@ -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; diff --git a/openbox/config.c b/openbox/config.c index 8fd2dc0..e732011 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -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); } } diff --git a/openbox/event.c b/openbox/event.c index d48d32b..6af88dc 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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); } diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 2ce664a..5861361 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -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) diff --git a/openbox/keyboard.h b/openbox/keyboard.h index 8569b97..f265812 100644 --- a/openbox/keyboard.h +++ b/openbox/keyboard.h @@ -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); diff --git a/openbox/keytree.c b/openbox/keytree.c index 87003a0..4747c26 100644 --- a/openbox/keytree.c +++ b/openbox/keytree.c @@ -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); } diff --git a/openbox/keytree.h b/openbox/keytree.h index 6b37606..e15872d 100644 --- a/openbox/keytree.h +++ b/openbox/keytree.h @@ -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); diff --git a/openbox/misc.h b/openbox/misc.h index 750dddd..becb9ee 100644 --- a/openbox/misc.h +++ b/openbox/misc.h @@ -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, -- 1.9.1