/* 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;
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) {
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");
}
}
};
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);
}
}
IceAddConnectionWatch(ice_watch, NULL);
#endif
+#ifdef XKB
+ XkbSetDetectableAutoRepeat(obt_display, True, NULL);
+#endif
+
client_add_destroy_notify(focus_delay_client_dest, NULL);
}
static ObPopup *popup = NULL;
static KeyBindingTree *curpos;
static guint chain_timer = 0;
+static guint repeat_key = 0;
static void grab_keys(gboolean grab)
{
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;
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) {
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 &&
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();
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);
}
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);
}
grab_keys(TRUE);
popup = popup_new();
popup_set_text_align(popup, RR_JUSTIFY_CENTER);
+ repeat_key = 0;
}
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);
}
}
-KeyBindingTree *tree_build(GList *keylist, gboolean grab)
+KeyBindingTree *tree_build(GList *keylist, gboolean grab, gboolean no_repeat)
{
GList *it;
KeyBindingTree *ret = NULL, *p;
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);
}
typedef struct KeyBindingTree {
guint state;
guint key;
+ gboolean no_repeat;
gboolean grab;
GList *keylist;
GSList *actions; /* list of Action pointers */
} 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);
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,