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()");
373 PyRun_SimpleString("display = OBDisplay_display()");
376 sys.path.append('stuff')
377 install the .py wrappers, and include their path with this, then import em
380 // set up access to the python global variables
381 PyObject
*obmodule
= PyImport_AddModule("__main__");
382 obdict
= PyModule_GetDict(obmodule
);
384 // set up the custom types
385 MotionData_Type
.ob_type
= &PyType_Type
;
386 ButtonData_Type
.ob_type
= &PyType_Type
;
387 KeyData_Type
.ob_type
= &PyType_Type
;
390 void python_destroy()
395 bool python_exec(const std::string
&path
)
397 FILE *rcpyfd
= fopen(path
.c_str(), "r");
399 printf("failed to load python file %s\n", path
.c_str());
402 PyRun_SimpleFile(rcpyfd
, const_cast<char*>(path
.c_str()));
407 void python_callback(PyObject
*func
, PyObject
*data
)
412 arglist
= Py_BuildValue("(O)", data
);
415 result
= PyEval_CallObject(func
, arglist
);
417 // an exception occured in the script, display it
425 bool python_get_long(const char *name
, long *value
)
427 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
428 if (!(val
&& PyLong_Check(val
))) return false;
430 *value
= PyLong_AsLong(val
);
434 bool python_get_string(const char *name
, std::string
*value
)
436 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
437 if (!(val
&& PyString_Check(val
))) return false;
439 *value
= PyString_AsString(val
);
443 bool python_get_stringlist(const char *name
, std::vector
<std::string
> *value
)
445 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
446 if (!(val
&& PyList_Check(val
))) return false;
448 for (int i
= 0, end
= PyList_Size(val
); i
< end
; ++i
) {
449 PyObject
*str
= PyList_GetItem(val
, i
);
450 if (PyString_Check(str
))
451 value
->push_back(PyString_AsString(str
));
456 // ************************************* //
457 // Stuff for calling from Python scripts //
458 // ************************************* //
460 PyObject
*mbind(const std::string
&button
, ob::MouseContext context
,
461 ob::MouseAction action
, PyObject
*func
)
463 if (!PyCallable_Check(func
)) {
464 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
468 if (!ob::Openbox::instance
->bindings()->addButton(button
, context
,
470 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
473 Py_INCREF(Py_None
); return Py_None
;
476 PyObject
*ebind(ob::EventAction action
, PyObject
*func
)
478 if (!PyCallable_Check(func
)) {
479 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
483 if (!ob::Openbox::instance
->bindings()->addEvent(action
, func
)) {
484 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
487 Py_INCREF(Py_None
); return Py_None
;
490 PyObject
*kbind(PyObject
*keylist
, ob::KeyContext context
, PyObject
*func
)
492 if (!PyCallable_Check(func
)) {
493 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
496 if (!PyList_Check(keylist
)) {
497 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
501 ob::OBBindings::StringVect vectkeylist
;
502 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
503 PyObject
*str
= PyList_GetItem(keylist
, i
);
504 if (!PyString_Check(str
)) {
505 PyErr_SetString(PyExc_TypeError
,
506 "Invalid keylist. It must contain only strings.");
509 vectkeylist
.push_back(PyString_AsString(str
));
512 if (!ob::Openbox::instance
->bindings()->addKey(vectkeylist
, func
)) {
513 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
516 Py_INCREF(Py_None
); return Py_None
;
519 PyObject
*kunbind(PyObject
*keylist
, PyObject
*func
)
521 if (!PyList_Check(keylist
)) {
522 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
525 if (!PyCallable_Check(func
)) {
526 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
530 ob::OBBindings::StringVect vectkeylist
;
531 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
532 PyObject
*str
= PyList_GetItem(keylist
, i
);
533 if (!PyString_Check(str
)) {
534 PyErr_SetString(PyExc_TypeError
,
535 "Invalid keylist. It must contain only strings.");
538 vectkeylist
.push_back(PyString_AsString(str
));
541 if (!ob::Openbox::instance
->bindings()->removeKey(vectkeylist
, func
)) {
542 PyErr_SetString(PyExc_RuntimeError
, "Could not remove callback.");
545 Py_INCREF(Py_None
); return Py_None
;
550 ob::Openbox::instance
->bindings()->removeAllKeys();
553 void set_reset_key(const std::string
&key
)
555 ob::Openbox::instance
->bindings()->setResetKey(key
);
558 PyObject
*send_client_msg(Window target
, int type
, Window about
,
559 long data
, long data1
, long data2
,
560 long data3
, long data4
)
562 if (type
< 0 || type
>= otk::OBProperty::NUM_ATOMS
) {
563 PyErr_SetString(PyExc_TypeError
,
564 "Invalid atom type. Must be from otk::OBProperty::Atoms");
569 e
.xclient
.type
= ClientMessage
;
570 e
.xclient
.format
= 32;
571 e
.xclient
.message_type
=
572 Openbox::instance
->property()->atom((otk::OBProperty::Atoms
)type
);
573 e
.xclient
.window
= about
;
574 e
.xclient
.data
.l
[0] = data
;
575 e
.xclient
.data
.l
[1] = data1
;
576 e
.xclient
.data
.l
[2] = data2
;
577 e
.xclient
.data
.l
[3] = data3
;
578 e
.xclient
.data
.l
[4] = data4
;
580 XSendEvent(otk::OBDisplay::display
, target
, false,
581 SubstructureRedirectMask
| SubstructureNotifyMask
,
583 Py_INCREF(Py_None
); return Py_None
;