From d4853f108c1d22c344c1cb9a8a8b7cdc46648983 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 30 Dec 2002 16:42:15 +0000 Subject: [PATCH] all broken now. working on adding mouse binding support --- src/bindings.cc | 166 ++++++++++++++++++++++++++++++-------------- src/bindings.hh | 34 +++++++-- src/openbox.cc | 6 +- src/openbox.i | 6 +- src/openbox_wrap.cc | 71 ++++++++++++++++--- src/python.cc | 57 ++++++++++++--- src/python.hh | 11 ++- 7 files changed, 266 insertions(+), 85 deletions(-) diff --git a/src/bindings.cc b/src/bindings.cc index ee479d5e..8f474b37 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -33,11 +33,38 @@ static void print_branch(BindingTree *first, std::string str) void OBBindings::display() { - if (_tree.first_child) - print_branch(_tree.first_child, ""); + if (_keytree.first_child) { + printf("Key Tree:\n"); + print_branch(_keytree.first_child, ""); + } + if (_mousetree.next_sibling) { + printf("Mouse Tree:\n"); + BindingTree *p = _mousetree.next_sibling; + while (p) { + printf("%d %s\n", p->id, p->text.c_str()); + p = p->next_sibling; + } + } } +static bool buttonvalue(const std::string &button, unsigned int *val) +{ + if (button == "1" || button == "Button1") { + *val |= Button1; + } else if (button == "2" || button == "Button2") { + *val |= Button2; + } else if (button == "3" || button == "Button3") { + *val |= Button3; + } else if (button == "4" || button == "Button4") { + *val |= Button4; + } else if (button == "5" || button == "Button5") { + *val |= Button5; + } else + return false; + return true; +} + static bool modvalue(const std::string &mod, unsigned int *val) { if (mod == "C") { // control @@ -68,7 +95,7 @@ static bool modvalue(const std::string &mod, unsigned int *val) return true; } -bool OBBindings::translate(const std::string &str, Binding &b) +bool OBBindings::translate(const std::string &str, Binding &b, bool askey) { // parse out the base key name std::string::size_type keybegin = str.find_last_of('-'); @@ -83,7 +110,7 @@ bool OBBindings::translate(const std::string &str, Binding &b) std::string mod(str, begin, end-begin); if (!modvalue(mod, &modval)) { - printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str()); +// printf(_("Invalid modifier element in key binding: %s\n"), mod.c_str()); return false; } @@ -91,11 +118,15 @@ bool OBBindings::translate(const std::string &str, Binding &b) } // set the binding - KeySym sym = XStringToKeysym(const_cast(key.c_str())); - if (sym == NoSymbol) return false; b.modifiers = modval; - b.key = XKeysymToKeycode(otk::OBDisplay::display, sym); - return b.key != 0; + if (askey) { + KeySym sym = XStringToKeysym(const_cast(key.c_str())); + if (sym == NoSymbol) return false; + b.key = XKeysymToKeycode(otk::OBDisplay::display, sym); + return b.key != 0; + } else { + return buttonvalue(key, &b.key); + } } static void destroytree(BindingTree *tree) @@ -119,7 +150,7 @@ BindingTree *OBBindings::buildtree(const StringVect &keylist, int id) ret = new BindingTree(id); if (!p) ret->chain = false; ret->first_child = p; - if (!translate(*it, ret->binding)) { + if (!translate(*it, ret->binding, true)) { destroytree(ret); ret = 0; break; @@ -131,6 +162,7 @@ BindingTree *OBBindings::buildtree(const StringVect &keylist, int id) OBBindings::OBBindings() + : _curpos(&_keytree) { } @@ -141,16 +173,48 @@ OBBindings::~OBBindings() } +bool OBBindings::add_mouse(const std::string &button, int id) +{ + BindingTree n; + + if (!translate(button, n.binding, false)) + return false; + + BindingTree *p = _mousetree.next_sibling, *last = &_mousetree; + while (p) { + if (p->binding == n.binding) + return false; // conflict + last = p; + p = p->next_sibling; + } + display(); + last->next_sibling = new BindingTree(id); + display(); + last->next_sibling->chain = false; + last->next_sibling->binding.key = n.binding.key; + last->next_sibling->binding.modifiers = n.binding.modifiers; + + return true; +} + + +int OBBindings::remove_mouse(const std::string &button) +{ + (void)button; + assert(false); // XXX: function not implemented yet +} + + void OBBindings::assimilate(BindingTree *node) { BindingTree *a, *b, *tmp, *last; - if (!_tree.first_child) { + if (!_keytree.first_child) { // there are no nodes at this level yet - _tree.first_child = node; + _keytree.first_child = node; return; } else { - a = _tree.first_child; + a = _keytree.first_child; last = a; b = node; while (a) { @@ -173,9 +237,9 @@ void OBBindings::assimilate(BindingTree *node) } -int OBBindings::find(BindingTree *search) { +int OBBindings::find_key(BindingTree *search) { BindingTree *a, *b; - a = _tree.first_child; + a = _keytree.first_child; b = search; while (a && b) { if (a->binding != b->binding) { @@ -193,46 +257,14 @@ int OBBindings::find(BindingTree *search) { return -1; // it just isn't in here } -/* -static int find(BindingTree *parent, BindingTree *node) { - BindingTree *p, *lastsib, *nextparent, *nextnode = node->first_child; - - if (!parent->first_child) - return -1; - - p = parent->first_child; - while (p) { - if (node->binding == p->binding) { - if (node->chain == p->chain) { - if (!node->chain) { - return p->id; // found it! (return the actual id, not the search's) - } else { - break; // go on to the next child in the chain - } - } else { - return -2; // the chain status' don't match (conflict!) - } - } - p = p->next_sibling; - } - if (!p) return -1; // doesn't exist - - if (node->chain) { - assert(node->first_child); - return find(p, node->first_child); - } else - return -1; // it just isnt in here -} -*/ - -bool OBBindings::add(const StringVect &keylist, int id) +bool OBBindings::add_key(const StringVect &keylist, int id) { BindingTree *tree; if (!(tree = buildtree(keylist, id))) return false; // invalid binding requested - if (find(tree) < -1) { + if (find_key(tree) < -1) { // conflicts with another binding destroytree(tree); return false; @@ -244,7 +276,7 @@ bool OBBindings::add(const StringVect &keylist, int id) } -int OBBindings::find(const StringVect &keylist) +int OBBindings::find_key(const StringVect &keylist) { BindingTree *tree; bool ret; @@ -252,7 +284,7 @@ int OBBindings::find(const StringVect &keylist) if (!(tree = buildtree(keylist, 0))) return false; // invalid binding requested - ret = find(tree) >= 0; + ret = find_key(tree) >= 0; destroytree(tree); @@ -260,7 +292,7 @@ int OBBindings::find(const StringVect &keylist) } -int OBBindings::remove(const StringVect &keylist) +int OBBindings::remove_key(const StringVect &keylist) { (void)keylist; assert(false); // XXX: function not implemented yet @@ -283,8 +315,36 @@ static void remove_branch(BindingTree *first) void OBBindings::remove_all() { - if (_tree.first_child) - remove_branch(_tree.first_child); + if (_keytree.first_child) { + remove_branch(_keytree.first_child); + _keytree.first_child = 0; + } + BindingTree *p = _mousetree.next_sibling; + while (p) { + BindingTree *n = p->next_sibling; + delete p; + p = n; + } + _mousetree.next_sibling = 0; +} + + +void OBBindings::process(unsigned int modifiers, unsigned int key) +{ + BindingTree *c = _curpos->first_child; + + while (c) { + if (c->binding.key == key && c->binding.modifiers == modifiers) { + _curpos = c; + break; + } + } + if (c) { + if (!_curpos->chain) { + // XXX execute command for _curpos->id + _curpos = &_keytree; // back to the start + } + } } } diff --git a/src/bindings.hh b/src/bindings.hh index ffe987b3..e4bd65f3 100644 --- a/src/bindings.hh +++ b/src/bindings.hh @@ -46,10 +46,13 @@ public: typedef std::vector StringVect; private: - BindingTree _tree;// root node of the tree (this doesn't have siblings!) + BindingTree _keytree; // root node of the tree (this doesn't have siblings!) + BindingTree *_curpos; // position in the keytree - int find(BindingTree *search); - bool translate(const std::string &str, Binding &b); + BindingTree _mousetree; // this tree is a list. it has only siblings + + int find_key(BindingTree *search); + bool translate(const std::string &str, Binding &b, bool askey); BindingTree *buildtree(const StringVect &keylist, int id); void OBBindings::assimilate(BindingTree *node); @@ -59,20 +62,35 @@ public: //! Destroys the OBBinding object virtual ~OBBindings(); - //! Adds a new binding + //! Adds a new mouse binding + /*! + A binding will fail to be added if the binding already exists, or if the + string is invalid. + @return true if the binding could be added; false if it could not. + */ + bool add_mouse(const std::string &button, int id); + + //! Removes a mouse binding + /*! + @return The id of the binding that was removed, or '< 0' if none were + removed. + */ + int remove_mouse(const std::string &button); + + //! Adds a new key binding /*! A binding will fail to be added if the binding already exists (as part of a chain or not), or if any of the strings in the keylist are invalid. @return true if the binding could be added; false if it could not. */ - bool add(const StringVect &keylist, int id); + bool add_key(const StringVect &keylist, int id); //! Removes a key binding /*! @return The id of the binding that was removed, or '< 0' if none were removed. */ - int remove(const StringVect &keylist); + int remove_key(const StringVect &keylist); //! Removes all key bindings void remove_all(); @@ -82,7 +100,9 @@ public: @return -1 if the keybinding was not found but does not conflict with any others; -2 if the keybinding conflicts with another. */ - int find(const StringVect &keylist); + int find_key(const StringVect &keylist); + + void process(unsigned int modifiers, unsigned int key); // XXX: need an exec() function or something that will be used by openbox // and hold state for which chain we're in etc. (it could have a timer diff --git a/src/openbox.cc b/src/openbox.cc index cf05e2a8..69092eca 100644 --- a/src/openbox.cc +++ b/src/openbox.cc @@ -153,12 +153,14 @@ Openbox::Openbox(int argc, char **argv) v.push_back("C-A-x"); v.push_back("C-y"); v.push_back("v"); - _bindings->add(v, 1); + _bindings->add_key(v, 1); v.clear(); // v.push_back("C-x"); // v.push_back("C-z"); v.push_back("a"); - _bindings->add(v, 2); + _bindings->add_key(v, 2); + + _bindings->add_mouse("A-1", 1); printf("CHAINS:\n"); _bindings->display(); diff --git a/src/openbox.i b/src/openbox.i index d4b83575..74ed3010 100644 --- a/src/openbox.i +++ b/src/openbox.i @@ -56,8 +56,10 @@ %rename(preregister) ob::python_preregister; %rename(unregister) ob::python_unregister; %rename(unregister_all) ob::python_unregister_all; -%rename(bind) ob::python_bind; -%rename(unbind) ob::python_unbind; +%rename(bind_key) ob::python_bind_key; +%rename(unbind_key) ob::python_unbind_key; +%rename(bind_mouse) ob::python_bind_mouse; +%rename(unbind_mouse) ob::python_unbind_mouse; %rename(unbind_all) ob::python_unbind_all; %ignore ob::OBScreen::clients; diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc index f9945024..118fe1af 100644 --- a/src/openbox_wrap.cc +++ b/src/openbox_wrap.cc @@ -2569,7 +2569,7 @@ static PyObject *_wrap_unregister_all(PyObject *self, PyObject *args) { } -static PyObject *_wrap_bind(PyObject *self, PyObject *args) { +static PyObject *_wrap_bind_key(PyObject *self, PyObject *args) { PyObject *resultobj; PyObject *arg1 = (PyObject *) 0 ; PyObject *arg2 = (PyObject *) 0 ; @@ -2577,10 +2577,10 @@ static PyObject *_wrap_bind(PyObject *self, PyObject *args) { PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; - if(!PyArg_ParseTuple(args,(char *)"OO:bind",&obj0,&obj1)) goto fail; + if(!PyArg_ParseTuple(args,(char *)"OO:bind_key",&obj0,&obj1)) goto fail; arg1 = obj0; arg2 = obj1; - result = (bool)ob::python_bind(arg1,arg2); + result = (bool)ob::python_bind_key(arg1,arg2); resultobj = PyInt_FromLong((long)result); return resultobj; @@ -2589,15 +2589,68 @@ static PyObject *_wrap_bind(PyObject *self, PyObject *args) { } -static PyObject *_wrap_unbind(PyObject *self, PyObject *args) { +static PyObject *_wrap_unbind_key(PyObject *self, PyObject *args) { PyObject *resultobj; PyObject *arg1 = (PyObject *) 0 ; bool result; PyObject * obj0 = 0 ; - if(!PyArg_ParseTuple(args,(char *)"O:unbind",&obj0)) goto fail; + if(!PyArg_ParseTuple(args,(char *)"O:unbind_key",&obj0)) goto fail; arg1 = obj0; - result = (bool)ob::python_unbind(arg1); + result = (bool)ob::python_unbind_key(arg1); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_bind_mouse(PyObject *self, PyObject *args) { + PyObject *resultobj; + std::string *arg1 = 0 ; + PyObject *arg2 = (PyObject *) 0 ; + bool result; + std::string temp1 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"OO:bind_mouse",&obj0,&obj1)) goto fail; + { + if (PyString_Check(obj0)) { + temp1 = std::string(PyString_AsString(obj0)); + arg1 = &temp1; + }else { + SWIG_exception(SWIG_TypeError, "string expected"); + } + } + arg2 = obj1; + result = (bool)ob::python_bind_mouse((std::string const &)*arg1,arg2); + + resultobj = PyInt_FromLong((long)result); + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_unbind_mouse(PyObject *self, PyObject *args) { + PyObject *resultobj; + std::string *arg1 = 0 ; + bool result; + std::string temp1 ; + PyObject * obj0 = 0 ; + + if(!PyArg_ParseTuple(args,(char *)"O:unbind_mouse",&obj0)) goto fail; + { + if (PyString_Check(obj0)) { + temp1 = std::string(PyString_AsString(obj0)); + arg1 = &temp1; + }else { + SWIG_exception(SWIG_TypeError, "string expected"); + } + } + result = (bool)ob::python_unbind_mouse((std::string const &)*arg1); resultobj = PyInt_FromLong((long)result); return resultobj; @@ -2719,8 +2772,10 @@ static PyMethodDef SwigMethods[] = { { (char *)"preregister", _wrap_preregister, METH_VARARGS }, { (char *)"unregister", _wrap_unregister, METH_VARARGS }, { (char *)"unregister_all", _wrap_unregister_all, METH_VARARGS }, - { (char *)"bind", _wrap_bind, METH_VARARGS }, - { (char *)"unbind", _wrap_unbind, METH_VARARGS }, + { (char *)"bind_key", _wrap_bind_key, METH_VARARGS }, + { (char *)"unbind_key", _wrap_unbind_key, METH_VARARGS }, + { (char *)"bind_mouse", _wrap_bind_mouse, METH_VARARGS }, + { (char *)"unbind_mouse", _wrap_unbind_mouse, METH_VARARGS }, { (char *)"unbind_all", _wrap_unbind_all, METH_VARARGS }, { NULL, NULL } }; diff --git a/src/python.cc b/src/python.cc index 8f2e4f5a..ed71463c 100644 --- a/src/python.cc +++ b/src/python.cc @@ -11,7 +11,8 @@ namespace ob { typedef std::vector FunctionList; static FunctionList callbacks[OBActions::NUM_ACTIONS]; -static FunctionList bindfuncs; +static FunctionList keyfuncs; +static FunctionList mousefuncs; bool python_register(int action, PyObject *callback) { @@ -132,7 +133,7 @@ void python_callback(OBActions::ActionType action, Window window, -bool python_bind(PyObject *keylist, PyObject *callback) +bool python_bind_key(PyObject *keylist, PyObject *callback) { if (!PyList_Check(keylist)) { PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list."); @@ -156,10 +157,10 @@ bool python_bind(PyObject *keylist, PyObject *callback) // the id is what the binding class can call back with so it doesnt have to // worry about the python function pointer - int id = bindfuncs.size(); - if (Openbox::instance->bindings()->add(vectkeylist, id)) { + int id = keyfuncs.size(); + if (Openbox::instance->bindings()->add_key(vectkeylist, id)) { Py_XINCREF(callback); // Add a reference to new callback - bindfuncs.push_back(callback); + keyfuncs.push_back(callback); return true; } else { PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid."); @@ -167,7 +168,7 @@ bool python_bind(PyObject *keylist, PyObject *callback) } } -bool python_unbind(PyObject *keylist) +bool python_unbind_key(PyObject *keylist) { if (!PyList_Check(keylist)) { PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list."); @@ -187,12 +188,48 @@ bool python_unbind(PyObject *keylist) int id; if ((id = - Openbox::instance->bindings()->remove(vectkeylist)) >= 0) { - assert(bindfuncs[id]); // shouldn't be able to remove it twice - Py_XDECREF(bindfuncs[id]); // Dispose of previous callback + Openbox::instance->bindings()->remove_key(vectkeylist)) >= 0) { + assert(keyfuncs[id]); // shouldn't be able to remove it twice + Py_XDECREF(keyfuncs[id]); // Dispose of previous callback // important note: we don't erase the item from the list cuz that would // ruin all the id's that are in use. simply nullify it. - bindfuncs[id] = 0; + keyfuncs[id] = 0; + return true; + } + + return false; +} + +bool python_bind_mouse(const std::string &button, PyObject *callback) +{ + if (!PyCallable_Check(callback)) { + PyErr_SetString(PyExc_AssertionError, "Invalid callback function."); + return false; + } + + // the id is what the binding class can call back with so it doesnt have to + // worry about the python function pointer + int id = mousefuncs.size(); + if (Openbox::instance->bindings()->add_mouse(button, id)) { + Py_XINCREF(callback); // Add a reference to new callback + mousefuncs.push_back(callback); + return true; + } else { + PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid."); + return false; + } +} + +bool python_unbind_mouse(const std::string &button) +{ + int id; + if ((id = + Openbox::instance->bindings()->remove_mouse(button)) >= 0) { + assert(mousefuncs[id]); // shouldn't be able to remove it twice + Py_XDECREF(mousefuncs[id]); // Dispose of previous callback + // important note: we don't erase the item from the list cuz that would + // ruin all the id's that are in use. simply nullify it. + mousefuncs[id] = 0; return true; } diff --git a/src/python.hh b/src/python.hh index 8a1bb161..2332add0 100644 --- a/src/python.hh +++ b/src/python.hh @@ -26,15 +26,20 @@ bool python_unregister(int action, PyObject *callback); //! Removes all python callback functions from the hook list bool python_unregister_all(int action); -//! Add a mouse/keybinding +//! Add a keybinding /*! @param keylist A python list of modifier/key/buttons, in the form: "C-A-space" or "A-Button1" etc. @param callback A python function to call when the binding is used. */ -bool python_bind(PyObject *keylist, PyObject *callback); +bool python_bind_key(PyObject *keylist, PyObject *callback); -bool python_unbind(PyObject *keylist); +bool python_unbind_key(PyObject *keylist); + +//! Adds a mouse binding +bool python_bind_mouse(const std::string &button, PyObject *callback); + +bool python_unbind_mouse(const std::string &button); bool python_unbind_all(); -- 2.39.2