1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
8 #include "otk/display.hh"
11 // The initializer in openbox_wrap.cc
12 extern void init_openbox(void);
13 // The initializer in otk_wrap.cc
14 extern void init_otk(void);
19 static PyObject
*obdict
= NULL
;
21 // ************************************************************* //
22 // Define some custom types which are passed to python callbacks //
23 // ************************************************************* //
25 static void dealloc(PyObject
*self
)
30 PyObject
*MotionData_window(MotionData
*self
, PyObject
*args
)
32 if(!PyArg_ParseTuple(args
,":window")) return NULL
;
33 return PyLong_FromLong(self
->window
);
36 PyObject
*MotionData_context(MotionData
*self
, PyObject
*args
)
38 if(!PyArg_ParseTuple(args
,":context")) return NULL
;
39 return PyLong_FromLong((int)self
->context
);
42 PyObject
*MotionData_action(MotionData
*self
, PyObject
*args
)
44 if(!PyArg_ParseTuple(args
,":action")) return NULL
;
45 return PyLong_FromLong((int)self
->action
);
48 PyObject
*MotionData_modifiers(MotionData
*self
, PyObject
*args
)
50 if(!PyArg_ParseTuple(args
,":modifiers")) return NULL
;
51 return PyLong_FromUnsignedLong(self
->state
);
54 PyObject
*MotionData_button(MotionData
*self
, PyObject
*args
)
56 if(!PyArg_ParseTuple(args
,":button")) return NULL
;
58 switch (self
->button
) {
66 return PyLong_FromLong(b
);
69 PyObject
*MotionData_xroot(MotionData
*self
, PyObject
*args
)
71 if(!PyArg_ParseTuple(args
,":xroot")) return NULL
;
72 return PyLong_FromLong(self
->xroot
);
75 PyObject
*MotionData_yroot(MotionData
*self
, PyObject
*args
)
77 if(!PyArg_ParseTuple(args
,":yroot")) return NULL
;
78 return PyLong_FromLong(self
->yroot
);
81 PyObject
*MotionData_pressx(MotionData
*self
, PyObject
*args
)
83 if(!PyArg_ParseTuple(args
,":pressx")) return NULL
;
84 return PyLong_FromLong(self
->pressx
);
87 PyObject
*MotionData_pressy(MotionData
*self
, PyObject
*args
)
89 if(!PyArg_ParseTuple(args
,":pressy")) return NULL
;
90 return PyLong_FromLong(self
->pressy
);
94 PyObject
*MotionData_press_clientx(MotionData
*self
, PyObject
*args
)
96 if(!PyArg_ParseTuple(args
,":press_clientx")) return NULL
;
97 return PyLong_FromLong(self
->press_clientx
);
100 PyObject
*MotionData_press_clienty(MotionData
*self
, PyObject
*args
)
102 if(!PyArg_ParseTuple(args
,":press_clienty")) return NULL
;
103 return PyLong_FromLong(self
->press_clienty
);
106 PyObject
*MotionData_press_clientwidth(MotionData
*self
, PyObject
*args
)
108 if(!PyArg_ParseTuple(args
,":press_clientwidth")) return NULL
;
109 return PyLong_FromLong(self
->press_clientwidth
);
112 PyObject
*MotionData_press_clientheight(MotionData
*self
, PyObject
*args
)
114 if(!PyArg_ParseTuple(args
,":press_clientheight")) return NULL
;
115 return PyLong_FromLong(self
->press_clientheight
);
118 PyObject
*MotionData_time(MotionData
*self
, PyObject
*args
)
120 if(!PyArg_ParseTuple(args
,":time")) return NULL
;
121 return PyLong_FromLong(self
->time
);
124 static PyMethodDef MotionData_methods
[] = {
125 {"action", (PyCFunction
)MotionData_action
, METH_VARARGS
,
126 "Return the action being executed."},
127 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
128 "Return the client window id."},
129 {"context", (PyCFunction
)MotionData_context
, METH_VARARGS
,
130 "Return the context that the action is occuring in."},
131 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
132 "Return the modifier keys state."},
133 {"button", (PyCFunction
)MotionData_button
, METH_VARARGS
,
134 "Return the number of the pressed button (1-5)."},
135 {"xroot", (PyCFunction
)MotionData_xroot
, METH_VARARGS
,
136 "Return the X-position of the mouse cursor on the root window."},
137 {"yroot", (PyCFunction
)MotionData_yroot
, METH_VARARGS
,
138 "Return the Y-position of the mouse cursor on the root window."},
139 {"pressx", (PyCFunction
)MotionData_pressx
, METH_VARARGS
,
140 "Return the X-position of the mouse cursor at the start of the drag."},
141 {"pressy", (PyCFunction
)MotionData_pressy
, METH_VARARGS
,
142 "Return the Y-position of the mouse cursor at the start of the drag."},
143 {"press_clientx", (PyCFunction
)MotionData_press_clientx
, METH_VARARGS
,
144 "Return the X-position of the client at the start of the drag."},
145 {"press_clienty", (PyCFunction
)MotionData_press_clienty
, METH_VARARGS
,
146 "Return the Y-position of the client at the start of the drag."},
147 {"press_clientwidth", (PyCFunction
)MotionData_press_clientwidth
,
149 "Return the width of the client at the start of the drag."},
150 {"press_clientheight", (PyCFunction
)MotionData_press_clientheight
,
152 "Return the height of the client at the start of the drag."},
153 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
154 "Return the time at which the event occured."},
155 {NULL
, NULL
, 0, NULL
}
158 static PyMethodDef ButtonData_methods
[] = {
159 {"action", (PyCFunction
)MotionData_action
, METH_VARARGS
,
160 "Return the action being executed."},
161 {"context", (PyCFunction
)MotionData_context
, METH_VARARGS
,
162 "Return the context that the action is occuring in."},
163 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
164 "Return the client window id."},
165 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
166 "Return the modifier keys state."},
167 {"button", (PyCFunction
)MotionData_button
, METH_VARARGS
,
168 "Return the number of the pressed button (1-5)."},
169 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
170 "Return the time at which the event occured."},
171 {NULL
, NULL
, 0, NULL
}
174 PyObject
*KeyData_key(KeyData
*self
, PyObject
*args
)
176 if(!PyArg_ParseTuple(args
,":key")) return NULL
;
177 return PyString_FromString(
178 XKeysymToString(XKeycodeToKeysym(otk::OBDisplay::display
, self
->key
, 0)));
182 static PyMethodDef KeyData_methods
[] = {
183 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
184 "Return the client window id."},
185 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
186 "Return the modifier keys state."},
187 {"key", (PyCFunction
)KeyData_key
, METH_VARARGS
,
188 "Return the name of the pressed key."},
189 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
190 "Return the time at which the event occured."},
191 {NULL
, NULL
, 0, NULL
}
194 static PyObject
*MotionDataGetAttr(PyObject
*obj
, char *name
)
196 return Py_FindMethod(MotionData_methods
, obj
, name
);
199 static PyObject
*ButtonDataGetAttr(PyObject
*obj
, char *name
)
201 return Py_FindMethod(ButtonData_methods
, obj
, name
);
204 static PyObject
*KeyDataGetAttr(PyObject
*obj
, char *name
)
206 return Py_FindMethod(KeyData_methods
, obj
, name
);
209 static PyTypeObject MotionData_Type
= {
210 PyObject_HEAD_INIT(NULL
)
217 (getattrfunc
)MotionDataGetAttr
,
218 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
221 static PyTypeObject ButtonData_Type
= {
222 PyObject_HEAD_INIT(NULL
)
229 (getattrfunc
)ButtonDataGetAttr
,
230 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
233 static PyTypeObject KeyData_Type
= {
234 PyObject_HEAD_INIT(NULL
)
241 (getattrfunc
)KeyDataGetAttr
,
242 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
245 MotionData
*new_motion_data(Window window
, Time time
, unsigned int state
,
246 unsigned int button
, MouseContext context
,
247 MouseAction action
, int xroot
, int yroot
,
248 const otk::Point
&initpos
, const otk::Rect
&initarea
)
250 MotionData
*data
= PyObject_New(MotionData
, &MotionData_Type
);
251 data
->window
= window
;
254 data
->button
= button
;
255 data
->context
= context
;
256 data
->action
= action
;
259 data
->pressx
= initpos
.x();
260 data
->pressy
= initpos
.y();
261 data
->press_clientx
= initarea
.x();
262 data
->press_clienty
= initarea
.y();
263 data
->press_clientwidth
= initarea
.width();
264 data
->press_clientheight
= initarea
.height();
268 ButtonData
*new_button_data(Window window
, Time time
, unsigned int state
,
269 unsigned int button
, MouseContext context
,
272 ButtonData
*data
= PyObject_New(ButtonData
, &ButtonData_Type
);
273 data
->window
= window
;
276 data
->button
= button
;
277 data
->context
= context
;
278 data
->action
= action
;
282 KeyData
*new_key_data(Window window
, Time time
, unsigned int state
,
285 KeyData
*data
= PyObject_New(KeyData
, &KeyData_Type
);
286 data
->window
= window
;
293 // **************** //
294 // End custom types //
295 // **************** //
297 void python_init(char *argv0
)
299 Py_SetProgramName(argv0
);
303 PyRun_SimpleString("from _otk import *; from _openbox import *;");
304 PyRun_SimpleString("openbox = Openbox_instance()");
306 // set up access to the python global variables
307 PyObject
*obmodule
= PyImport_AddModule("__main__");
308 obdict
= PyModule_GetDict(obmodule
);
310 // set up the custom types
311 MotionData_Type
.ob_type
= &PyType_Type
;
312 ButtonData_Type
.ob_type
= &PyType_Type
;
313 KeyData_Type
.ob_type
= &PyType_Type
;
316 void python_destroy()
321 bool python_exec(const std::string
&path
)
323 FILE *rcpyfd
= fopen(path
.c_str(), "r");
325 printf("failed to load python file %s\n", path
.c_str());
328 PyRun_SimpleFile(rcpyfd
, const_cast<char*>(path
.c_str()));
333 void python_callback(PyObject
*func
, PyObject
*data
)
338 arglist
= Py_BuildValue("(O)", data
);
341 result
= PyEval_CallObject(func
, arglist
);
343 // an exception occured in the script, display it
351 bool python_get_string(const char *name
, std::string
*value
)
353 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
354 if (!(val
&& PyString_Check(val
))) return false;
356 *value
= PyString_AsString(val
);
360 bool python_get_stringlist(const char *name
, std::vector
<std::string
> *value
)
362 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
363 if (!(val
&& PyList_Check(val
))) return false;
365 for (int i
= 0, end
= PyList_Size(val
); i
< end
; ++i
) {
366 PyObject
*str
= PyList_GetItem(val
, i
);
367 if (PyString_Check(str
))
368 value
->push_back(PyString_AsString(str
));
373 // ************************************* //
374 // Stuff for calling from Python scripts //
375 // ************************************* //
378 PyObject * python_register(int action, PyObject *func, bool infront = false)
380 if (!PyCallable_Check(func)) {
381 PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
385 if (!ob::Openbox::instance->actions()->registerCallback(
386 (ob::OBActions::ActionType)action, func, infront)) {
387 PyErr_SetString(PyExc_RuntimeError, "Unable to register action callback.");
390 Py_INCREF(Py_None); return Py_None;
393 PyObject *unregister(int action, PyObject *func)
395 if (!PyCallable_Check(func)) {
396 PyErr_SetString(PyExc_TypeError, "Invalid callback function.");
400 if (!ob::Openbox::instance->actions()->unregisterCallback(
401 (ob::OBActions::ActionType)action, func)) {
402 PyErr_SetString(PyExc_RuntimeError, "Unable to unregister action callback.");
405 Py_INCREF(Py_None); return Py_None;
408 PyObject *unregister_all(int action)
410 if (!ob::Openbox::instance->actions()->unregisterAllCallbacks(
411 (ob::OBActions::ActionType)action)) {
412 PyErr_SetString(PyExc_RuntimeError,
413 "Unable to unregister action callbacks.");
416 Py_INCREF(Py_None); return Py_None;
419 PyObject
* mbind(const std::string
&button
, ob::MouseContext context
,
420 ob::MouseAction action
, PyObject
*func
)
422 if (!PyCallable_Check(func
)) {
423 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
427 if (!ob::Openbox::instance
->bindings()->addButton(button
, context
,
429 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
432 Py_INCREF(Py_None
); return Py_None
;
435 PyObject
* kbind(PyObject
*keylist
, ob::KeyContext context
, PyObject
*func
)
437 if (!PyCallable_Check(func
)) {
438 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
441 if (!PyList_Check(keylist
)) {
442 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
446 ob::OBBindings::StringVect vectkeylist
;
447 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
448 PyObject
*str
= PyList_GetItem(keylist
, i
);
449 if (!PyString_Check(str
)) {
450 PyErr_SetString(PyExc_TypeError
,
451 "Invalid keylist. It must contain only strings.");
454 vectkeylist
.push_back(PyString_AsString(str
));
457 if (!ob::Openbox::instance
->bindings()->add(vectkeylist
, func
)) {
458 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
461 Py_INCREF(Py_None
); return Py_None
;
464 PyObject
* kunbind(PyObject
*keylist
)
466 if (!PyList_Check(keylist
)) {
467 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
471 ob::OBBindings::StringVect vectkeylist
;
472 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
473 PyObject
*str
= PyList_GetItem(keylist
, i
);
474 if (!PyString_Check(str
)) {
475 PyErr_SetString(PyExc_TypeError
,
476 "Invalid keylist. It must contain only strings.");
479 vectkeylist
.push_back(PyString_AsString(str
));
482 ob::Openbox::instance
->bindings()->remove(vectkeylist
);
483 Py_INCREF(Py_None
); return Py_None
;
488 ob::Openbox::instance
->bindings()->removeAll();
491 void set_reset_key(const std::string
&key
)
493 ob::Openbox::instance
->bindings()->setResetKey(key
);