all broken now. working on adding mouse binding support

This commit is contained in:
Dana Jansens 2002-12-30 16:42:15 +00:00
parent 9bf9567283
commit d4853f108c
7 changed files with 266 additions and 85 deletions

View file

@ -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
b.modifiers = modval;
if (askey) {
KeySym sym = XStringToKeysym(const_cast<char *>(key.c_str()));
if (sym == NoSymbol) return false;
b.modifiers = modval;
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
}
}
}
}

View file

@ -46,10 +46,13 @@ public:
typedef std::vector<std::string> 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

View file

@ -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();

View file

@ -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;

View file

@ -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 }
};

View file

@ -11,7 +11,8 @@ namespace ob {
typedef std::vector<PyObject*> 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;
}

View file

@ -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();