merge the C branch into HEAD
[openbox.git] / c / hooks.c
blob6bf15d2009d9d4cd5d824d6e80af46dcb5ed1c70
1 #include "hooks.h"
2 #include <Python.h>
3 #include <glib.h>
5 /* the 'hooks' module and its dictionary */
6 static PyObject *hooks = NULL, *hooksdict = NULL;
8 /*
10 * Define the type 'Hook'
13 #define IS_HOOK(v) ((v)->ob_type == &HookType)
15 staticforward PyTypeObject HookType;
17 typedef struct {
18 PyObject_HEAD
19 GSList *funcs;
20 } HookObject;
22 static PyObject *create_Hook(PyObject *self, PyObject *args)
24 HookObject *hook;
25 char *name;
26 int ret;
28 (void) self;
30 if (!PyArg_ParseTuple(args, "s:Hook", &name))
31 return NULL;
33 hook = PyObject_New(HookObject, &HookType);
34 hook->funcs = NULL;
36 /* add it to the hooks module */
37 ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook);
38 Py_DECREF(hook);
40 if (ret == -1) {
41 char *s = g_strdup_printf(
42 "Failed to add the hook '%s' to the 'hooks' module", name);
43 PyErr_SetString(PyExc_RuntimeError, s);
44 g_free(s);
45 return NULL;
48 Py_INCREF(Py_None);
49 return Py_None;
52 static void hook_dealloc(HookObject *self)
54 GSList *it;
56 for (it = self->funcs; it != NULL; it = it->next)
57 Py_DECREF((PyObject*) it->data);
59 PyObject_Del((PyObject*) self);
62 static PyObject *hook_fire(HookObject *self, PyObject *args)
64 GSList *it;
66 if (!IS_HOOK(self)) {
67 PyErr_SetString(PyExc_TypeError,
68 "descriptor 'fire' requires a 'Hook' object");
69 return NULL;
72 for (it = self->funcs; it != NULL; it = it->next) {
73 PyObject *ret = PyObject_CallObject(it->data, args);
74 if (ret == NULL)
75 return NULL;
76 Py_DECREF(ret);
79 Py_INCREF(Py_None);
80 return Py_None;
83 static PyObject *hook_add(HookObject *self, PyObject *args)
85 PyObject *func;
87 if (!IS_HOOK(self)) {
88 PyErr_SetString(PyExc_TypeError,
89 "descriptor 'add' requires a 'Hook' object");
90 return NULL;
92 if (!PyArg_ParseTuple(args, "O:add", &func))
93 return NULL;
94 if (!PyCallable_Check(func)) {
95 PyErr_SetString(PyExc_TypeError,
96 "descriptor 'add' requires a callable argument");
97 return NULL;
99 self->funcs = g_slist_append(self->funcs, func);
100 Py_INCREF(func);
102 Py_INCREF(Py_None);
103 return Py_None;
106 static PyObject *hook_remove(HookObject *self, PyObject *args)
108 PyObject *func;
109 GSList *it;
111 if (!IS_HOOK(self)) {
112 PyErr_SetString(PyExc_TypeError,
113 "descriptor 'remove' requires a 'Hook' object");
114 return NULL;
116 if (!PyArg_ParseTuple(args, "O:remove", &func))
117 return NULL;
118 if (!PyCallable_Check(func)) {
119 PyErr_SetString(PyExc_TypeError,
120 "descriptor 'remove' requires a callable argument");
121 return NULL;
123 it = g_slist_find(self->funcs, func);
124 if (it != NULL) {
125 self->funcs = g_slist_delete_link(self->funcs, it);
126 Py_DECREF(func);
128 Py_INCREF(Py_None);
129 return Py_None;
131 PyErr_SetString(PyExc_TypeError,
132 "given callable object was not found in Hook");
133 return NULL;
136 static PyObject *hook_count(HookObject *self, PyObject *args)
138 if (!IS_HOOK(self)) {
139 PyErr_SetString(PyExc_TypeError,
140 "descriptor 'fire' requires a 'Hook' object");
141 return NULL;
143 if (!PyArg_ParseTuple(args, ":count"))
144 return NULL;
146 return PyInt_FromLong(g_slist_length(self->funcs));
149 static PyTypeObject HookType = {
150 PyObject_HEAD_INIT(NULL)
152 "Hook",
153 sizeof(HookObject),
155 (destructor) hook_dealloc, /*tp_dealloc*/
156 0, /*tp_print*/
157 0, /*tp_getattr*/
158 0, /*tp_setattr*/
159 0, /*tp_compare*/
160 0, /*tp_repr*/
161 0, /*tp_as_number*/
162 0, /*tp_as_sequence*/
163 0, /*tp_as_mapping*/
164 0, /*tp_hash */
167 static PyMethodDef HookMethods[] = {
168 {"fire", (PyCFunction)hook_fire, METH_VARARGS,
169 "hook.fire() -- Fire the added hook functions for the Hook."},
170 {"add", (PyCFunction)hook_add, METH_VARARGS,
171 "hook.add(func) -- Add a function to the hook." },
172 {"remove", (PyCFunction)hook_remove, METH_VARARGS,
173 "hook.remove(func) -- Remove a function from the hook." },
174 {"count", (PyCFunction)hook_count, METH_VARARGS,
175 "hook.count() -- Return the number of functions in the hook." },
177 { NULL, NULL, 0, NULL }
183 * Module initialization/finalization
187 /* the "events" hook */
188 static HookObject *events_hook = NULL, *keyboard_hook = NULL,
189 *pointer_hook = NULL;
191 static PyMethodDef HooksMethods[] = {
192 {"create", create_Hook, METH_VARARGS,
193 "hooks.create('name') -- Add a hook called 'name' to the hooks module."},
195 { NULL, NULL, 0, NULL }
198 void hooks_startup()
200 int ret;
202 HookType.ob_type = &PyType_Type;
203 HookType.tp_methods = HookMethods;
204 PyType_Ready(&HookType);
206 Py_InitModule("hooks", HooksMethods);
208 /* get the hooks module/dict */
209 hooks = PyImport_ImportModule("hooks"); /* new */
210 g_assert(hooks != NULL);
211 hooksdict = PyModule_GetDict(hooks); /* borrowed */
212 g_assert(hooksdict != NULL);
214 /* create the "events" hook */
215 events_hook = PyObject_New(HookObject, &HookType);
216 events_hook->funcs = NULL;
218 /* add it to the hooks module */
219 ret = PyDict_SetItemString(hooksdict, "events", (PyObject*) events_hook);
220 g_assert(ret == 0);
222 /* create the "keyboard" hook */
223 keyboard_hook = PyObject_New(HookObject, &HookType);
224 keyboard_hook->funcs = NULL;
226 /* add it to the hooks module */
227 ret = PyDict_SetItemString(hooksdict, "keyboard",
228 (PyObject*) keyboard_hook);
229 g_assert(ret == 0);
231 /* create the "pointer" hook */
232 pointer_hook = PyObject_New(HookObject, &HookType);
233 pointer_hook->funcs = NULL;
235 /* add it to the hooks module */
236 ret = PyDict_SetItemString(hooksdict, "pointer", (PyObject*) pointer_hook);
237 g_assert(ret == 0);
240 void hooks_shutdown()
242 Py_DECREF(pointer_hook);
243 Py_DECREF(keyboard_hook);
244 Py_DECREF(events_hook);
245 Py_DECREF(hooks);
248 void hooks_fire(EventData *data)
250 PyObject *ret, *args;
252 g_assert(events_hook != NULL);
254 args = Py_BuildValue("(O)", data);
255 ret = hook_fire(events_hook, args);
256 Py_DECREF(args);
257 if (ret == NULL)
258 PyErr_Print();
261 void hooks_fire_keyboard(EventData *data)
263 PyObject *ret, *args;
265 g_assert(events_hook != NULL);
267 args = Py_BuildValue("(O)", data);
268 ret = hook_fire(keyboard_hook, args);
269 Py_DECREF(args);
270 if (ret == NULL)
271 PyErr_Print();
274 void hooks_fire_pointer(EventData *data)
276 PyObject *ret, *args;
278 g_assert(events_hook != NULL);
280 args = Py_BuildValue("(O)", data);
281 ret = hook_fire(pointer_hook, args);
282 Py_DECREF(args);
283 if (ret == NULL)
284 PyErr_Print();