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_screen(MotionData
*self
, PyObject
*args
)
32 if(!PyArg_ParseTuple(args
,":screen")) return NULL
;
33 return PyLong_FromLong(self
->screen
);
36 PyObject
*MotionData_window(MotionData
*self
, PyObject
*args
)
38 if(!PyArg_ParseTuple(args
,":window")) return NULL
;
39 return PyLong_FromLong(self
->window
);
42 PyObject
*MotionData_context(MotionData
*self
, PyObject
*args
)
44 if(!PyArg_ParseTuple(args
,":context")) return NULL
;
45 return PyLong_FromLong((int)self
->context
);
48 PyObject
*MotionData_action(MotionData
*self
, PyObject
*args
)
50 if(!PyArg_ParseTuple(args
,":action")) return NULL
;
51 return PyLong_FromLong((int)self
->action
);
54 PyObject
*MotionData_modifiers(MotionData
*self
, PyObject
*args
)
56 if(!PyArg_ParseTuple(args
,":modifiers")) return NULL
;
57 return PyLong_FromUnsignedLong(self
->state
);
60 PyObject
*MotionData_button(MotionData
*self
, PyObject
*args
)
62 if(!PyArg_ParseTuple(args
,":button")) return NULL
;
64 switch (self
->button
) {
72 return PyLong_FromLong(b
);
75 PyObject
*MotionData_xroot(MotionData
*self
, PyObject
*args
)
77 if(!PyArg_ParseTuple(args
,":xroot")) return NULL
;
78 return PyLong_FromLong(self
->xroot
);
81 PyObject
*MotionData_yroot(MotionData
*self
, PyObject
*args
)
83 if(!PyArg_ParseTuple(args
,":yroot")) return NULL
;
84 return PyLong_FromLong(self
->yroot
);
87 PyObject
*MotionData_pressx(MotionData
*self
, PyObject
*args
)
89 if(!PyArg_ParseTuple(args
,":pressx")) return NULL
;
90 return PyLong_FromLong(self
->pressx
);
93 PyObject
*MotionData_pressy(MotionData
*self
, PyObject
*args
)
95 if(!PyArg_ParseTuple(args
,":pressy")) return NULL
;
96 return PyLong_FromLong(self
->pressy
);
100 PyObject
*MotionData_press_clientx(MotionData
*self
, PyObject
*args
)
102 if(!PyArg_ParseTuple(args
,":press_clientx")) return NULL
;
103 return PyLong_FromLong(self
->press_clientx
);
106 PyObject
*MotionData_press_clienty(MotionData
*self
, PyObject
*args
)
108 if(!PyArg_ParseTuple(args
,":press_clienty")) return NULL
;
109 return PyLong_FromLong(self
->press_clienty
);
112 PyObject
*MotionData_press_clientwidth(MotionData
*self
, PyObject
*args
)
114 if(!PyArg_ParseTuple(args
,":press_clientwidth")) return NULL
;
115 return PyLong_FromLong(self
->press_clientwidth
);
118 PyObject
*MotionData_press_clientheight(MotionData
*self
, PyObject
*args
)
120 if(!PyArg_ParseTuple(args
,":press_clientheight")) return NULL
;
121 return PyLong_FromLong(self
->press_clientheight
);
124 PyObject
*MotionData_time(MotionData
*self
, PyObject
*args
)
126 if(!PyArg_ParseTuple(args
,":time")) return NULL
;
127 return PyLong_FromLong(self
->time
);
130 static PyMethodDef MotionData_methods
[] = {
131 {"action", (PyCFunction
)MotionData_action
, METH_VARARGS
,
132 "Return the action being executed."},
133 {"screen", (PyCFunction
)MotionData_screen
, METH_VARARGS
,
134 "Return the number of the screen the event is on."},
135 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
136 "Return the client window id."},
137 {"context", (PyCFunction
)MotionData_context
, METH_VARARGS
,
138 "Return the context that the action is occuring in."},
139 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
140 "Return the modifier keys state."},
141 {"button", (PyCFunction
)MotionData_button
, METH_VARARGS
,
142 "Return the number of the pressed button (1-5)."},
143 {"xroot", (PyCFunction
)MotionData_xroot
, METH_VARARGS
,
144 "Return the X-position of the mouse cursor on the root window."},
145 {"yroot", (PyCFunction
)MotionData_yroot
, METH_VARARGS
,
146 "Return the Y-position of the mouse cursor on the root window."},
147 {"pressx", (PyCFunction
)MotionData_pressx
, METH_VARARGS
,
148 "Return the X-position of the mouse cursor at the start of the drag."},
149 {"pressy", (PyCFunction
)MotionData_pressy
, METH_VARARGS
,
150 "Return the Y-position of the mouse cursor at the start of the drag."},
151 {"press_clientx", (PyCFunction
)MotionData_press_clientx
, METH_VARARGS
,
152 "Return the X-position of the client at the start of the drag."},
153 {"press_clienty", (PyCFunction
)MotionData_press_clienty
, METH_VARARGS
,
154 "Return the Y-position of the client at the start of the drag."},
155 {"press_clientwidth", (PyCFunction
)MotionData_press_clientwidth
,
157 "Return the width of the client at the start of the drag."},
158 {"press_clientheight", (PyCFunction
)MotionData_press_clientheight
,
160 "Return the height of the client at the start of the drag."},
161 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
162 "Return the time at which the event occured."},
163 {NULL
, NULL
, 0, NULL
}
166 static PyMethodDef ButtonData_methods
[] = {
167 {"action", (PyCFunction
)MotionData_action
, METH_VARARGS
,
168 "Return the action being executed."},
169 {"context", (PyCFunction
)MotionData_context
, METH_VARARGS
,
170 "Return the context that the action is occuring in."},
171 {"screen", (PyCFunction
)MotionData_screen
, METH_VARARGS
,
172 "Return the number of the screen the event is on."},
173 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
174 "Return the client window id."},
175 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
176 "Return the modifier keys state."},
177 {"button", (PyCFunction
)MotionData_button
, METH_VARARGS
,
178 "Return the number of the pressed button (1-5)."},
179 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
180 "Return the time at which the event occured."},
181 {NULL
, NULL
, 0, NULL
}
184 PyObject
*EventData_action(EventData
*self
, PyObject
*args
)
186 if(!PyArg_ParseTuple(args
,":action")) return NULL
;
187 return PyLong_FromLong((int)self
->action
);
190 PyObject
*EventData_modifiers(EventData
*self
, PyObject
*args
)
192 if(!PyArg_ParseTuple(args
,":modifiers")) return NULL
;
193 return PyLong_FromUnsignedLong(self
->state
);
196 static PyMethodDef EventData_methods
[] = {
197 {"screen", (PyCFunction
)MotionData_screen
, METH_VARARGS
,
198 "Return the number of the screen the event is on."},
199 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
200 "Return the client window id."},
201 {"action", (PyCFunction
)EventData_action
, METH_VARARGS
,
202 "Return the action being executed."},
203 {"modifiers", (PyCFunction
)EventData_modifiers
, METH_VARARGS
,
204 "Return the modifier keys state."},
205 {NULL
, NULL
, 0, NULL
}
208 PyObject
*KeyData_key(KeyData
*self
, PyObject
*args
)
210 if(!PyArg_ParseTuple(args
,":key")) return NULL
;
211 return PyString_FromString(
212 XKeysymToString(XKeycodeToKeysym(otk::OBDisplay::display
, self
->key
, 0)));
216 static PyMethodDef KeyData_methods
[] = {
217 {"screen", (PyCFunction
)MotionData_screen
, METH_VARARGS
,
218 "Return the number of the screen the event is on."},
219 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
220 "Return the client window id."},
221 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
222 "Return the modifier keys state."},
223 {"key", (PyCFunction
)KeyData_key
, METH_VARARGS
,
224 "Return the name of the pressed key."},
225 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
226 "Return the time at which the event occured."},
227 {NULL
, NULL
, 0, NULL
}
230 static PyObject
*MotionDataGetAttr(PyObject
*obj
, char *name
)
232 return Py_FindMethod(MotionData_methods
, obj
, name
);
235 static PyObject
*ButtonDataGetAttr(PyObject
*obj
, char *name
)
237 return Py_FindMethod(ButtonData_methods
, obj
, name
);
240 static PyObject
*EventDataGetAttr(PyObject
*obj
, char *name
)
242 return Py_FindMethod(EventData_methods
, obj
, name
);
245 static PyObject
*KeyDataGetAttr(PyObject
*obj
, char *name
)
247 return Py_FindMethod(KeyData_methods
, obj
, name
);
250 static PyTypeObject MotionData_Type
= {
251 PyObject_HEAD_INIT(NULL
)
258 (getattrfunc
)MotionDataGetAttr
,
259 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
262 static PyTypeObject ButtonData_Type
= {
263 PyObject_HEAD_INIT(NULL
)
270 (getattrfunc
)ButtonDataGetAttr
,
271 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
274 static PyTypeObject EventData_Type
= {
275 PyObject_HEAD_INIT(NULL
)
282 (getattrfunc
)EventDataGetAttr
,
283 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
286 static PyTypeObject KeyData_Type
= {
287 PyObject_HEAD_INIT(NULL
)
294 (getattrfunc
)KeyDataGetAttr
,
295 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
298 MotionData
*new_motion_data(int screen
, Window window
, Time time
,
299 unsigned int state
, unsigned int button
,
300 MouseContext context
, MouseAction action
,
301 int xroot
, int yroot
, const otk::Point
&initpos
,
302 const otk::Rect
&initarea
)
304 MotionData
*data
= PyObject_New(MotionData
, &MotionData_Type
);
305 data
->screen
= screen
;
306 data
->window
= window
;
309 data
->button
= button
;
310 data
->context
= context
;
311 data
->action
= action
;
314 data
->pressx
= initpos
.x();
315 data
->pressy
= initpos
.y();
316 data
->press_clientx
= initarea
.x();
317 data
->press_clienty
= initarea
.y();
318 data
->press_clientwidth
= initarea
.width();
319 data
->press_clientheight
= initarea
.height();
323 ButtonData
*new_button_data(int screen
, Window window
, Time time
,
324 unsigned int state
, unsigned int button
,
325 MouseContext context
, MouseAction action
)
327 ButtonData
*data
= PyObject_New(ButtonData
, &ButtonData_Type
);
328 data
->screen
= screen
;
329 data
->window
= window
;
332 data
->button
= button
;
333 data
->context
= context
;
334 data
->action
= action
;
338 EventData
*new_event_data(int screen
, Window window
, EventAction action
,
341 EventData
*data
= PyObject_New(EventData
, &EventData_Type
);
342 data
->screen
= screen
;
343 data
->window
= window
;
344 data
->action
= action
;
349 KeyData
*new_key_data(int screen
, Window window
, Time time
, unsigned int state
,
352 KeyData
*data
= PyObject_New(KeyData
, &KeyData_Type
);
353 data
->screen
= screen
;
354 data
->window
= window
;
361 // **************** //
362 // End custom types //
363 // **************** //
365 void python_init(char *argv0
)
367 Py_SetProgramName(argv0
);
371 PyRun_SimpleString("from _otk import *; from _openbox import *;");
372 PyRun_SimpleString("openbox = Openbox_instance()");
375 sys.path.append('stuff')
376 install the .py wrappers, and include their path with this, then import em
379 // set up access to the python global variables
380 PyObject
*obmodule
= PyImport_AddModule("__main__");
381 obdict
= PyModule_GetDict(obmodule
);
383 // set up the custom types
384 MotionData_Type
.ob_type
= &PyType_Type
;
385 ButtonData_Type
.ob_type
= &PyType_Type
;
386 KeyData_Type
.ob_type
= &PyType_Type
;
389 void python_destroy()
394 bool python_exec(const std::string
&path
)
396 FILE *rcpyfd
= fopen(path
.c_str(), "r");
398 printf("failed to load python file %s\n", path
.c_str());
401 PyRun_SimpleFile(rcpyfd
, const_cast<char*>(path
.c_str()));
406 void python_callback(PyObject
*func
, PyObject
*data
)
411 arglist
= Py_BuildValue("(O)", data
);
414 result
= PyEval_CallObject(func
, arglist
);
416 // an exception occured in the script, display it
424 bool python_get_long(const char *name
, long *value
)
426 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
427 if (!(val
&& PyLong_Check(val
))) return false;
429 *value
= PyLong_AsLong(val
);
433 bool python_get_string(const char *name
, std::string
*value
)
435 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
436 if (!(val
&& PyString_Check(val
))) return false;
438 *value
= PyString_AsString(val
);
442 bool python_get_stringlist(const char *name
, std::vector
<std::string
> *value
)
444 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
445 if (!(val
&& PyList_Check(val
))) return false;
447 for (int i
= 0, end
= PyList_Size(val
); i
< end
; ++i
) {
448 PyObject
*str
= PyList_GetItem(val
, i
);
449 if (PyString_Check(str
))
450 value
->push_back(PyString_AsString(str
));
455 // ************************************* //
456 // Stuff for calling from Python scripts //
457 // ************************************* //
459 PyObject
*mbind(const std::string
&button
, ob::MouseContext context
,
460 ob::MouseAction action
, PyObject
*func
)
462 if (!PyCallable_Check(func
)) {
463 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
467 if (!ob::Openbox::instance
->bindings()->addButton(button
, context
,
469 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
472 Py_INCREF(Py_None
); return Py_None
;
475 PyObject
*ebind(ob::EventAction action
, PyObject
*func
)
477 if (!PyCallable_Check(func
)) {
478 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
482 if (!ob::Openbox::instance
->bindings()->addEvent(action
, func
)) {
483 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
486 Py_INCREF(Py_None
); return Py_None
;
489 PyObject
*kbind(PyObject
*keylist
, ob::KeyContext context
, PyObject
*func
)
491 if (!PyCallable_Check(func
)) {
492 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
495 if (!PyList_Check(keylist
)) {
496 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
500 ob::OBBindings::StringVect vectkeylist
;
501 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
502 PyObject
*str
= PyList_GetItem(keylist
, i
);
503 if (!PyString_Check(str
)) {
504 PyErr_SetString(PyExc_TypeError
,
505 "Invalid keylist. It must contain only strings.");
508 vectkeylist
.push_back(PyString_AsString(str
));
511 if (!ob::Openbox::instance
->bindings()->addKey(vectkeylist
, func
)) {
512 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
515 Py_INCREF(Py_None
); return Py_None
;
518 PyObject
*kunbind(PyObject
*keylist
, PyObject
*func
)
520 if (!PyList_Check(keylist
)) {
521 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
524 if (!PyCallable_Check(func
)) {
525 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
529 ob::OBBindings::StringVect vectkeylist
;
530 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
531 PyObject
*str
= PyList_GetItem(keylist
, i
);
532 if (!PyString_Check(str
)) {
533 PyErr_SetString(PyExc_TypeError
,
534 "Invalid keylist. It must contain only strings.");
537 vectkeylist
.push_back(PyString_AsString(str
));
540 if (!ob::Openbox::instance
->bindings()->removeKey(vectkeylist
, func
)) {
541 PyErr_SetString(PyExc_RuntimeError
, "Could not remove callback.");
544 Py_INCREF(Py_None
); return Py_None
;
549 ob::Openbox::instance
->bindings()->removeAllKeys();
552 void set_reset_key(const std::string
&key
)
554 ob::Openbox::instance
->bindings()->setResetKey(key
);