From a47d0a53652a96ca1df96fc9268757df1431ae55 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 1 Mar 2008 01:52:38 -0500 Subject: [PATCH] queue hooks so that they don't run as each thing happens, instead run them at the end. keep the openbox code paths fast. --- openbox/client.c | 20 ++++++++++-------- openbox/event.c | 5 +++++ openbox/focus.c | 4 ++-- openbox/hooks.c | 54 +++++++++++++++++++++++++++++++++++++++++------- openbox/hooks.h | 7 +++---- openbox/screen.c | 2 +- 6 files changed, 68 insertions(+), 24 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 7c23e8e0..c0864bc4 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -562,7 +562,7 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Managed window 0x%lx plate 0x%x (%s)", window, self->frame->window, self->class); - hooks_run(OB_HOOK_WIN_NEW, self); + hooks_queue(OB_HOOK_WIN_NEW, self); } @@ -638,6 +638,7 @@ void client_unmanage(ObClient *self) if (!self->prompt) XChangeSaveSet(obt_display, self->window, SetModeDelete); + /* this can't be queued to run later */ hooks_run(OB_HOOK_WIN_CLOSE, self); /* update the focus lists */ @@ -2525,7 +2526,7 @@ gboolean client_show(ObClient *self) */ client_change_wm_state(self); - hooks_run(OB_HOOK_WIN_VISIBLE, self); + hooks_queue(OB_HOOK_WIN_VISIBLE, self); } return show; } @@ -2565,7 +2566,7 @@ gboolean client_hide(ObClient *self) */ client_change_wm_state(self); - hooks_run(OB_HOOK_WIN_INVISIBLE, self); + hooks_queue(OB_HOOK_WIN_INVISIBLE, self); } return hide; } @@ -3162,7 +3163,8 @@ static void client_iconify_recursive(ObClient *self, /* do this after starting the animation so it doesn't flash */ client_showhide(self); - hooks_run((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC), self); + hooks_queue((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC), + self); } /* iconify all direct transients, and deiconify all transients @@ -3251,7 +3253,7 @@ void client_maximize(ObClient *self, gboolean max, gint dir) client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); - hooks_run((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self); + hooks_queue((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self); } void client_shade(ObClient *self, gboolean shade) @@ -3266,7 +3268,7 @@ void client_shade(ObClient *self, gboolean shade) /* resize the frame to just the titlebar */ frame_adjust_area(self->frame, FALSE, TRUE, FALSE); - hooks_run((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self); + hooks_queue((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self); } static void client_ping_event(ObClient *self, gboolean dead) @@ -3470,7 +3472,7 @@ static void client_set_desktop_recursive(ObClient *self, client_reconfigure(self, FALSE); if (old != self->desktop) - hooks_run(OB_HOOK_WIN_DESK_CHANGE, self); + hooks_queue(OB_HOOK_WIN_DESK_CHANGE, self); } /* move all transients */ @@ -3874,8 +3876,8 @@ void client_set_undecorated(ObClient *self, gboolean undecorated) client_setup_decor_and_functions(self, TRUE); client_change_state(self); /* reflect this in the state hints */ - hooks_run((undecorated ? - OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self); + hooks_queue((undecorated ? + OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self); } } diff --git a/openbox/event.c b/openbox/event.c index 142cf1f2..2563be2b 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -738,6 +738,11 @@ static void event_process(const XEvent *ec, gpointer data) e->type == MotionNotify) event_handle_user_input(client, e); + XFlush(obt_display); + + /* run all the hooks at once */ + hooks_run_queue(); + /* if something happens and it's not from an XEvent, then we don't know the time */ event_curtime = CurrentTime; diff --git a/openbox/focus.c b/openbox/focus.c index 5eb27bc4..23cf9101 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -105,8 +105,8 @@ void focus_set_client(ObClient *client) OBT_PROP_SET32(obt_root(ob_screen), NET_ACTIVE_WINDOW, WINDOW, active); } - hooks_run(OB_HOOK_WIN_UNFOCUS, old); - hooks_run(OB_HOOK_WIN_FOCUS, client); + hooks_queue(OB_HOOK_WIN_UNFOCUS, old); + hooks_queue(OB_HOOK_WIN_FOCUS, client); } static ObClient* focus_fallback_target(gboolean allow_refocus, diff --git a/openbox/hooks.c b/openbox/hooks.c index 7d7f7007..ad57fdb8 100644 --- a/openbox/hooks.c +++ b/openbox/hooks.c @@ -3,12 +3,22 @@ #include "client.h" #include "focus.h" #include "debug.h" +#include "obt/display.h" #include static GSList *hooks[OB_NUM_HOOKS]; static const gchar *names[OB_NUM_HOOKS]; +typedef struct { + ObHook hook; + struct _ObClient *client; +} ObHookQueue; + +#define QUEUE_SIZE 20 +ObHookQueue run_queue[QUEUE_SIZE]; +gint queue_size; + void hooks_startup(gboolean reconfig) { gint i; @@ -16,6 +26,8 @@ void hooks_startup(gboolean reconfig) 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"; @@ -55,19 +67,27 @@ ObHook hooks_hook_from_name(const gchar *n) return OB_HOOK_INVALID; } -void hooks_run(ObHook hook, struct _ObClient *client) +void hooks_queue(ObHook hook, struct _ObClient *client) { - GSList *it; + ObHookQueue *q; g_assert(hook < OB_NUM_HOOKS && hook > OB_HOOK_INVALID); - ob_debug("Running hook %s for client 0x%x", names[hook], + ob_debug("Queing hook %s for client 0x%x", names[hook], (client ? client->window : 0)); - actions_run_acts(hooks[hook], - OB_USER_ACTION_HOOK, - 0, -1, -1, 0, - OB_FRAME_CONTEXT_NONE, - client); + q = &run_queue[queue_size++]; + q->hook = hook; + q->client = client; + + if (queue_size == QUEUE_SIZE) + /* queue is full */ + hooks_run_queue(); +} + +void hooks_run(ObHook hook, struct _ObClient *c) +{ + hooks_queue(hook, c); + hooks_run_queue(); } void hooks_add(ObHook hook, struct _ObActionsAct *act) @@ -78,3 +98,21 @@ void hooks_add(ObHook hook, struct _ObActionsAct *act) config file */ hooks[hook] = g_slist_append(hooks[hook], act); } + +void hooks_run_queue(void) +{ + 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); + } + queue_size = 0; +} diff --git a/openbox/hooks.h b/openbox/hooks.h index 442eef01..322f952d 100644 --- a/openbox/hooks.h +++ b/openbox/hooks.h @@ -32,12 +32,11 @@ void hooks_shutdown(gboolean reconfig); ObHook hooks_hook_from_name(const gchar *n); -/*! Run a hook. - @param on TRUE if the hook is being run cuz a state was turned on, FALSE - if a state was turned off -*/ +void hooks_queue(ObHook hook, struct _ObClient *c); void hooks_run(ObHook hook, struct _ObClient *c); void hooks_add(ObHook hook, struct _ObActionsAct *act); +void hooks_run_queue(void); + #endif diff --git a/openbox/screen.c b/openbox/screen.c index 3432ac43..cd46c53b 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -710,7 +710,7 @@ void screen_set_desktop(guint num, gboolean dofocus) if (event_curtime != CurrentTime) screen_desktop_user_time = event_curtime; - hooks_run(OB_HOOK_SCREEN_DESK_CHANGE, NULL); + hooks_queue(OB_HOOK_SCREEN_DESK_CHANGE, NULL); } void screen_add_desktop(gboolean current) -- 2.45.2