+++ /dev/null
-#include "focus.h"
-#include "openbox.h"
-#include "hooks.h"
-#include "kbind.h"
-
-#include <glib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
-
-typedef struct KeyBindingTree {
- guint state;
- guint key;
- GList *keylist;
-
- /* the next binding in the tree at the same level */
- struct KeyBindingTree *next_sibling;
- /* the first child of this binding (next binding in a chained sequence).*/
- struct KeyBindingTree *first_child;
-} KeyBindingTree;
-
-
-static KeyBindingTree *firstnode, *curpos;
-static guint reset_key, reset_state;
-static gboolean grabbed, user_grabbed;
-
-guint kbind_translate_modifier(char *str)
-{
- if (!strcmp("Mod1", str)) return Mod1Mask;
- else if (!strcmp("Mod2", str)) return Mod2Mask;
- else if (!strcmp("Mod3", str)) return Mod3Mask;
- else if (!strcmp("Mod4", str)) return Mod4Mask;
- else if (!strcmp("Mod5", str)) return Mod5Mask;
- else if (!strcmp("C", str)) return ControlMask;
- else if (!strcmp("S", str)) return ShiftMask;
- g_warning("Invalid modifier '%s' in binding.", str);
- return 0;
-}
-
-static gboolean translate(char *str, guint *state, guint *keycode)
-{
- char **parsed;
- char *l;
- int i;
- gboolean ret = FALSE;
- KeySym sym;
-
- parsed = g_strsplit(str, "-", -1);
-
- /* first, find the key (last token) */
- l = NULL;
- for (i = 0; parsed[i] != NULL; ++i)
- l = parsed[i];
- if (l == NULL)
- goto translation_fail;
-
- /* figure out the mod mask */
- *state = 0;
- for (i = 0; parsed[i] != l; ++i) {
- guint m = kbind_translate_modifier(parsed[i]);
- if (!m) goto translation_fail;
- *state |= m;
- }
-
- /* figure out the keycode */
- sym = XStringToKeysym(l);
- if (sym == NoSymbol) {
- g_warning("Invalid key name '%s' in key binding.", l);
- goto translation_fail;
- }
- *keycode = XKeysymToKeycode(ob_display, sym);
- if (!keycode) {
- g_warning("Key '%s' does not exist on the display.", l);
- goto translation_fail;
- }
-
- ret = TRUE;
-
-translation_fail:
- g_strfreev(parsed);
- return ret;
-}
-
-static void destroytree(KeyBindingTree *tree)
-{
- KeyBindingTree *c;
-
- while (tree) {
- destroytree(tree->next_sibling);
- c = tree->first_child;
- if (c == NULL) {
- GList *it;
- for (it = tree->keylist; it != NULL; it = it->next)
- g_free(it->data);
- g_list_free(tree->keylist);
- }
- g_free(tree);
- tree = c;
- }
-}
-
-static KeyBindingTree *buildtree(GList *keylist)
-{
- GList *it;
- KeyBindingTree *ret = NULL, *p;
-
- if (g_list_length(keylist) <= 0)
- return NULL; /* nothing in the list.. */
-
- for (it = g_list_last(keylist); it != NULL; it = it->prev) {
- p = ret;
- ret = g_new(KeyBindingTree, 1);
- ret->next_sibling = NULL;
- if (p == NULL) {
- GList *it;
-
- /* this is the first built node, the bottom node of the tree */
- ret->keylist = g_list_copy(keylist); /* shallow copy */
- for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
- it->data = g_strdup(it->data);
- }
- ret->first_child = p;
- if (!translate(it->data, &ret->state, &ret->key)) {
- destroytree(ret);
- return NULL;
- }
- }
- return ret;
-}
-
-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 == a->key))
- last->next_sibling = b;
- else {
- last->first_child = b->first_child;
- g_free(b);
- }
- }
-}
-
-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;
- }
- }
-}
-
-void reset_chains()
-{
- /* XXX kill timer */
- curpos = NULL;
- if (grabbed) {
- grabbed = FALSE;
- g_message("reset chains. user: %d", user_grabbed);
- if (!user_grabbed)
- XUngrabKeyboard(ob_display, CurrentTime);
- }
-}
-
-void kbind_fire(guint state, guint key, gboolean press)
-{
- EventData *data;
- struct Client *c = focus_client;
- GQuark context = c != NULL ? g_quark_try_string("client")
- : g_quark_try_string("root");
-
- if (user_grabbed) {
- data = eventdata_new_key(press ? Key_Press : Key_Release,
- context, c, state, key, NULL);
- g_assert(data != NULL);
- hooks_fire_keyboard(data);
- eventdata_free(data);
- }
-
- if (key == reset_key && 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 == key && p->state == 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 {
- data = eventdata_new_key(press ? Key_Press : Key_Release,
- context, c, state, key,
- p->keylist);
- g_assert(data != NULL);
- hooks_fire(data);
- eventdata_free(data);
-
- XAllowEvents(ob_display, AsyncKeyboard, CurrentTime);
- reset_chains();
- }
- break;
- }
- p = p->next_sibling;
- }
- }
-}
-
-gboolean kbind_add(GList *keylist)
-{
- KeyBindingTree *tree, *t;
- gboolean conflict;
-
- if (!(tree = buildtree(keylist)))
- return FALSE; /* invalid binding requested */
-
- t = find(tree, &conflict);
- if (conflict) {
- /* conflicts with another binding */
- destroytree(tree);
- return FALSE;
- }
-
- if (t != NULL) {
- /* already bound to something */
- destroytree(tree);
- } else {
- /* grab the server here to make sure no key pressed go missed */
- XGrabServer(ob_display);
- XSync(ob_display, FALSE);
-
- grab_keys(FALSE);
-
- /* assimilate this built tree into the main tree */
- assimilate(tree); // assimilation destroys/uses the tree
-
- grab_keys(TRUE);
-
- XUngrabServer(ob_display);
- XFlush(ob_display);
- }
-
- return TRUE;
-}
-
-void kbind_clearall()
-{
- grab_keys(FALSE);
- destroytree(firstnode);
- firstnode = NULL;
- grab_keys(TRUE);
-}
-
-void kbind_startup()
-{
- gboolean b;
-
- curpos = firstnode = NULL;
- grabbed = user_grabbed = FALSE;
-
- b = translate("C-G", &reset_state, &reset_key);
- g_assert(b);
-}
-
-void kbind_shutdown()
-{
- if (grabbed || user_grabbed) {
- grabbed = FALSE;
- kbind_grab_keyboard(FALSE);
- }
- grab_keys(FALSE);
- destroytree(firstnode);
- firstnode = NULL;
-}
-
-gboolean kbind_grab_keyboard(gboolean grab)
-{
- gboolean ret = TRUE;
-
- if (!grab)
- g_message("grab_keyboard(false). grabbed: %d", grabbed);
-
- user_grabbed = grab;
- if (!grabbed) {
- if (grab)
- ret = XGrabKeyboard(ob_display, ob_root, 0, GrabModeAsync,
- GrabModeAsync, CurrentTime) == GrabSuccess;
- else
- XUngrabKeyboard(ob_display, CurrentTime);
- }
- return ret;
-}