]> Dogcows Code - chaz/openbox/blob - openbox/hooks.c
merge the C branch into HEAD
[chaz/openbox] / openbox / hooks.c
1 #include "hooks.h"
2 #include <glib.h>
3
4 /*
5 *
6 * Define the 'Hook' class type
7 *
8 */
9 #define IS_HOOK(v) ((v)->ob_type == &HookType)
10
11 staticforward PyTypeObject HookType;
12
13 typedef struct HookObject {
14 PyObject_HEAD
15 GSList *funcs;
16 } HookObject;
17
18 static int hook_init(HookObject *self, PyObject *args, PyObject *kwds)
19 {
20 char *keywords[] = { 0 };
21 if (!PyArg_ParseTupleAndKeywords(args, kwds, ":__init__", keywords))
22 return -1;
23 self->funcs = NULL;
24 return 0;
25 }
26
27 static void hook_dealloc(HookObject *self)
28 {
29 GSList *it;
30
31 for (it = self->funcs; it != NULL; it = it->next)
32 Py_DECREF((PyObject*) it->data);
33
34 PyObject_Del((PyObject*) self);
35 }
36
37 static PyObject *hook_fire(HookObject *self, PyObject *args)
38 {
39 GSList *it;
40
41 if (!IS_HOOK(self)) {
42 PyErr_SetString(PyExc_TypeError,
43 "descriptor 'fire' requires a 'Hook' object");
44 return NULL;
45 }
46
47 for (it = self->funcs; it != NULL; it = it->next) {
48 PyObject *ret = PyObject_CallObject(it->data, args);
49 if (ret == NULL)
50 return NULL;
51 Py_DECREF(ret);
52 }
53
54 Py_INCREF(Py_None);
55 return Py_None;
56 }
57
58 static PyObject *hook_append(HookObject *self, PyObject *args)
59 {
60 PyObject *func;
61
62 if (!IS_HOOK(self)) {
63 PyErr_SetString(PyExc_TypeError,
64 "descriptor 'append' requires a 'Hook' object");
65 return NULL;
66 }
67 if (!PyArg_ParseTuple(args, "O:append", &func))
68 return NULL;
69 if (!PyCallable_Check(func)) {
70 PyErr_SetString(PyExc_TypeError,
71 "descriptor 'append' requires a callable argument");
72 return NULL;
73 }
74 self->funcs = g_slist_append(self->funcs, func);
75 Py_INCREF(func);
76
77 Py_INCREF(Py_None);
78 return Py_None;
79 }
80
81 static PyObject *hook_remove(HookObject *self, PyObject *args)
82 {
83 PyObject *func;
84 GSList *it;
85
86 if (!IS_HOOK(self)) {
87 PyErr_SetString(PyExc_TypeError,
88 "descriptor 'remove' requires a 'Hook' object");
89 return NULL;
90 }
91 if (!PyArg_ParseTuple(args, "O:remove", &func))
92 return NULL;
93 if (!PyCallable_Check(func)) {
94 PyErr_SetString(PyExc_TypeError,
95 "descriptor 'remove' requires a callable argument");
96 return NULL;
97 }
98
99 it = g_slist_find(self->funcs, func);
100 if (it != NULL) {
101 self->funcs = g_slist_delete_link(self->funcs, it);
102 Py_DECREF(func);
103
104 Py_INCREF(Py_None);
105 return Py_None;
106 }
107 PyErr_SetString(PyExc_TypeError,
108 "given callable object was not found in Hook");
109 return NULL;
110 }
111
112 static PyObject *hook_call(HookObject *self, PyObject *args)
113 {
114 GSList *it, *next;
115 gboolean stop = FALSE;
116
117 if (!IS_HOOK(self)) {
118 PyErr_SetString(PyExc_TypeError,
119 "descriptor '__call__' requires a 'Hook' object");
120 return NULL;
121 }
122
123 for (it = self->funcs; !stop && it != NULL;) {
124 next = it->next; /* incase the hook removes itself */
125
126 PyObject *ret = PyObject_CallObject(it->data, args);
127 if (ret == NULL)
128 return NULL;
129 if (ret != Py_None)
130 stop = TRUE;
131 Py_DECREF(ret);
132
133 it = next;
134 }
135
136 Py_INCREF(Py_None);
137 return Py_None;
138 }
139
140 static PyTypeObject HookType = {
141 PyObject_HEAD_INIT(NULL)
142 0,
143 "Hook",
144 sizeof(HookObject),
145 0,
146 (destructor) hook_dealloc, /*tp_dealloc*/
147 0, /*tp_print*/
148 0, /*tp_getattr*/
149 0, /*tp_setattr*/
150 0, /*tp_compare*/
151 0, /*tp_repr*/
152 0, /*tp_as_number*/
153 0, /*tp_as_sequence*/
154 0, /*tp_as_mapping*/
155 0, /*tp_hash */
156 };
157
158 static PyMethodDef HookMethods[] = {
159 {"append", (PyCFunction)hook_append, METH_VARARGS,
160 "hook.add(func) -- Add a function to the hook." },
161 {"remove", (PyCFunction)hook_remove, METH_VARARGS,
162 "hook.remove(func) -- Remove a function from the hook." },
163 { NULL, NULL, 0, NULL }
164 };
165
166
167 /*
168 *
169 * Module initialization/finalization
170 *
171 */
172
173 static PyObject *hooks, *hooksdict;
174
175 static PyMethodDef HooksMethods[] = {
176 { NULL, NULL, 0, NULL }
177 };
178
179 struct HookObject *hooks_create(char *name)
180 {
181 HookObject *hook;
182 int ret;
183
184 hook = PyObject_New(HookObject, &HookType);
185 hook->funcs = NULL;
186
187 /* add it to the hooks module */
188 ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook);
189 g_assert(ret != -1);
190
191 return hook;
192 }
193
194 void hooks_startup()
195 {
196 HookType.ob_type = &PyType_Type;
197 HookType.tp_methods = HookMethods;
198 HookType.tp_alloc = PyType_GenericAlloc;
199 HookType.tp_new = PyType_GenericNew;
200 HookType.tp_init = (initproc) hook_init;
201 HookType.tp_call = (ternaryfunc) hook_call;
202 PyType_Ready(&HookType);
203
204 Py_InitModule("hooks", HooksMethods);
205
206 /* get the hooks module/dict */
207 hooks = PyImport_ImportModule("hooks"); /* new */
208 g_assert(hooks != NULL);
209 hooksdict = PyModule_GetDict(hooks); /* borrowed */
210 g_assert(hooksdict != NULL);
211
212 /* add the Hook type to the hooks module */
213 PyDict_SetItemString(hooksdict, "Hook", (PyObject*) &HookType);
214
215 hook_startup = hooks_create("startup");
216 hook_shutdown = hooks_create("shutdown");
217 hook_visibledesktop = hooks_create("visibledesktop");
218 hook_numdesktops = hooks_create("numdesktops");
219 hook_desktopnames = hooks_create("desktopnames");
220 hook_showdesktop = hooks_create("showdesktop");
221 hook_screenconfiguration = hooks_create("screenconfiguration");
222 hook_screenarea = hooks_create("screenarea");
223 hook_managed = hooks_create("managed");
224 hook_closed = hooks_create("closed");
225 hook_bell = hooks_create("bell");
226 hook_urgent = hooks_create("urgent");
227 hook_pointerenter = hooks_create("pointerenter");
228 hook_pointerleave = hooks_create("pointerleave");
229 hook_focused = hooks_create("focused");
230 hook_requestactivate = hooks_create("requestactivate");
231 hook_title = hooks_create("title");
232 hook_desktop = hooks_create("desktop");
233 hook_iconic = hooks_create("iconic");
234 hook_shaded = hooks_create("shaded");
235 hook_maximized = hooks_create("maximized");
236 hook_fullscreen = hooks_create("fullscreen");
237 hook_visible = hooks_create("visible");
238 hook_configuration = hooks_create("configuration");
239 }
240
241 void hooks_shutdown()
242 {
243 Py_DECREF(hook_startup);
244 Py_DECREF(hook_shutdown);
245 Py_DECREF(hook_visibledesktop);
246 Py_DECREF(hook_numdesktops);
247 Py_DECREF(hook_desktopnames);
248 Py_DECREF(hook_showdesktop);
249 Py_DECREF(hook_screenconfiguration);
250 Py_DECREF(hook_screenarea);
251 Py_DECREF(hook_managed);
252 Py_DECREF(hook_closed);
253 Py_DECREF(hook_bell);
254 Py_DECREF(hook_urgent);
255 Py_DECREF(hook_pointerenter);
256 Py_DECREF(hook_pointerleave);
257 Py_DECREF(hook_focused);
258 Py_DECREF(hook_requestactivate);
259 Py_DECREF(hook_title);
260 Py_DECREF(hook_desktop);
261 Py_DECREF(hook_iconic);
262 Py_DECREF(hook_shaded);
263 Py_DECREF(hook_maximized);
264 Py_DECREF(hook_fullscreen);
265 Py_DECREF(hook_visible);
266 Py_DECREF(hook_configuration);
267
268 Py_DECREF(hooks);
269 }
270
271 void hooks_fire(struct HookObject *hook, PyObject *args)
272 {
273 PyObject *ret = hook_call(hook, args);
274 if (ret == NULL)
275 PyErr_Print();
276 Py_XDECREF(ret);
277 }
278
279 void hooks_fire_client(struct HookObject *hook, struct Client *client)
280 {
281 PyObject *args;
282
283 if (client != NULL) {
284 PyObject *c = clientwrap_new(client);
285 g_assert(c != NULL);
286 args = Py_BuildValue("(O)", c);
287 Py_DECREF(c);
288 } else {
289 args = Py_BuildValue("(O)", Py_None);
290 }
291
292 g_assert(args != NULL);
293 hooks_fire(hook, args);
294 Py_DECREF(args);
295 }
This page took 0.049884 seconds and 4 git commands to generate.