X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fhooks.c;h=53586db8ad3f919aa76c946304f260ab51afa70e;hb=308478e4a5f4dc76d69395dda8a9bc42cb69eec4;hp=35d8d694f39b8b0324a8ac15b20e429ae718e810;hpb=f8a47de5ec444c452093371e3db16857eb39a490;p=chaz%2Fopenbox diff --git a/openbox/hooks.c b/openbox/hooks.c index 35d8d694..53586db8 100644 --- a/openbox/hooks.c +++ b/openbox/hooks.c @@ -1,295 +1,118 @@ #include "hooks.h" -#include - -/* - * - * 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); -} +#include "actions.h" +#include "client.h" +#include "focus.h" +#include "debug.h" +#include "obt/display.h" -static PyObject *hook_fire(HookObject *self, PyObject *args) -{ - GSList *it; +#include - if (!IS_HOOK(self)) { - PyErr_SetString(PyExc_TypeError, - "descriptor 'fire' requires a 'Hook' object"); - return NULL; - } +static GSList *hooks[OB_NUM_HOOKS]; +static const gchar *names[OB_NUM_HOOKS]; - for (it = self->funcs; it != NULL; it = it->next) { - PyObject *ret = PyObject_CallObject(it->data, args); - if (ret == NULL) - return NULL; - Py_DECREF(ret); - } +typedef struct { + ObHook hook; + struct _ObClient *client; +} ObHookQueue; - Py_INCREF(Py_None); - return Py_None; -} +#define QUEUE_SIZE 20 +ObHookQueue run_queue[QUEUE_SIZE]; +gint queue_size; -static PyObject *hook_append(HookObject *self, PyObject *args) +void hooks_startup(gboolean reconfig) { - 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; + gint i; + + for (i = 0; i < OB_NUM_HOOKS; ++i) + hooks[i] = NULL; + + queue_size = 0; + + names[OB_HOOK_WIN_NEW] = "WindowNew"; + names[OB_HOOK_WIN_CLOSE] = "WindowClosed"; + names[OB_HOOK_WIN_VISIBLE] = "WindowVisible"; + names[OB_HOOK_WIN_INVISIBLE] = "WindowInvisible"; + names[OB_HOOK_WIN_ICONIC] = "WindowIconified"; + names[OB_HOOK_WIN_UNICONIC] = "WindowUniconified"; + names[OB_HOOK_WIN_MAX] = "WindowMaximized"; + names[OB_HOOK_WIN_UNMAX] = "WindowUnmaximized"; + names[OB_HOOK_WIN_SHADE] = "WindowShaded"; + names[OB_HOOK_WIN_UNSHADE] = "WindowUnshaded"; + names[OB_HOOK_WIN_FOCUS] = "WindowFocused"; + names[OB_HOOK_WIN_UNFOCUS] = "WindowUnfocused"; + names[OB_HOOK_WIN_DESK_CHANGE] = "WindowOnNewDesktop"; + names[OB_HOOK_WIN_DECORATED] = "WindowDecorated"; + names[OB_HOOK_WIN_UNDECORATED] = "WindowUndecorated"; + names[OB_HOOK_SCREEN_DESK_CHANGE] = "DesktopChanged"; } -static PyObject *hook_remove(HookObject *self, PyObject *args) +void hooks_shutdown(gboolean reconfig) { - 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); + gint i; - Py_INCREF(Py_None); - return Py_None; - } - PyErr_SetString(PyExc_TypeError, - "given callable object was not found in Hook"); - return NULL; + for (i = 0; i < OB_NUM_HOOKS; ++i) + while (hooks[i]) { + actions_act_unref(hooks[i]->data); + hooks[i] = g_slist_delete_link(hooks[i], hooks[i]); + } } -static PyObject *hook_call(HookObject *self, PyObject *args) +ObHook hooks_hook_from_name(const gchar *n) { - GSList *it, *next; - gboolean stop = FALSE; - - if (!IS_HOOK(self)) { - PyErr_SetString(PyExc_TypeError, - "descriptor '__call__' requires a 'Hook' object"); - return NULL; - } + gint i; - 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; + for (i = 1; i < OB_NUM_HOOKS; ++i) + if (!g_ascii_strcasecmp(n, names[i])) + return (ObHook)i; + return OB_HOOK_INVALID; } -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) +void hooks_queue(ObHook hook, struct _ObClient *client) { - HookObject *hook; - int ret; + ObHookQueue *q; - hook = PyObject_New(HookObject, &HookType); - hook->funcs = NULL; + g_assert(hook < OB_NUM_HOOKS && hook > OB_HOOK_INVALID); - /* add it to the hooks module */ - ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook); - g_assert(ret != -1); + //ob_debug("Queing hook %s for client 0x%x", names[hook], + // (client ? client->window : 0)); + q = &run_queue[queue_size++]; + q->hook = hook; + q->client = client; - return hook; + if (queue_size == QUEUE_SIZE) + /* queue is full */ + hooks_run_queue(); } -void hooks_startup() +void hooks_run(ObHook hook, struct _ObClient *c) { - 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"); + hooks_queue(hook, c); + hooks_run_queue(); } -void hooks_shutdown() +void hooks_add(ObHook hook, struct _ObActionsAct *act) { - 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); + g_assert(hook < OB_NUM_HOOKS && hook > OB_HOOK_INVALID); - Py_DECREF(hooks); + /* append so they are executed in the same order as they appear in the + config file */ + hooks[hook] = g_slist_append(hooks[hook], act); } -void hooks_fire(struct HookObject *hook, PyObject *args) +void hooks_run_queue(void) { - 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); + gint i; + + for (i = 0; i < queue_size; ++i) { + const ObHookQueue *q = &run_queue[i]; + + //ob_debug("Running hook %s for client 0x%x", names[q->hook], + // (q->client ? q->client->window : 0)); + actions_run_acts(hooks[q->hook], + OB_USER_ACTION_HOOK, + 0, -1, -1, 0, + OB_FRAME_CONTEXT_NONE, + q->client); } - - g_assert(args != NULL); - hooks_fire(hook, args); - Py_DECREF(args); + queue_size = 0; }