diff options
| author | Dana Jansens <danakj@orodu.net> | 2003-03-16 21:11:39 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2003-03-16 21:11:39 +0000 |
| commit | f8a47de5ec444c452093371e3db16857eb39a490 (patch) | |
| tree | 31db2567842d98232775f9980f7a8d2586c0ac71 /openbox/hooks.c | |
| parent | 8ba0586bcbdc7fe9648f1063812126d71a041670 (diff) | |
merge the C branch into HEAD
Diffstat (limited to 'openbox/hooks.c')
| -rw-r--r-- | openbox/hooks.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/openbox/hooks.c b/openbox/hooks.c new file mode 100644 index 00000000..35d8d694 --- /dev/null +++ b/openbox/hooks.c @@ -0,0 +1,295 @@ +#include "hooks.h" +#include <glib.h> + +/* + * + * Define the 'Hook' class type + * + */ +#define IS_HOOK(v) ((v)->ob_type == &HookType) + +staticforward PyTypeObject HookType; + +typedef struct HookObject { + PyObject_HEAD + GSList *funcs; +} HookObject; + +static int hook_init(HookObject *self, PyObject *args, PyObject *kwds) +{ + char *keywords[] = { 0 }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, ":__init__", keywords)) + return -1; + self->funcs = NULL; + return 0; +} + +static void hook_dealloc(HookObject *self) +{ + GSList *it; + + for (it = self->funcs; it != NULL; it = it->next) + Py_DECREF((PyObject*) it->data); + + PyObject_Del((PyObject*) self); +} + +static PyObject *hook_fire(HookObject *self, PyObject *args) +{ + GSList *it; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'fire' requires a 'Hook' object"); + return NULL; + } + + for (it = self->funcs; it != NULL; it = it->next) { + PyObject *ret = PyObject_CallObject(it->data, args); + if (ret == NULL) + return NULL; + Py_DECREF(ret); + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *hook_append(HookObject *self, PyObject *args) +{ + PyObject *func; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'append' requires a 'Hook' object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "O:append", &func)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'append' requires a callable argument"); + return NULL; + } + self->funcs = g_slist_append(self->funcs, func); + Py_INCREF(func); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *hook_remove(HookObject *self, PyObject *args) +{ + PyObject *func; + GSList *it; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'remove' requires a 'Hook' object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "O:remove", &func)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'remove' requires a callable argument"); + return NULL; + } + + it = g_slist_find(self->funcs, func); + if (it != NULL) { + self->funcs = g_slist_delete_link(self->funcs, it); + Py_DECREF(func); + + Py_INCREF(Py_None); + return Py_None; + } + PyErr_SetString(PyExc_TypeError, + "given callable object was not found in Hook"); + return NULL; +} + +static PyObject *hook_call(HookObject *self, PyObject *args) +{ + GSList *it, *next; + gboolean stop = FALSE; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor '__call__' requires a 'Hook' object"); + return NULL; + } + + for (it = self->funcs; !stop && it != NULL;) { + next = it->next; /* incase the hook removes itself */ + + PyObject *ret = PyObject_CallObject(it->data, args); + if (ret == NULL) + return NULL; + if (ret != Py_None) + stop = TRUE; + Py_DECREF(ret); + + it = next; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyTypeObject HookType = { + PyObject_HEAD_INIT(NULL) + 0, + "Hook", + sizeof(HookObject), + 0, + (destructor) hook_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +static PyMethodDef HookMethods[] = { + {"append", (PyCFunction)hook_append, METH_VARARGS, + "hook.add(func) -- Add a function to the hook." }, + {"remove", (PyCFunction)hook_remove, METH_VARARGS, + "hook.remove(func) -- Remove a function from the hook." }, + { NULL, NULL, 0, NULL } +}; + + +/* + * + * Module initialization/finalization + * + */ + +static PyObject *hooks, *hooksdict; + +static PyMethodDef HooksMethods[] = { + { NULL, NULL, 0, NULL } +}; + +struct HookObject *hooks_create(char *name) +{ + HookObject *hook; + int ret; + + hook = PyObject_New(HookObject, &HookType); + hook->funcs = NULL; + + /* add it to the hooks module */ + ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook); + g_assert(ret != -1); + + return hook; +} + +void hooks_startup() +{ + HookType.ob_type = &PyType_Type; + HookType.tp_methods = HookMethods; + HookType.tp_alloc = PyType_GenericAlloc; + HookType.tp_new = PyType_GenericNew; + HookType.tp_init = (initproc) hook_init; + HookType.tp_call = (ternaryfunc) hook_call; + PyType_Ready(&HookType); + + Py_InitModule("hooks", HooksMethods); + + /* get the hooks module/dict */ + hooks = PyImport_ImportModule("hooks"); /* new */ + g_assert(hooks != NULL); + hooksdict = PyModule_GetDict(hooks); /* borrowed */ + g_assert(hooksdict != NULL); + + /* add the Hook type to the hooks module */ + PyDict_SetItemString(hooksdict, "Hook", (PyObject*) &HookType); + + hook_startup = hooks_create("startup"); + hook_shutdown = hooks_create("shutdown"); + hook_visibledesktop = hooks_create("visibledesktop"); + hook_numdesktops = hooks_create("numdesktops"); + hook_desktopnames = hooks_create("desktopnames"); + hook_showdesktop = hooks_create("showdesktop"); + hook_screenconfiguration = hooks_create("screenconfiguration"); + hook_screenarea = hooks_create("screenarea"); + hook_managed = hooks_create("managed"); + hook_closed = hooks_create("closed"); + hook_bell = hooks_create("bell"); + hook_urgent = hooks_create("urgent"); + hook_pointerenter = hooks_create("pointerenter"); + hook_pointerleave = hooks_create("pointerleave"); + hook_focused = hooks_create("focused"); + hook_requestactivate = hooks_create("requestactivate"); + hook_title = hooks_create("title"); + hook_desktop = hooks_create("desktop"); + hook_iconic = hooks_create("iconic"); + hook_shaded = hooks_create("shaded"); + hook_maximized = hooks_create("maximized"); + hook_fullscreen = hooks_create("fullscreen"); + hook_visible = hooks_create("visible"); + hook_configuration = hooks_create("configuration"); +} + +void hooks_shutdown() +{ + Py_DECREF(hook_startup); + Py_DECREF(hook_shutdown); + Py_DECREF(hook_visibledesktop); + Py_DECREF(hook_numdesktops); + Py_DECREF(hook_desktopnames); + Py_DECREF(hook_showdesktop); + Py_DECREF(hook_screenconfiguration); + Py_DECREF(hook_screenarea); + Py_DECREF(hook_managed); + Py_DECREF(hook_closed); + Py_DECREF(hook_bell); + Py_DECREF(hook_urgent); + Py_DECREF(hook_pointerenter); + Py_DECREF(hook_pointerleave); + Py_DECREF(hook_focused); + Py_DECREF(hook_requestactivate); + Py_DECREF(hook_title); + Py_DECREF(hook_desktop); + Py_DECREF(hook_iconic); + Py_DECREF(hook_shaded); + Py_DECREF(hook_maximized); + Py_DECREF(hook_fullscreen); + Py_DECREF(hook_visible); + Py_DECREF(hook_configuration); + + Py_DECREF(hooks); +} + +void hooks_fire(struct HookObject *hook, PyObject *args) +{ + PyObject *ret = hook_call(hook, args); + if (ret == NULL) + PyErr_Print(); + Py_XDECREF(ret); +} + +void hooks_fire_client(struct HookObject *hook, struct Client *client) +{ + PyObject *args; + + if (client != NULL) { + PyObject *c = clientwrap_new(client); + g_assert(c != NULL); + args = Py_BuildValue("(O)", c); + Py_DECREF(c); + } else { + args = Py_BuildValue("(O)", Py_None); + } + + g_assert(args != NULL); + hooks_fire(hook, args); + Py_DECREF(args); +} |
