X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fkeyboard.c;h=70ac3ffcfd0038b64d3075ecf86ce7493affc137;hb=1d5fa24e4b92fbd2fc16847612a6825ca08d6567;hp=87cd5036a26b348a23210476fb4ece5be47d8d6f;hpb=f8a47de5ec444c452093371e3db16857eb39a490;p=chaz%2Fopenbox diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 87cd5036..70ac3ffc 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -103,319 +103,7 @@ static PyTypeObject KeyboardDataType = { /***************************************************************************/ -guint keyboard_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 = keyboard_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); - Py_XDECREF(tree->func); - } - 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; - ret->func = 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 == 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); -} static gboolean grab_keyboard(gboolean grab) { @@ -456,93 +144,6 @@ typedef struct Keyboard { staticforward PyTypeObject KeyboardType; -static PyObject *keyb_bind(Keyboard *self, PyObject *args) -{ - KeyBindingTree *tree = NULL, *t; - gboolean conflict; - PyObject *item, *tuple, *func; - GList *keylist = NULL, *it; - int i, s; - - CHECK_KEYBOARD(self, "grab"); - if (!PyArg_ParseTuple(args, "OO:grab", &tuple, &func)) - return NULL; - - if (!PyTuple_Check(tuple)) { - PyErr_SetString(PyExc_ValueError, "expected a tuple of strings"); - goto binderror; - } - if (!PyCallable_Check(func)) { - PyErr_SetString(PyExc_ValueError, "expected a callable object"); - goto binderror; - } - - s = PyTuple_GET_SIZE(tuple); - if (s <= 0) { - PyErr_SetString(PyExc_ValueError, "expected a tuple of strings"); - goto binderror; - } - - for (i = 0; i < s; ++i) { - item = PyTuple_GET_ITEM(tuple, i); - if (!PyString_Check(item)) { - PyErr_SetString(PyExc_ValueError, "expected a tuple of strings"); - goto binderror; - } - keylist = g_list_append(keylist, - g_strdup(PyString_AsString(item))); - } - - if (!(tree = buildtree(keylist))) { - PyErr_SetString(PyExc_ValueError, "invalid binding"); - goto binderror; - } - - t = find(tree, &conflict); - if (conflict) { - PyErr_SetString(PyExc_ValueError, "conflict with binding"); - goto binderror; - } - if (t != NULL) { - /* already bound to something */ - PyErr_SetString(PyExc_ValueError, "keychain is already bound"); - goto binderror; - } - - /* grab the server here to make sure no key pressed go missed */ - XGrabServer(ob_display); - XSync(ob_display, FALSE); - - grab_keys(FALSE); - - /* set the function */ - t = tree; - while (t->first_child) t = t->first_child; - t->func = func; - Py_INCREF(func); - - /* assimilate this built tree into the main tree */ - assimilate(tree); // assimilation destroys/uses the tree - - grab_keys(TRUE); - - XUngrabServer(ob_display); - XFlush(ob_display); - - for (it = keylist; it != NULL; it = it->next) - g_free(it->data); - g_list_free(it); - - Py_INCREF(Py_None); - return Py_None; - -binderror: - if (tree != NULL) destroytree(tree); - for (it = keylist; it != NULL; it = it->next) - g_free(it->data); - g_list_free(it); - return NULL; -} static PyObject *keyb_clearBinds(Keyboard *self, PyObject *args) {