]> Dogcows Code - chaz/openbox/commitdiff
keybindings underway. dont work yet
authorDana Jansens <danakj@orodu.net>
Mon, 30 Dec 2002 06:31:45 +0000 (06:31 +0000)
committerDana Jansens <danakj@orodu.net>
Mon, 30 Dec 2002 06:31:45 +0000 (06:31 +0000)
src/Makefile.am
src/actions.cc
src/actions.hh
src/bindings.cc [new file with mode: 0644]
src/bindings.hh [new file with mode: 0644]
src/openbox.cc
src/openbox.hh
src/openbox.i
src/openbox_wrap.cc
src/python.cc
src/python.hh

index e406de3f5b98ef439bc7ca26b6c36c5afde74c70..a8995148e8d5be8a3068c332eab004a6d457916c 100644 (file)
@@ -19,7 +19,7 @@ openbox3_LDADD=-L../otk -lotk @LIBINTL@
 
 openbox3_SOURCES= actions.cc client.cc frame.cc openbox.cc screen.cc \
                   main.cc rootwindow.cc backgroundwidget.cc labelwidget.cc \
-                  buttonwidget.cc python.cc openbox_wrap.cc
+                  buttonwidget.cc python.cc bindings.cc openbox_wrap.cc
 
 MAINTAINERCLEANFILES= Makefile.in
 
index 0dbe46405128135b5cb874299242ecc88c190333..716b033bfbbaf122af7d685fc922541f0e804cac 100644 (file)
@@ -1,4 +1,4 @@
-// -*- mode: C++; indent-tabs-mode: nil; -*-
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
 
 #ifdef HAVE_CONFIG_H
 # include "../config.h"
index 4cf37ef1c5117bab919442118754a4e6cac82e12..f210f6ce9fa74ca6a74e3d327dfe8ceff9991964 100644 (file)
@@ -1,4 +1,4 @@
-// -*- mode: C++; indent-tabs-mode: nil; -*-
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
 #ifndef __actions_hh
 #define __actions_hh
 
