-static void assimilate(KeyBindingTree *node)
-{
- KeyBindingTree *a, *b, *tmp, *last;
-
- if (firstnode == NULL) {
- /* there are no nodes at this level yet */
- firstnode = node;
- } else {
- a = firstnode;
- last = a;
- b = node;
- while (a) {
- last = a;
- if (!(a->state == b->state && a->key == b->key)) {
- a = a->next_sibling;
- } else {
- tmp = b;
- b = b->first_child;
- g_free(tmp);
- a = a->first_child;
- }
- }
- if (!(last->state == b->state && last->key == b->key))
- last->next_sibling = b;
- else {
- last->first_child = b->first_child;
- g_free(b);
- }
- }
-}
-
-static KeyBindingTree *find(KeyBindingTree *search, gboolean *conflict)
-{
- KeyBindingTree *a, *b;
-
- *conflict = FALSE;
-
- a = firstnode;
- b = search;
- while (a && b) {
- if (!(a->state == b->state && a->key == b->key)) {
- a = a->next_sibling;
- } else {
- if ((a->first_child == NULL) == (b->first_child == NULL)) {
- if (a->first_child == NULL) {
- /* found it! (return the actual node, not the search's) */
- return a;
- }
- } else {
- *conflict = TRUE;
- return NULL; /* the chain status' don't match (conflict!) */
- }
- b = b->first_child;
- a = a->first_child;
- }
- }
- return NULL; // it just isn't in here
-}
-
-static void grab_keys(gboolean grab)
-{
- if (!grab) {
- XUngrabKey(ob_display, AnyKey, AnyModifier, ob_root);
- } else {
- KeyBindingTree *p = firstnode;
- while (p) {
- XGrabKey(ob_display, p->key, p->state, ob_root, FALSE,
- GrabModeAsync, GrabModeSync);
- p = p->next_sibling;
- }
- }
-}
-
-static void reset_chains()
-{
- /* XXX kill timer */
- curpos = NULL;
- if (grabbed) {
- grabbed = FALSE;
- g_message("reset chains. user_grabbed: %d", user_grabbed);
- if (!user_grabbed)
- XUngrabKeyboard(ob_display, CurrentTime);
- }
-}
-
-void keyboard_event(XKeyEvent *e)
-{
- PyObject *chain, *client, *args, *keybdata, *ret;
- gboolean press = e->type == KeyPress;
-
- if (focus_client) client = clientwrap_new(focus_client);
- else client = Py_None;
-
- if (user_grabbed) {
- GString *str = g_string_sized_new(0);
- KeySym sym;
-
- /* build the 'chain' */
- if (e->state & ControlMask)
- g_string_append(str, "C-");
- if (e->state & ShiftMask)
- g_string_append(str, "S-");
- if (e->state & Mod1Mask)
- g_string_append(str, "Mod1-");
- if (e->state & Mod2Mask)
- g_string_append(str, "Mod2-");
- if (e->state & Mod3Mask)
- g_string_append(str, "Mod3-");
- if (e->state & Mod4Mask)
- g_string_append(str, "Mod4-");
- if (e->state & Mod5Mask)
- g_string_append(str, "Mod5-");
-
- sym = XKeycodeToKeysym(ob_display, e->keycode, 0);
- if (sym == NoSymbol)
- g_string_append(str, "NoSymbol");
- else {
- char *name = XKeysymToString(sym);
- if (name == NULL)
- name = "Undefined";
- g_string_append(str, name);
- }
-
- chain = PyTuple_New(1);
- PyTuple_SET_ITEM(chain, 0, PyString_FromString(str->str));
- g_string_free(str, TRUE);
-
- keybdata = keybdata_new(chain, e->state, e->keycode, press);
-
- args = Py_BuildValue("OO", keybdata, client);
-
- ret = PyObject_CallObject(grab_func, args);
- if (ret == NULL) PyErr_Print();
- Py_XDECREF(ret);
-
- Py_DECREF(args);
- Py_DECREF(keybdata);
- Py_DECREF(chain);
- }
-
- if (press) {
- if (e->keycode == reset_key && e->state == reset_state) {
- reset_chains();
- XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
- } else {
- KeyBindingTree *p;
- if (curpos == NULL)
- p = firstnode;
- else
- p = curpos->first_child;
- while (p) {
- if (p->key == e->keycode && p->state == e->state) {
- if (p->first_child != NULL) { /* part of a chain */
- /* XXX TIMER */
- if (!grabbed && !user_grabbed) {
- /*grab should never fail because we should have a
- sync grab at this point */
- XGrabKeyboard(ob_display, ob_root, 0,
- GrabModeAsync, GrabModeSync,
- CurrentTime);
- }
- grabbed = TRUE;
- curpos = p;
- XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
- } else {
- GList *it;
- int i;
-
- chain = PyTuple_New(g_list_length(p->keylist));
- for (i = 0, it = p->keylist; it != NULL;
- it = it->next, ++i)
- PyTuple_SET_ITEM(chain, i,
- PyString_FromString(it->data));
-
- keybdata = keybdata_new(chain, e->state, e->keycode,
- press);
-
- args = Py_BuildValue("OO", keybdata, client);
-
- ret = PyObject_CallObject(p->func, args);
- if (ret == NULL) PyErr_Print();
- Py_XDECREF(ret);
-
- Py_DECREF(args);
- Py_DECREF(keybdata);
- Py_DECREF(chain);
-
- XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
- reset_chains();
- }
- break;
- }
- p = p->next_sibling;
- }
- }
- }
-
- if (client != Py_None) { Py_DECREF(client); }
-}
-
-static void clearall()
-{
- grab_keys(FALSE);
- destroytree(firstnode);
- firstnode = NULL;
- grab_keys(TRUE);
-}