summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-01-03 21:36:09 +0000
committerDana Jansens <danakj@orodu.net>2003-01-03 21:36:09 +0000
commita0350e27b311db5cab49035752d3852ee68bf8a2 (patch)
tree1d53117e9998e39701e296c03bed9b27b1e8af36 /src
parent86a2bed6595cdc926dccb4a7c0f984fd5996e3c2 (diff)
allow "event bindings" via ebind() for new windows/window enter/leave
Diffstat (limited to 'src')
-rw-r--r--src/actions.cc131
-rw-r--r--src/actions.hh39
-rw-r--r--src/openbox.i2
-rw-r--r--src/openbox_wrap.cc34
-rw-r--r--src/python.cc106
-rw-r--r--src/python.hh29
6 files changed, 169 insertions, 172 deletions
diff --git a/src/actions.cc b/src/actions.cc
index ffa0a8f0..00d4c1bf 100644
--- a/src/actions.cc
+++ b/src/actions.cc
@@ -16,7 +16,6 @@
namespace ob {
-const unsigned int OBActions::DOUBLECLICKDELAY = 300;
const int OBActions::BUTTONS;
OBActions::OBActions()
@@ -24,6 +23,9 @@ OBActions::OBActions()
{
for (int i=0; i<BUTTONS; ++i)
_posqueue[i] = new ButtonPressAction();
+
+ for (int i = 0; i < NUM_EVENTS; ++i)
+ _callback[i] = 0;
}
@@ -116,7 +118,12 @@ void OBActions::buttonReleaseHandler(const XButtonEvent &e)
Openbox::instance->bindings()->fireButton(data);
- if (e.time - _release.time < DOUBLECLICKDELAY &&
+ // XXX: dont load this every time!!@*
+ long dblclick;
+ if (!python_get_long("double_click_delay", &dblclick))
+ dblclick = 300;
+
+ if (e.time - _release.time < (unsigned)dblclick &&
_release.win == e.window && _release.button == e.button) {
// run the DOUBLECLICK python hook
@@ -142,12 +149,12 @@ void OBActions::enterHandler(const XCrossingEvent &e)
{
OtkEventHandler::enterHandler(e);
- OBWidget *w = dynamic_cast<OBWidget*>
- (Openbox::instance->findHandler(e.window));
-
// run the ENTER python hook
- doCallback(Action_EnterWindow, e.window,
- (OBWidget::WidgetType)(w ? w->type():-1), e.state, 0, 0, 0, 0);
+ if (_callback[EventEnterWindow]) {
+ EventData *data = new_event_data(e.window, EventEnterWindow, e.state);
+ python_callback(_callback[EventEnterWindow], (PyObject*)data);
+ Py_DECREF((PyObject*)data);
+ }
}
@@ -155,19 +162,18 @@ void OBActions::leaveHandler(const XCrossingEvent &e)
{
OtkEventHandler::leaveHandler(e);
- OBWidget *w = dynamic_cast<OBWidget*>
- (Openbox::instance->findHandler(e.window));
-
// run the LEAVE python hook
- doCallback(Action_LeaveWindow, e.window,
- (OBWidget::WidgetType)(w ? w->type():-1), e.state, 0, 0, 0, 0);
+ if (_callback[EventLeaveWindow]) {
+ EventData *data = new_event_data(e.window, EventLeaveWindow, e.state);
+ python_callback(_callback[EventLeaveWindow], (PyObject*)data);
+ Py_DECREF((PyObject*)data);
+ }
}
void OBActions::keyPressHandler(const XKeyEvent &e)
{
-// OBWidget *w = dynamic_cast<OBWidget*>
-// (Openbox::instance->findHandler(e.window));
+ OtkEventHandler::keyPressHandler(e);
unsigned int state = e.state & (ControlMask | ShiftMask | Mod1Mask |
Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
@@ -177,6 +183,8 @@ void OBActions::keyPressHandler(const XKeyEvent &e)
void OBActions::motionHandler(const XMotionEvent &e)
{
+ OtkEventHandler::motionHandler(e);
+
if (!e.same_screen) return; // this just gets stupid
int x_root = e.x_root, y_root = e.y_root;
@@ -211,97 +219,66 @@ void OBActions::motionHandler(const XMotionEvent &e)
void OBActions::mapRequestHandler(const XMapRequestEvent &e)
{
- doCallback(Action_NewWindow, e.window, (OBWidget::WidgetType)-1,
- 0, 0, 0, 0, 0);
+ OtkEventHandler::mapRequestHandler(e);
+
+ if (_callback[EventNewWindow]) {
+ EventData *data = new_event_data(e.window, EventNewWindow, 0);
+ python_callback(_callback[EventNewWindow], (PyObject*)data);
+ Py_DECREF((PyObject*)data);
+ }
}
void OBActions::unmapHandler(const XUnmapEvent &e)
{
- (void)e;
- doCallback(Action_CloseWindow, e.window, (OBWidget::WidgetType)-1,
- 0, 0, 0, 0, 0);
+ OtkEventHandler::unmapHandler(e);
+
+ if (_callback[EventCloseWindow]) {
+ EventData *data = new_event_data(e.window, EventCloseWindow, 0);
+ python_callback(_callback[EventCloseWindow], (PyObject*)data);
+ Py_DECREF((PyObject*)data);
+ }
}
void OBActions::destroyHandler(const XDestroyWindowEvent &e)
{
- (void)e;
- doCallback(Action_CloseWindow, e.window, (OBWidget::WidgetType)-1,
- 0, 0, 0, 0, 0);
-}
+ OtkEventHandler::destroyHandler(e);
-void OBActions::doCallback(ActionType action, Window window,
- OBWidget::WidgetType type, unsigned int state,
- unsigned int button, int xroot, int yroot,
- Time time)
-{
- std::pair<CallbackMap::iterator, CallbackMap::iterator> it_pair =
- _callbacks.equal_range(action);
-
- CallbackMap::iterator it;
-// for (it = it_pair.first; it != it_pair.second; ++it)
-// python_callback(it->second, action, window, type, state,
-// button, xroot, yroot, time);
- // XXX do a callback
+ if (_callback[EventCloseWindow]) {
+ EventData *data = new_event_data(e.window, EventCloseWindow, 0);
+ python_callback(_callback[EventCloseWindow], (PyObject*)data);
+ Py_DECREF((PyObject*)data);
+ }
}
-bool OBActions::registerCallback(ActionType action, PyObject *func,
- bool atfront)
+bool OBActions::bind(EventAction action, PyObject *func)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS) {
+ if (action < 0 || action >= NUM_EVENTS) {
return false;
}
- if (!func)
- return false;
- std::pair<CallbackMap::iterator, CallbackMap::iterator> it_pair =
- _callbacks.equal_range(action);
-
- CallbackMap::iterator it;
- for (it = it_pair.first; it != it_pair.second; ++it)
- if (it->second == func)
- return true; // already in there
- if (atfront)
- _callbacks.insert(_callbacks.begin(), CallbackMapPair(action, func));
- else
- _callbacks.insert(CallbackMapPair(action, func));
+ Py_XDECREF(_callback[action]);
+ _callback[action] = func;
Py_INCREF(func);
return true;
}
-bool OBActions::unregisterCallback(ActionType action, PyObject *func)
+bool OBActions::unbind(EventAction action)
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS) {
+ if (action < 0 || action >= NUM_EVENTS) {
return false;
}
- if (!func)
- return false;
-
- std::pair<CallbackMap::iterator, CallbackMap::iterator> it_pair =
- _callbacks.equal_range(action);
- CallbackMap::iterator it;
- for (it = it_pair.first; it != it_pair.second; ++it)
- if (it->second == func)
- break;
- if (it != it_pair.second) { // its been registered before
- Py_DECREF(func);
- _callbacks.erase(it);
- }
+ Py_XDECREF(_callback[action]);
+ _callback[action] = 0;
return true;
}
-bool OBActions::unregisterAllCallbacks(ActionType action)
+void OBActions::unbindAll()
{
- if (action < 0 || action >= OBActions::NUM_ACTIONS) {
- return false;
+ for (int i = 0; i < NUM_EVENTS; ++i) {
+ Py_XDECREF(_callback[i]);
+ _callback[i] = 0;
}
-
- while (!_callbacks.empty()) {
- CallbackMap::iterator it = _callbacks.begin();
- Py_DECREF(it->second);
- _callbacks.erase(it);
- }
- return true;
}
}
diff --git a/src/actions.hh b/src/actions.hh
index 2b68153a..970a18a4 100644
--- a/src/actions.hh
+++ b/src/actions.hh
@@ -27,15 +27,7 @@ namespace ob {
*/
class OBActions : public otk::OtkEventHandler {
public:
- // update the same enum in openbox.i when making changes to this
- enum ActionType {
- Action_EnterWindow,
- Action_LeaveWindow,
- Action_NewWindow,
- Action_CloseWindow,
- NUM_ACTIONS
- };
-
+#ifndef SWIG // get rid of a swig warning
struct ButtonReleaseAction {
Window win;
unsigned int button;
@@ -49,10 +41,9 @@ public:
otk::Rect clientarea;
ButtonPressAction() { button = 0; }
};
-
+#endif // SWIG
private:
// milliseconds XXX: config option
- static const unsigned int DOUBLECLICKDELAY;
static const int BUTTONS = 5;
//! The mouse button currently being watched from a press for a CLICK
@@ -68,15 +59,9 @@ private:
void insertPress(const XButtonEvent &e);
void removePress(const XButtonEvent &e);
-
- typedef std::multimap<ActionType, PyObject*> CallbackMap;
- typedef std::pair<ActionType, PyObject*> CallbackMapPair;
- CallbackMap _callbacks;
- void doCallback(ActionType action, Window window, OBWidget::WidgetType type,
- unsigned int state, unsigned int button,
- int xroot, int yroot, Time time);
-
+ PyObject *_callback[NUM_EVENTS];
+
public:
//! Constructs an OBActions object
OBActions();
@@ -97,18 +82,14 @@ public:
virtual void unmapHandler(const XUnmapEvent &e);
virtual void destroyHandler(const XDestroyWindowEvent &e);
- //! Add a callback funtion to the back of the hook list
- /*!
- Registering functions for KeyPress events is pointless. Use
- OBSCript::bindKey instead to do this.
- */
- bool registerCallback(ActionType action, PyObject *func, bool atfront);
+ //! Bind a callback for an action
+ bool bind(EventAction action, PyObject *func);
- //! Remove a callback function from the hook list
- bool unregisterCallback(ActionType action, PyObject *func);
+ //! Unbind the callback function from an action
+ bool unbind(EventAction action);
- //! Remove all callback functions from the hook list
- bool unregisterAllCallbacks(ActionType action);
+ //! Remove all callback functions
+ void unbindAll();
};
}
diff --git a/src/openbox.i b/src/openbox.i
index aeae40dd..1b227568 100644
--- a/src/openbox.i
+++ b/src/openbox.i
@@ -24,8 +24,6 @@
ob::Openbox *Openbox_instance() { return ob::Openbox::instance; }
%};
-%rename(register) python_register;
-
%ignore ob::OBScreen::clients;
%{
#include <iterator>
diff --git a/src/openbox_wrap.cc b/src/openbox_wrap.cc
index 8ed3bc44..ecc21e32 100644
--- a/src/openbox_wrap.cc
+++ b/src/openbox_wrap.cc
@@ -2554,15 +2554,16 @@ static PyObject *_wrap_kbind(PyObject *self, PyObject *args) {
}
-static PyObject *_wrap_kunbind(PyObject *self, PyObject *args) {
+static PyObject *_wrap_ebind(PyObject *self, PyObject *args) {
PyObject *resultobj;
- PyObject *arg1 = (PyObject *) 0 ;
+ int arg1 ;
+ PyObject *arg2 = (PyObject *) 0 ;
PyObject *result;
- PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
- if(!PyArg_ParseTuple(args,(char *)"O:kunbind",&obj0)) goto fail;
- arg1 = obj0;
- result = (PyObject *)ob::kunbind(arg1);
+ if(!PyArg_ParseTuple(args,(char *)"iO:ebind",&arg1,&obj1)) goto fail;
+ arg2 = obj1;
+ result = (PyObject *)ob::ebind((ob::EventAction )arg1,arg2);
resultobj = result;
return resultobj;
@@ -2571,19 +2572,6 @@ static PyObject *_wrap_kunbind(PyObject *self, PyObject *args) {
}
-static PyObject *_wrap_kunbind_all(PyObject *self, PyObject *args) {
- PyObject *resultobj;
-
- if(!PyArg_ParseTuple(args,(char *)":kunbind_all")) goto fail;
- ob::kunbind_all();
-
- Py_INCREF(Py_None); resultobj = Py_None;
- return resultobj;
- fail:
- return NULL;
-}
-
-
static PyObject *_wrap_set_reset_key(PyObject *self, PyObject *args) {
PyObject *resultobj;
std::string *arg1 = 0 ;
@@ -2706,8 +2694,7 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"OBClient_swigregister", OBClient_swigregister, METH_VARARGS },
{ (char *)"mbind", _wrap_mbind, METH_VARARGS },
{ (char *)"kbind", _wrap_kbind, METH_VARARGS },
- { (char *)"kunbind", _wrap_kunbind, METH_VARARGS },
- { (char *)"kunbind_all", _wrap_kunbind_all, METH_VARARGS },
+ { (char *)"ebind", _wrap_ebind, METH_VARARGS },
{ (char *)"set_reset_key", _wrap_set_reset_key, METH_VARARGS },
{ NULL, NULL }
};
@@ -2867,6 +2854,11 @@ static swig_const_info swig_const_table[] = {
{ SWIG_PY_INT, (char *)"KC_Menu", (long) ob::KC_Menu, 0, 0, 0},
{ SWIG_PY_INT, (char *)"KC_All", (long) ob::KC_All, 0, 0, 0},
{ SWIG_PY_INT, (char *)"NUM_KEY_CONTEXT", (long) ob::NUM_KEY_CONTEXT, 0, 0, 0},
+{ SWIG_PY_INT, (char *)"EventEnterWindow", (long) ob::EventEnterWindow, 0, 0, 0},
+{ SWIG_PY_INT, (char *)"EventLeaveWindow", (long) ob::EventLeaveWindow, 0, 0, 0},
+{ SWIG_PY_INT, (char *)"EventNewWindow", (long) ob::EventNewWindow, 0, 0, 0},
+{ SWIG_PY_INT, (char *)"EventCloseWindow", (long) ob::EventCloseWindow, 0, 0, 0},
+{ SWIG_PY_INT, (char *)"NUM_EVENTS", (long) ob::NUM_EVENTS, 0, 0, 0},
{ SWIG_PY_INT, (char *)"X_PROTOCOL", (long) 11, 0, 0, 0},
{ SWIG_PY_INT, (char *)"X_PROTOCOL_REVISION", (long) 0, 0, 0, 0},
{ SWIG_PY_INT, (char *)"None", (long) 0L, 0, 0, 0},
diff --git a/src/python.cc b/src/python.cc
index 818115ca..4bddce8f 100644
--- a/src/python.cc
+++ b/src/python.cc
@@ -171,6 +171,28 @@ static PyMethodDef ButtonData_methods[] = {
{NULL, NULL, 0, NULL}
};
+PyObject *EventData_action(EventData *self, PyObject *args)
+{
+ if(!PyArg_ParseTuple(args,":action")) return NULL;
+ return PyLong_FromLong((int)self->action);
+}
+
+PyObject *EventData_modifiers(EventData *self, PyObject *args)
+{
+ if(!PyArg_ParseTuple(args,":modifiers")) return NULL;
+ return PyLong_FromUnsignedLong(self->state);
+}
+
+static PyMethodDef EventData_methods[] = {
+ {"window", (PyCFunction)MotionData_window, METH_VARARGS,
+ "Return the client window id."},
+ {"action", (PyCFunction)EventData_action, METH_VARARGS,
+ "Return the action being executed."},
+ {"modifiers", (PyCFunction)EventData_modifiers, METH_VARARGS,
+ "Return the modifier keys state."},
+ {NULL, NULL, 0, NULL}
+};
+
PyObject *KeyData_key(KeyData *self, PyObject *args)
{
if(!PyArg_ParseTuple(args,":key")) return NULL;
@@ -201,6 +223,11 @@ static PyObject *ButtonDataGetAttr(PyObject *obj, char *name)
return Py_FindMethod(ButtonData_methods, obj, name);
}
+static PyObject *EventDataGetAttr(PyObject *obj, char *name)
+{
+ return Py_FindMethod(EventData_methods, obj, name);
+}
+
static PyObject *KeyDataGetAttr(PyObject *obj, char *name)
{
return Py_FindMethod(KeyData_methods, obj, name);
@@ -230,6 +257,18 @@ static PyTypeObject ButtonData_Type = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
+static PyTypeObject EventData_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "EventData",
+ sizeof(EventData),
+ 0,
+ dealloc,
+ 0,
+ (getattrfunc)EventDataGetAttr,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+
static PyTypeObject KeyData_Type = {
PyObject_HEAD_INIT(NULL)
0,
@@ -279,6 +318,16 @@ ButtonData *new_button_data(Window window, Time time, unsigned int state,
return data;
}
+EventData *new_event_data(Window window, EventAction action,
+ unsigned int state)
+{
+ EventData *data = PyObject_New(EventData, &EventData_Type);
+ data->window = window;
+ data->action = action;
+ data->state = state;
+ return data;
+}
+
KeyData *new_key_data(Window window, Time time, unsigned int state,
unsigned int key)
{
@@ -348,6 +397,15 @@ void python_callback(PyObject *func, PyObject *data)
Py_DECREF(arglist);
}
+bool python_get_long(const char *name, long *value)
+{
+ PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
+ if (!(val && PyLong_Check(val))) return false;
+
+ *value = PyLong_AsLong(val);
+ return true;
+}
+
bool python_get_string(const char *name, std::string *value)
{
PyObject *val = PyDict_GetItemString(obdict, const_cast<char*>(name));
@@ -374,65 +432,37 @@ bool python_get_stringlist(const char *name, std::vector<std::string> *value)
// Stuff for calling from Python scripts //
// ************************************* //
-/*
-PyObject * python_register(int action, PyObject *func, bool infront = false)
-{
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
- return NULL;
- }
-
- if (!ob::Openbox::instance->actions()->registerCallback(
- (ob::OBActions::ActionType)action, func, infront)) {
- PyErr_SetString(PyExc_RuntimeError, "Unable to register action callback.");
- return NULL;
- }
- Py_INCREF(Py_None); return Py_None;
-}
-
-PyObject *unregister(int action, PyObject *func)
+PyObject *mbind(const std::string &button, ob::MouseContext context,
+ ob::MouseAction action, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
-
- if (!ob::Openbox::instance->actions()->unregisterCallback(
- (ob::OBActions::ActionType)action, func)) {
- PyErr_SetString(PyExc_RuntimeError, "Unable to unregister action callback.");
+
+ if (!ob::Openbox::instance->bindings()->addButton(button, context,
+ action, func)) {
+ PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
-PyObject *unregister_all(int action)
-{
- if (!ob::Openbox::instance->actions()->unregisterAllCallbacks(
- (ob::OBActions::ActionType)action)) {
- PyErr_SetString(PyExc_RuntimeError,
- "Unable to unregister action callbacks.");
- return NULL;
- }
- Py_INCREF(Py_None); return Py_None;
-}
-*/
-PyObject * mbind(const std::string &button, ob::MouseContext context,
- ob::MouseAction action, PyObject *func)
+PyObject *ebind(ob::EventAction action, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
return NULL;
}
- if (!ob::Openbox::instance->bindings()->addButton(button, context,
- action, func)) {
+ if (!ob::Openbox::instance->actions()->bind(action, func)) {
PyErr_SetString(PyExc_RuntimeError,"Unable to add binding.");
return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
-PyObject * kbind(PyObject *keylist, ob::KeyContext context, PyObject *func)
+PyObject *kbind(PyObject *keylist, ob::KeyContext context, PyObject *func)
{
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
@@ -461,7 +491,7 @@ PyObject * kbind(PyObject *keylist, ob::KeyContext context, PyObject *func)
Py_INCREF(Py_None); return Py_None;
}
-PyObject * kunbind(PyObject *keylist)
+PyObject *kunbind(PyObject *keylist)
{
if (!PyList_Check(keylist)) {
PyErr_SetString(PyExc_TypeError, "Invalid keylist. Not a list.");
diff --git a/src/python.hh b/src/python.hh
index 67943a84..2bf656d8 100644
--- a/src/python.hh
+++ b/src/python.hh
@@ -48,6 +48,14 @@ enum KeyContext {
NUM_KEY_CONTEXT
};
+enum EventAction {
+ EventEnterWindow,
+ EventLeaveWindow,
+ EventNewWindow,
+ EventCloseWindow,
+ NUM_EVENTS
+};
+
#ifndef SWIG
// *** MotionData can be (and is) cast ButtonData!! (in actions.cc) *** //
@@ -83,6 +91,13 @@ typedef struct {
typedef struct {
PyObject_HEAD;
Window window;
+ unsigned int state;
+ EventAction action;
+} EventData;
+
+typedef struct {
+ PyObject_HEAD;
+ Window window;
Time time;
unsigned int state;
unsigned int key;
@@ -100,21 +115,25 @@ MotionData *new_motion_data(Window window, Time time, unsigned int state,
ButtonData *new_button_data(Window window, Time time, unsigned int state,
unsigned int button, MouseContext context,
MouseAction action);
+EventData *new_event_data(Window window, EventAction action,
+ unsigned int state);
KeyData *new_key_data(Window window, Time time, unsigned int state,
unsigned int key);
void python_callback(PyObject *func, PyObject *data);
+bool python_get_long(const char *name, long *value);
bool python_get_string(const char *name, std::string *value);
bool python_get_stringlist(const char *name, std::vector<std::string> *value);
#endif
-PyObject * mbind(const std::string &button, ob::MouseContext context,
- ob::MouseAction action, PyObject *func);
+PyObject *mbind(const std::string &button, ob::MouseContext context,
+ ob::MouseAction action, PyObject *func);
+
+PyObject *kbind(PyObject *keylist, ob::KeyContext context, PyObject *func);
+
+PyObject *ebind(ob::EventAction action, PyObject *func);
-PyObject * kbind(PyObject *keylist, ob::KeyContext context, PyObject *func);
-PyObject * kunbind(PyObject *keylist);
-void kunbind_all();
void set_reset_key(const std::string &key);
}