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);
}
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 */
*/
client_change_wm_state(self);
- hooks_run(OB_HOOK_WIN_VISIBLE, self);
+ hooks_queue(OB_HOOK_WIN_VISIBLE, self);
}
return show;
}
*/
client_change_wm_state(self);
- hooks_run(OB_HOOK_WIN_INVISIBLE, self);
+ hooks_queue(OB_HOOK_WIN_INVISIBLE, self);
}
return hide;
}
/* 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
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)
/* 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)
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 */
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);
}
}
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;
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,
#include "client.h"
#include "focus.h"
#include "debug.h"
+#include "obt/display.h"
#include <glib.h>
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;
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";
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)
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;
+}
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
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)