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()");
355 // set up access to the python global variables
356 PyObject
*obmodule
= PyImport_AddModule("__main__");
357 obdict
= PyModule_GetDict(obmodule
);
359 // set up the custom types
360 MotionData_Type
.ob_type
= &PyType_Type
;
361 ButtonData_Type
.ob_type
= &PyType_Type
;
362 KeyData_Type
.ob_type
= &PyType_Type
;
365 void python_destroy()
370 bool python_exec(const std::string
&path
)
372 FILE *rcpyfd
= fopen(path
.c_str(), "r");
374 printf("failed to load python file %s\n", path
.c_str());
377 PyRun_SimpleFile(rcpyfd
, const_cast<char*>(path
.c_str()));
382 void python_callback(PyObject
*func
, PyObject
*data
)
387 arglist
= Py_BuildValue("(O)", data
);
390 result
= PyEval_CallObject(func
, arglist
);
392 // an exception occured in the script, display it
400 bool python_get_long(const char *name
, long *value
)
402 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
403 if (!(val
&& PyLong_Check(val
))) return false;
405 *value
= PyLong_AsLong(val
);
409 bool python_get_string(const char *name
, std::string
*value
)
411 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
412 if (!(val
&& PyString_Check(val
))) return false;
414 *value
= PyString_AsString(val
);
418 bool python_get_stringlist(const char *name
, std::vector
<std::string
> *value
)
420 PyObject
*val
= PyDict_GetItemString(obdict
, const_cast<char*>(name
));
421 if (!(val
&& PyList_Check(val
))) return false;
423 for (int i
= 0, end
= PyList_Size(val
); i
< end
; ++i
) {
424 PyObject
*str
= PyList_GetItem(val
, i
);
425 if (PyString_Check(str
))
426 value
->push_back(PyString_AsString(str
));
431 // ************************************* //
432 // Stuff for calling from Python scripts //
433 // ************************************* //
435 PyObject
*mbind(const std::string
&button
, ob::MouseContext context
,
436 ob::MouseAction action
, PyObject
*func
)
438 if (!PyCallable_Check(func
)) {
439 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
443 if (!ob::Openbox::instance
->bindings()->addButton(button
, context
,
445 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
448 Py_INCREF(Py_None
); return Py_None
;
451 PyObject
*ebind(ob::EventAction action
, PyObject
*func
)
453 if (!PyCallable_Check(func
)) {
454 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
458 if (!ob::Openbox::instance
->bindings()->addEvent(action
, func
)) {
459 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
462 Py_INCREF(Py_None
); return Py_None
;
465 PyObject
*kbind(PyObject
*keylist
, ob::KeyContext context
, PyObject
*func
)
467 if (!PyCallable_Check(func
)) {
468 PyErr_SetString(PyExc_TypeError
, "Invalid callback function.");
471 if (!PyList_Check(keylist
)) {
472 PyErr_SetString(PyExc_TypeError
, "Invalid keylist. Not a list.");
476 ob::OBBindings::StringVect vectkeylist
;
477 for (int i
= 0, end
= PyList_Size(keylist
); i
< end
; ++i
) {
478 PyObject
*str
= PyList_GetItem(keylist
, i
);
479 if (!PyString_Check(str
)) {
480 PyErr_SetString(PyExc_TypeError
,
481 "Invalid keylist. It must contain only strings.");
484 vectkeylist
.push_back(PyString_AsString(str
));
487 if (!ob::Openbox::instance
->bindings()->addKey(vectkeylist
, func
)) {
488 PyErr_SetString(PyExc_RuntimeError
,"Unable to add binding.");
491 Py_INCREF(Py_None
); return Py_None
;
494 PyObject
*kunbind(PyObject
*keylist
)
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 ob::Openbox::instance
->bindings()->removeKey(vectkeylist
);
513 Py_INCREF(Py_None
); return Py_None
;
518 ob::Openbox::instance
->bindings()->removeAllKeys();
521 void set_reset_key(const std::string
&key
)
523 ob::Openbox::instance
->bindings()->setResetKey(key
);