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
*EventData_action(EventData
*self
, PyObject
*args
)
176 if(!PyArg_ParseTuple(args
,":action")) return NULL
;
177 return PyLong_FromLong((int)self
->action
);
180 PyObject
*EventData_modifiers(EventData
*self
, PyObject
*args
)
182 if(!PyArg_ParseTuple(args
,":modifiers")) return NULL
;
183 return PyLong_FromUnsignedLong(self
->state
);
186 static PyMethodDef EventData_methods
[] = {
187 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
188 "Return the client window id."},
189 {"action", (PyCFunction
)EventData_action
, METH_VARARGS
,
190 "Return the action being executed."},
191 {"modifiers", (PyCFunction
)EventData_modifiers
, METH_VARARGS
,
192 "Return the modifier keys state."},
193 {NULL
, NULL
, 0, NULL
}
196 PyObject
*KeyData_key(KeyData
*self
, PyObject
*args
)
198 if(!PyArg_ParseTuple(args
,":key")) return NULL
;
199 return PyString_FromString(
200 XKeysymToString(XKeycodeToKeysym(otk::OBDisplay::display
, self
->key
, 0)));
204 static PyMethodDef KeyData_methods
[] = {
205 {"window", (PyCFunction
)MotionData_window
, METH_VARARGS
,
206 "Return the client window id."},
207 {"modifiers", (PyCFunction
)MotionData_modifiers
, METH_VARARGS
,
208 "Return the modifier keys state."},
209 {"key", (PyCFunction
)KeyData_key
, METH_VARARGS
,
210 "Return the name of the pressed key."},
211 {"time", (PyCFunction
)MotionData_time
, METH_VARARGS
,
212 "Return the time at which the event occured."},
213 {NULL
, NULL
, 0, NULL
}
216 static PyObject
*MotionDataGetAttr(PyObject
*obj
, char *name
)
218 return Py_FindMethod(MotionData_methods
, obj
, name
);
221 static PyObject
*ButtonDataGetAttr(PyObject
*obj
, char *name
)
223 return Py_FindMethod(ButtonData_methods
, obj
, name
);
226 static PyObject
*EventDataGetAttr(PyObject
*obj
, char *name
)
228 return Py_FindMethod(EventData_methods
, obj
, name
);
231 static PyObject
*KeyDataGetAttr(PyObject
*obj
, char *name
)
233 return Py_FindMethod(KeyData_methods
, obj
, name
);
236 static PyTypeObject MotionData_Type
= {
237 PyObject_HEAD_INIT(NULL
)
244 (getattrfunc
)MotionDataGetAttr
,
245 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
248 static PyTypeObject ButtonData_Type
= {
249 PyObject_HEAD_INIT(NULL
)
256 (getattrfunc
)ButtonDataGetAttr
,
257 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
260 static PyTypeObject EventData_Type
= {
261 PyObject_HEAD_INIT(NULL
)
268 (getattrfunc
)EventDataGetAttr
,
269 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
272 static PyTypeObject KeyData_Type
= {
273 PyObject_HEAD_INIT(NULL
)
280 (getattrfunc
)KeyDataGetAttr
,
281 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
284 MotionData
*new_motion_data(Window window
, Time time
, unsigned int state
,
285 unsigned int button
, MouseContext context
,
286 MouseAction action
, int xroot
, int yroot
,
287 const otk::Point
&initpos
, const otk::Rect
&initarea
)
289 MotionData
*data
= PyObject_New(MotionData
, &MotionData_Type
);
290 data
->window
= window
;
293 data
->button
= button
;
294 data
->context
= context
;
295 data
->action
= action
;
298 data
->pressx
= initpos
.x();
299 data
->pressy
= initpos
.y();
300 data
->press_clientx
= initarea
.x();
301 data
->press_clienty
= initarea
.y();
302 data
->press_clientwidth
= initarea
.width();
303 data
->press_clientheight
= initarea
.height();
307 ButtonData
*new_button_data(Window window
, Time time
, unsigned int state
,
308 unsigned int button
, MouseContext context
,
311 ButtonData
*data
= PyObject_New(ButtonData
, &ButtonData_Type
);
312 data
->window
= window
;
315 data
->button
= button
;
316 data
->context
= context
;
317 data
->action
= action
;
321 EventData
*new_event_data(Window window
, EventAction action
,
324 EventData
*data
= PyObject_New(EventData
, &EventData_Type
);
325 data
->window
= window
;
326 data
->action
= action
;
331 KeyData
*new_key_data(Window window
, Time time
, unsigned int state
,
334 KeyData
*data
= PyObject_New(KeyData
, &KeyData_Type
);
335 data
->window
= window
;
342 // **************** //
343 // End custom types //
344 // **************** //
346 void python_init(char *argv0
)
348 Py_SetProgramName(argv0
);
352 PyRun_SimpleString("from _otk import *; from _openbox import *;");
353 PyRun_SimpleString("openbox = Openbox_instance()");
356 sys.path.append('stuff')
357 install the .py wrappers, and include their path with this, then import em
360 // set up access to the python global variables
361 PyObject
*obmodule
= PyImport_AddModule("__main__");
362 obdict
= PyModule_GetDict(obmodule
);
364 // set up the custom types
365 MotionData_Type
.ob_type
= &PyType_Type
;
366 ButtonData_Type
.ob_type
= &PyType_Type
;
367 KeyData_Type
.ob_type
= &PyType_Type
;
370 void python_destroy()
375 bool python_exec(const std::string
&path
)
377 FILE *rcpyfd
= fopen(path
.c_str(), "r");
379 printf("failed to load python file %s\n", path
.c_str());
382 PyRun_SimpleFile(rcpyfd
, const_cast<char*>(path
.c_str()));
387 void python_callback(PyObject
*func
, PyObject
*data
)
392 arglist
= Py_BuildValue("(O)", data
);
395 result
= PyEval_CallObject(func
, arglist
);
397 // an exception occured in the script, display it
405 bool python_get_long(const char *name
, long *value
)
407 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
408 if (!(val
&& PyLong_Check(val
))) return false;
410 *value
= PyLong_AsLong(val
);
414 bool python_get_string(const char *name
, std::string
*value
)
416 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
417 if (!(val
&& PyString_Check(val
))) return false;
419 *value
= PyString_AsString(val
);
423 bool python_get_stringlist(const char *name
, std::vector
<std::string
> *value
)
425 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
426 if (!(val
&& PyList_Check(val
))) return false;
428 for (int i
= 0, end
= PyList_Size(val
); i
< end
; ++i
) {
429 PyObject
*str
= PyList_GetItem(val
, i
);
430 if (PyString_Check(str
))
431 value
->push_back(PyString_AsString(str
));
436 // ************************************* //
437 // Stuff for calling from Python scripts //
438 // ************************************* //
440 PyObject
*mbind(const std::string
&button
, ob::MouseContext context
,
441 ob::MouseAction action
, PyObject
*func
)
443 if (!PyCallable_Check(func
)) {
444 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
448 if (!ob::Openbox::instance
->bindings()->addButton(button
, context
,
450 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
453 Py_INCREF(Py_None
); return Py_None
;
456 PyObject
*ebind(ob::EventAction action
, PyObject
*func
)
458 if (!PyCallable_Check(func
)) {
459 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
463 if (!ob::Openbox::instance
->bindings()->addEvent(action
, func
)) {
464 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
467 Py_INCREF(Py_None
); return Py_None
;
470 PyObject
*kbind(PyObject
*keylist
, ob::KeyContext context
, PyObject
*func
)
472 if (!PyCallable_Check(func
)) {
473 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
476 if (!PyList_Check(keylist
)) {
477 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
481 ob::OBBindings::StringVect vectkeylist
;
482 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
483 PyObject
*str
= PyList_GetItem(keylist
, i
);
484 if (!PyString_Check(str
)) {
485 PyErr_SetString(PyExc_TypeError
,
486 "Invalid keylist. It must contain only strings.");
489 vectkeylist
.push_back(PyString_AsString(str
));
492 if (!ob::Openbox::instance
->bindings()->addKey(vectkeylist
, func
)) {
493 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
496 Py_INCREF(Py_None
); return Py_None
;
499 PyObject
*kunbind(PyObject
*keylist
)
501 if (!PyList_Check(keylist
)) {
502 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
506 ob::OBBindings::StringVect vectkeylist
;
507 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
508 PyObject
*str
= PyList_GetItem(keylist
, i
);
509 if (!PyString_Check(str
)) {
510 PyErr_SetString(PyExc_TypeError
,
511 "Invalid keylist. It must contain only strings.");
514 vectkeylist
.push_back(PyString_AsString(str
));
517 ob::Openbox::instance
->bindings()->removeKey(vectkeylist
);
518 Py_INCREF(Py_None
); return Py_None
;
523 ob::Openbox::instance
->bindings()->removeAllKeys();
526 void set_reset_key(const std::string
&key
)
528 ob::Openbox::instance
->bindings()->setResetKey(key
);