diff --git a/src/bindings.cc b/src/bindings.cc
new file mode 100644 (file)
index 0000000..4bb651a
--- /dev/null
@@ -0,0 +1,257 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+
+#ifdef HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+#include "bindings.hh"
+#include "otk/display.hh"
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+namespace ob {
+
+#include <stdio.h>
+static void print_branch(BindingTree *first, std::string str)
+{
+  BindingTree *p = first;
+  
+  while (p) {
+    if (p->first_child)
+      print_branch(p->first_child, str + " " + p->text);
+    printf("%d%s\n", p->id, (str + " " + p->text).c_str());
+    BindingTree *s = p->next_sibling;
+    delete p;
+    p = s;
+  }
+}
+
+
+void OBBindings::display()
+{
+  if (_bindings.first_child)
+    print_branch(_bindings.first_child, "");
+}
+
+
+
+static bool translate(const std::string str, Binding &b)
+{
+  KeySym sym = XStringToKeysym(const_cast<char *>(str.c_str()));
+  if (sym == NoSymbol) return false;
+  b.modifiers = Mod1Mask;
+  b.key = XKeysymToKeycode(otk::OBDisplay::display, sym);
+  return b.key != 0;
+}
+
+static BindingTree *buildtree(const OBBindings::StringVect &keylist, int id)
+{
+  if (keylist.empty()) return 0; // nothing in the list.. return 0
+
+  BindingTree *ret = new BindingTree(id), *p = 0;
+
+  OBBindings::StringVect::const_iterator it, end = keylist.end();
+  for (it = keylist.begin(); it != end; ++it) {
+    if (p)
+      p = p->first_child = new BindingTree(id);
+    else
+      p = ret; // the first node
+    
+    if (!translate(*it, p->binding))
+      break;
+    p->text = *it;
+  }
+  if (it != end) {
+    // build failed.. clean up and return 0
+    p = ret;
+    while (p->first_child) {
+      BindingTree *c = p->first_child;
+      delete p;
+      p = c;      
+    }
+    delete p;
+    return 0;
+  } else {
+    // set the proper chain status on the last node
+    p->chain = false;
+  }
+
+  printf("<BUILDING>\n");
+  print_branch(ret);
+  printf("</BUILDING>\n");
+  
+  // successfully built a tree
+  return ret;
+}
+
+static void destroytree(BindingTree *tree)
+{
+  while (tree) {
+    BindingTree *c = tree->first_child;
+    delete tree;
+    tree = c;
+  }
+}
+
+OBBindings::OBBindings()
+{
+}
+
+
+OBBindings::~OBBindings()
+{
+  remove_all();
+}
+
+
+static void assimilate(BindingTree *parent, BindingTree *node)
+{
+  BindingTree *p, *lastsib, *nextparent, *nextnode = node->first_child;
+
+  if (!parent->first_child) {
+    // there are no nodes at this level yet
+    parent->first_child = node;
+    nextparent = node;
+  } else {
+    p = lastsib = parent->first_child;
+
+    while (p->next_sibling) {
+      p = p->next_sibling;
+      lastsib = p; // finds the last sibling
+      if (p->binding == node->binding) {
+       // found an identical binding..
+       assert(node->chain && p->chain);
+       delete node; // kill the one we aren't using
+       break;
+      }
+    }
+    if (!p) {
+      // couldn't find an existing binding, use this new one, and insert it
+      // into the list
+      p = lastsib->next_sibling = node;
+    }
+    nextparent = p;
+  }
+
+  if (nextnode)
+    assimilate(nextparent, nextnode);
+}
+
+
+static int find_bind(BindingTree *tree, BindingTree *search) {
+  BindingTree *a, *b;
+  a = tree;
+  b = search;
+  while (a && b) {
+    if (a->binding != b->binding) {
+      a = a->next_sibling;
+    } else {
+      if (a->chain == b->chain) {
+       if (!a->chain)
+         return a->id; // found it! (return the actual id, not the search's)
+      } else
+         return -2; // the chain status' don't match (conflict!)
+      b = b->first_child;
+      a = a->first_child;
+    }
+  }
+  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)
+{
+  BindingTree *tree;
+
+  if (!(tree = buildtree(keylist, id)))
+    return false; // invalid binding requested
+
+  if (find_bind(_bindings.first_child, tree) < -1) {
+    // conflicts with another binding
+    destroytree(tree);
+    return false;
+  }
+
+  // assimilate this built tree into the main tree
+  assimilate(&_bindings, tree); // assimilation destroys/uses the tree
+  return true;
+}
+
+
+int OBBindings::find(const StringVect &keylist)
+{
+  BindingTree *tree;
+  bool ret;
+
+  if (!(tree = buildtree(keylist, 0)))
+    return false; // invalid binding requested
+
+  ret = find_bind(_bindings.first_child, tree) >= 0;
+
+  destroytree(tree);
+
+  return ret;
+}
+
+
+int OBBindings::remove(const StringVect &keylist)
+{
+  (void)keylist;
+  assert(false); // XXX: function not implemented yet
+}
+
+
+static void remove_branch(BindingTree *first)
+{
+  BindingTree *p = first;
+
+  while (p) {
+    if (p->first_child)
+      remove_branch(p->first_child);
+    BindingTree *s = p->next_sibling;
+    delete p;
+    p = s;
+  }
+}
+
+
+void OBBindings::remove_all()
+{
+  if (_bindings.first_child)
+    remove_branch(_bindings.first_child);
+}
+
+}
diff --git a/src/bindings.hh b/src/bindings.hh
new file mode 100644 (file)
index 0000000..70b2326
--- /dev/null
@@ -0,0 +1,91 @@
+// -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
+#ifndef __binding_hh
+#define __binding_hh
+
+/*! @file binding.hh
+  @brief I dunno.. some binding stuff?
+*/
+
+#include <string>
+#include <vector>
+
+namespace ob {
+
+typedef struct Binding {
+  unsigned int modifiers;
+  unsigned int key;
+
+  bool operator==(struct Binding &b2) { return key == b2.key &&
+                                         modifiers == b2.modifiers; }
+  bool operator!=(struct Binding &b2) { return key != b2.key ||
+                                         modifiers != b2.modifiers; }
+  Binding(unsigned int mod, unsigned int k) { modifiers = mod; key = k; }
+} Binding;
+
+typedef struct BindingTree {
+  Binding binding;
+  std::string text;
+  int id;     // the id given for the binding in add()
+  bool chain; // true if this is a chain to another key (not an action)
+
+  struct BindingTree *next_sibling; // the next binding in the tree at the same
+                                    // level
+  struct BindingTree *first_child;  // the first child of this binding (next
+                                    // binding in a chained sequence).
+  BindingTree(int id) : binding(0, 0) {
+    this->id = id; chain = true; next_sibling = first_child = 0;
+  }
+  BindingTree() : binding(0, 0) {
+    this->id = -1; chain = true; next_sibling = first_child = 0;
+  }
+} BindingTree;
+
+class OBBindings {
+public:
+  //! A list of strings
+  typedef std::vector<std::string> StringVect;
+
+private:
+  BindingTree _bindings;// root nodes (these dont have siblings!)
+
+public:
+  //! Initializes an OBBinding object
+  OBBindings();
+  //! Destroys the OBBinding object
+  virtual ~OBBindings();
+
+  //! Adds a new 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);
+
+  //! Removes a key binding
+  /*!
+    @return The id of the binding that was removed, or '< 0' if none were
+            removed.
+  */
+  int remove(const StringVect &keylist);
+
+  //! Removes all key bindings
+  void remove_all();
+
+  //! Finds a keybinding and returns its id or '< 0' if it isn't found.
+  /*!
+    @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);
+
+  // 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
+  //      for reseting too...)
+
+  void display();
+};
+
+}
+
+#endif // __binding_hh
index ad31718359a335c69c65d1d27ba7f00354e5de4c..952fca51dfaf7103a481ac40325dfba2d40ea4f2 100644 (file)
@@ -9,6 +9,7 @@
 #include "client.hh"
 #include "screen.hh"
 #include "actions.hh"
+#include "bindings.hh"
 #include "otk/property.hh"
 #include "otk/display.hh"
 #include "otk/assassin.hh"
@@ -145,8 +146,22 @@ Openbox::Openbox(int argc, char **argv)
   sigaction(SIGHUP, &action, (struct sigaction *) 0);
 
   _property = new otk::OBProperty();
-
   _actions = new OBActions();
+  _bindings = new OBBindings();
+
+  OBBindings::StringVect v;
+//  v.push_back("C-x");
+//  v.push_back("C-y");
+  v.push_back("v");
+  _bindings->add(v, 1);
+  v.clear();
+//  v.push_back("C-x");
+//  v.push_back("C-z");
+  v.push_back("a");
+  _bindings->add(v, 2);
+
+  _bindings->display();
+  ::exit(0);
 
   setMasterHandler(_actions); // set as the master event handler
 
@@ -198,6 +213,10 @@ Openbox::~Openbox()
   _state = State_Exiting; // time to kill everything
 
   std::for_each(_screens.begin(), _screens.end(), otk::PointerAssassin());
+
+  delete _bindings;
+  delete _actions;
+  delete _property;
   
   // close the X display
   otk::OBDisplay::destroy();
index 976a49774ed2261cc51370d147d6accc3c812a9f..d64068f14a9f88dec74d09087140fd0c20c40246 100644 (file)
@@ -30,6 +30,7 @@ namespace ob {
 class OBScreen;
 class OBClient;
 class OBActions;
+class OBBindings;
 
 //! Mouse cursors used throughout Openbox
 struct Cursors {
@@ -121,6 +122,9 @@ private:
   //! The action interface through which all user-available actions occur
   OBActions *_actions;
 
+  //! The interface through which keys/buttons are grabbed and handled
+  OBBindings *_bindings;
+
   //! Run the application in synchronous mode? (for debugging)
   bool _sync;
 
@@ -184,6 +188,9 @@ public:
   //! Returns the otk::OBProperty instance for the window manager
   inline const otk::OBProperty *property() const { return _property; }
 
+  //! Returns the OBBinding instance for the window manager
+  inline OBBindings *bindings() const { return _bindings; }
+
   //! Returns a managed screen
   inline OBScreen *screen(int num) {
     assert(num >= 0); assert(num < (signed)_screens.size());
index 4d11507c388ede9a631b0fe274c20680c837793d..d4b83575e31bdc49d8e21ab32f5aa8571e195f82 100644 (file)
@@ -56,6 +56,9 @@
 %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(unbind_all) ob::python_unbind_all;
 
 %ignore ob::OBScreen::clients;
 %{
index 8337d1ee5709541c3501e26e22a4a5c6750bc088..f9945024791a0d64e7089d2749de3559446dd015 100644 (file)
@@ -667,10 +667,11 @@ SWIG_InstallConstants(PyObject *d, swig_const_info constants[]) {
 #define  SWIGTYPE_p_XDestroyWindowEvent swig_types[19] 
 #define  SWIGTYPE_p_otk__BImageControl swig_types[20] 
 #define  SWIGTYPE_p_PyObject swig_types[21] 
-#define  SWIGTYPE_p_ob__MwmHints swig_types[22] 
-#define  SWIGTYPE_p_otk__Configuration swig_types[23] 
-#define  SWIGTYPE_p_XUnmapEvent swig_types[24] 
-static swig_type_info *swig_types[26];
+#define  SWIGTYPE_p_ob__OBBindings swig_types[22] 
+#define  SWIGTYPE_p_ob__MwmHints swig_types[23] 
+#define  SWIGTYPE_p_otk__Configuration swig_types[24] 
+#define  SWIGTYPE_p_XUnmapEvent swig_types[25] 
+static swig_type_info *swig_types[27];
 
 /* -------- TYPES TABLE (END) -------- */
 
@@ -1112,6 +1113,23 @@ static PyObject *_wrap_Openbox_property(PyObject *self, PyObject *args) {
 }
 
 
+static PyObject *_wrap_Openbox_bindings(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    ob::Openbox *arg1 = (ob::Openbox *) 0 ;
+    ob::OBBindings *result;
+    PyObject * obj0  = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"O:Openbox_bindings",&obj0)) goto fail;
+    if ((SWIG_ConvertPtr(obj0,(void **) &arg1, SWIGTYPE_p_ob__Openbox,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail;
+    result = (ob::OBBindings *)((ob::Openbox const *)arg1)->bindings();
+    
+    resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE_p_ob__OBBindings, 0);
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyObject *_wrap_Openbox_screen(PyObject *self, PyObject *args) {
     PyObject *resultobj;
     ob::Openbox *arg1 = (ob::Openbox *) 0 ;
@@ -2551,6 +2569,57 @@ static PyObject *_wrap_unregister_all(PyObject *self, PyObject *args) {
 }
 
 
+static PyObject *_wrap_bind(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    PyObject *arg1 = (PyObject *) 0 ;
+    PyObject *arg2 = (PyObject *) 0 ;
+    bool result;
+    PyObject * obj0  = 0 ;
+    PyObject * obj1  = 0 ;
+    
+    if(!PyArg_ParseTuple(args,(char *)"OO:bind",&obj0,&obj1)) goto fail;
+    arg1 = obj0;
+    arg2 = obj1;
+    result = (bool)ob::python_bind(arg1,arg2);
+    
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
+static PyObject *_wrap_unbind(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;
+    arg1 = obj0;
+    result = (bool)ob::python_unbind(arg1);
+    
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
+static PyObject *_wrap_unbind_all(PyObject *self, PyObject *args) {
+    PyObject *resultobj;
+    bool result;
+    
+    if(!PyArg_ParseTuple(args,(char *)":unbind_all")) goto fail;
+    result = (bool)ob::python_unbind_all();
+    
+    resultobj = PyInt_FromLong((long)result);
+    return resultobj;
+    fail:
+    return NULL;
+}
+
+
 static PyMethodDef SwigMethods[] = {
         { (char *)"Openbox_instance", _wrap_Openbox_instance, METH_VARARGS },
         { (char *)"Cursors_session_set", _wrap_Cursors_session_set, METH_VARARGS },
@@ -2569,6 +2638,7 @@ static PyMethodDef SwigMethods[] = {
         { (char *)"Openbox_state", _wrap_Openbox_state, METH_VARARGS },
         { (char *)"Openbox_timerManager", _wrap_Openbox_timerManager, METH_VARARGS },
         { (char *)"Openbox_property", _wrap_Openbox_property, METH_VARARGS },
+        { (char *)"Openbox_bindings", _wrap_Openbox_bindings, METH_VARARGS },
         { (char *)"Openbox_screen", _wrap_Openbox_screen, METH_VARARGS },
         { (char *)"Openbox_screenCount", _wrap_Openbox_screenCount, METH_VARARGS },
         { (char *)"Openbox_cursors", _wrap_Openbox_cursors, METH_VARARGS },
@@ -2649,6 +2719,9 @@ 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 *)"unbind_all", _wrap_unbind_all, METH_VARARGS },
         { NULL, NULL }
 };
 
@@ -2689,6 +2762,7 @@ static swig_type_info _swigt__p_XPropertyEvent[] = {{"_p_XPropertyEvent", 0, "XP
 static swig_type_info _swigt__p_XDestroyWindowEvent[] = {{"_p_XDestroyWindowEvent", 0, "XDestroyWindowEvent *", 0},{"_p_XDestroyWindowEvent"},{0}};
 static swig_type_info _swigt__p_otk__BImageControl[] = {{"_p_otk__BImageControl", 0, "otk::BImageControl *", 0},{"_p_otk__BImageControl"},{0}};
 static swig_type_info _swigt__p_PyObject[] = {{"_p_PyObject", 0, "PyObject *", 0},{"_p_PyObject"},{0}};
+static swig_type_info _swigt__p_ob__OBBindings[] = {{"_p_ob__OBBindings", 0, "ob::OBBindings *", 0},{"_p_ob__OBBindings"},{0}};
 static swig_type_info _swigt__p_ob__MwmHints[] = {{"_p_ob__MwmHints", 0, "ob::MwmHints *", 0},{"_p_ob__MwmHints"},{0}};
 static swig_type_info _swigt__p_otk__Configuration[] = {{"_p_otk__Configuration", 0, "otk::Configuration *", 0},{"_p_otk__Configuration"},{0}};
 static swig_type_info _swigt__p_XUnmapEvent[] = {{"_p_XUnmapEvent", 0, "XUnmapEvent *", 0},{"_p_XUnmapEvent"},{0}};
@@ -2716,6 +2790,7 @@ _swigt__p_XPropertyEvent,
 _swigt__p_XDestroyWindowEvent, 
 _swigt__p_otk__BImageControl, 
 _swigt__p_PyObject, 
+_swigt__p_ob__OBBindings, 
 _swigt__p_ob__MwmHints, 
 _swigt__p_otk__Configuration, 
 _swigt__p_XUnmapEvent, 
index ed171f9cc4880659e2f3642dd310b606964751d4..8f2e4f5ad701689f68193b34e699809abb9562c0 100644 (file)
@@ -1,6 +1,7 @@
 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
 
 #include "python.hh"
+#include "openbox.hh"
 
 #include <vector>
 #include <algorithm>
@@ -10,6 +11,7 @@ namespace ob {
 typedef std::vector<PyObject*> FunctionList;
 
 static FunctionList callbacks[OBActions::NUM_ACTIONS];
+static FunctionList bindfuncs;
 
 bool python_register(int action, PyObject *callback)
 {
@@ -125,4 +127,83 @@ void python_callback(OBActions::ActionType action, Window window,
   Py_DECREF(arglist);
 }
 
+
+
+
+
+
+bool python_bind(PyObject *keylist, PyObject *callback)
+{
+  if (!PyList_Check(keylist)) {
+    PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
+    return false;
+  }
+  if (!PyCallable_Check(callback)) {
+    PyErr_SetString(PyExc_AssertionError, "Invalid callback function.");
+    return false;
+  }
+
+  OBBindings::StringVect vectkeylist;
+  for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
+    PyObject *str = PyList_GetItem(keylist, i);
+    if (!PyString_Check(str)) {
+      PyErr_SetString(PyExc_AssertionError,
+                      "Invalid keylist. It must contain only strings.");
+      return false;
+    }
+    vectkeylist.push_back(PyString_AsString(str));
+  }
+
+  // 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)) {
+    Py_XINCREF(callback);              // Add a reference to new callback
+    bindfuncs.push_back(callback);
+    return true;
+  } else {
+    PyErr_SetString(PyExc_AssertionError,"Unable to create binding. Invalid.");
+    return false;
+  }
+}
+
+bool python_unbind(PyObject *keylist)
+{
+  if (!PyList_Check(keylist)) {
+    PyErr_SetString(PyExc_AssertionError, "Invalid keylist. Not a list.");
+    return false;
+  }
+
+  OBBindings::StringVect vectkeylist;
+  for (int i = 0, end = PyList_Size(keylist); i < end; ++i) {
+    PyObject *str = PyList_GetItem(keylist, i);
+    if (!PyString_Check(str)) {
+      PyErr_SetString(PyExc_AssertionError,
+                      "Invalid keylist. It must contain only strings.");
+      return false;
+    }
+    vectkeylist.push_back(PyString_AsString(str));
+  }
+
+  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
+    // 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;
+    return true;
+  }
+  
+  return false;
+}
+
+bool python_unbind_all()
+{
+  Openbox::instance->bindings()->remove_all();
+  return true;
+}
+
+
 }
index 496b459de27682ba46879d170be490dcba4d9448..8a1bb16135936b3af552cabe77270798f0397f44 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "actions.hh"
 #include "widget.hh"
+#include "bindings.hh"
 
 extern "C" {
 #include <Python.h>
@@ -25,6 +26,18 @@ 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
+/*!
+  @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_unbind(PyObject *keylist);
+
+bool python_unbind_all();
+
 //! Fire a python callback function
 void python_callback(OBActions::ActionType action, Window window,
                      OBWidget::WidgetType type, unsigned int state,
This page took 0.048017 seconds and 4 git commands to generate.