summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2008-02-02 00:59:59 -0500
committerDana Jansens <danakj@orodu.net>2008-02-02 01:25:59 -0500
commit3b0f41dc66da86aaad4f0343bbfb632c7bbfd0c7 (patch)
treea4aed84e724d2c3a19392874a86bc22cd2c26b48
parent6a3ac556b9ed5fd6e578da20a144f22dd4769267 (diff)
fix a crash from chroot of invalid keys, and make keybindings reload better
since invalid(not translated) keybindings are allowed in the tree, the tree's structure may actually need to change when reconfiguring. actually, it could need to anyways. so when re-translating all the keybindings, actually rebuild the keybinding tree. also, make the chroot building code not fail when translate fails, to match the rest of the code and avoid segfaults with chroots on invalid keys.
-rw-r--r--openbox/keyboard.c39
-rw-r--r--openbox/keytree.c26
-rw-r--r--openbox/keytree.h1
3 files changed, 47 insertions, 19 deletions
diff --git a/openbox/keyboard.c b/openbox/keyboard.c
index 4c570dfb..82d6dfdc 100644
--- a/openbox/keyboard.c
+++ b/openbox/keyboard.c
@@ -265,9 +265,46 @@ void keyboard_event(ObClient *client, const XEvent *e)
}
}
+static void node_rebind(KeyBindingTree *node)
+{
+ if (node->first_child) {
+ /* find leaf nodes */
+ node_rebind(node->first_child);
+
+ /* for internal nodes, add them to the tree if they
+ are a chroot, but do this after adding their
+ children */
+ if (node->chroot)
+ keyboard_chroot(node->keylist);
+ }
+ else {
+ /* for leaf nodes, rebind each action assigned to it */
+ GSList *it;
+ 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->actions = g_slist_delete_link(node->actions, node->actions);
+ }
+
+ if (node->chroot)
+ keyboard_chroot(node->keylist);
+ }
+
+ /* go through each sibling */
+ if (node->next_sibling) node_rebind(node->next_sibling);
+}
+
void keyboard_rebind(void)
{
- tree_rebind(keyboard_firstnode);
+ KeyBindingTree *old;
+
+ old = keyboard_firstnode;
+ keyboard_firstnode = NULL;
+ node_rebind(old);
+
+ tree_destroy(old);
+ set_curpos(NULL);
grab_keys(TRUE);
}
diff --git a/openbox/keytree.c b/openbox/keytree.c
index 714fffda..56cc96d4 100644
--- a/openbox/keytree.c
+++ b/openbox/keytree.c
@@ -68,13 +68,6 @@ KeyBindingTree *tree_build(GList *keylist)
return ret;
}
-void tree_rebind(KeyBindingTree *node) {
- GList *it = g_list_last(node->keylist);
- translate_key(it->data, &node->state, &node->key);
- if (node->next_sibling) tree_rebind(node->next_sibling);
- if (node->first_child) tree_rebind(node->first_child);
-}
-
void tree_assimilate(KeyBindingTree *node)
{
KeyBindingTree *a, *b, *tmp, *last;
@@ -139,16 +132,15 @@ KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict)
gboolean tree_chroot(KeyBindingTree *tree, GList *keylist)
{
guint key, state;
- if (translate_key(keylist->data, &state, &key)) {
- while (tree != NULL && !(tree->state == state && tree->key == key))
- tree = tree->next_sibling;
- if (tree != NULL) {
- if (keylist->next == NULL) {
- tree->chroot = TRUE;
- return TRUE;
- } else
- return tree_chroot(tree->first_child, keylist->next);
- }
+ translate_key(keylist->data, &state, &key);
+ while (tree != NULL && !(tree->state == state && tree->key == key))
+ tree = tree->next_sibling;
+ if (tree != NULL) {
+ if (keylist->next == NULL) {
+ tree->chroot = TRUE;
+ return TRUE;
+ } else
+ return tree_chroot(tree->first_child, keylist->next);
}
return FALSE;
}
diff --git a/openbox/keytree.h b/openbox/keytree.h
index 0307378d..391cb154 100644
--- a/openbox/keytree.h
+++ b/openbox/keytree.h
@@ -41,7 +41,6 @@ KeyBindingTree *tree_build(GList *keylist);
void tree_assimilate(KeyBindingTree *node);
KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict);
gboolean tree_chroot(KeyBindingTree *tree, GList *keylist);
-void tree_rebind(KeyBindingTree *node);
#endif