53586db8ad3f919aa76c946304f260ab51afa70e
[dana/openbox.git] / openbox / hooks.c
1 #include "hooks.h"
2 #include "actions.h"
3 #include "client.h"
4 #include "focus.h"
5 #include "debug.h"
6 #include "obt/display.h"
7
8 #include <glib.h>
9
10 static GSList *hooks[OB_NUM_HOOKS];
11 static const gchar *names[OB_NUM_HOOKS];
12
13 typedef struct {
14     ObHook hook;
15     struct _ObClient *client;
16 } ObHookQueue;
17
18 #define QUEUE_SIZE 20
19 ObHookQueue run_queue[QUEUE_SIZE];
20 gint        queue_size;
21
22 void hooks_startup(gboolean reconfig)
23 {
24     gint i;
25
26     for (i = 0; i < OB_NUM_HOOKS; ++i)
27         hooks[i] = NULL;
28
29     queue_size = 0;
30
31     names[OB_HOOK_WIN_NEW] = "WindowNew";
32     names[OB_HOOK_WIN_CLOSE] = "WindowClosed";
33     names[OB_HOOK_WIN_VISIBLE] = "WindowVisible";
34     names[OB_HOOK_WIN_INVISIBLE] = "WindowInvisible";
35     names[OB_HOOK_WIN_ICONIC] = "WindowIconified";
36     names[OB_HOOK_WIN_UNICONIC] = "WindowUniconified";
37     names[OB_HOOK_WIN_MAX] = "WindowMaximized";
38     names[OB_HOOK_WIN_UNMAX] = "WindowUnmaximized";
39     names[OB_HOOK_WIN_SHADE] = "WindowShaded";
40     names[OB_HOOK_WIN_UNSHADE] = "WindowUnshaded";
41     names[OB_HOOK_WIN_FOCUS] = "WindowFocused";
42     names[OB_HOOK_WIN_UNFOCUS] = "WindowUnfocused";
43     names[OB_HOOK_WIN_DESK_CHANGE] = "WindowOnNewDesktop";
44     names[OB_HOOK_WIN_DECORATED] = "WindowDecorated";
45     names[OB_HOOK_WIN_UNDECORATED] = "WindowUndecorated";
46     names[OB_HOOK_SCREEN_DESK_CHANGE] = "DesktopChanged";
47 }
48
49 void hooks_shutdown(gboolean reconfig)
50 {
51     gint i;
52
53     for (i = 0; i < OB_NUM_HOOKS; ++i)
54         while (hooks[i]) {
55             actions_act_unref(hooks[i]->data);
56             hooks[i] = g_slist_delete_link(hooks[i], hooks[i]);
57         }
58 }
59
60 ObHook hooks_hook_from_name(const gchar *n)
61 {
62     gint i;
63
64     for (i = 1; i < OB_NUM_HOOKS; ++i)
65         if (!g_ascii_strcasecmp(n, names[i]))
66             return (ObHook)i;
67     return OB_HOOK_INVALID;
68 }
69
70 void hooks_queue(ObHook hook, struct _ObClient *client)
71 {
72     ObHookQueue *q;
73
74     g_assert(hook < OB_NUM_HOOKS && hook > OB_HOOK_INVALID);
75
76     //ob_debug("Queing hook %s for client 0x%x", names[hook],
77     //         (client ? client->window : 0));
78     q = &run_queue[queue_size++];
79     q->hook = hook;
80     q->client = client;
81
82     if (queue_size == QUEUE_SIZE)
83         /* queue is full */
84         hooks_run_queue();
85 }
86
87 void hooks_run(ObHook hook, struct _ObClient *c)
88 {
89     hooks_queue(hook, c);
90     hooks_run_queue();
91 }
92
93 void hooks_add(ObHook hook, struct _ObActionsAct *act)
94 {
95     g_assert(hook < OB_NUM_HOOKS && hook > OB_HOOK_INVALID);
96
97     /* append so they are executed in the same order as they appear in the
98        config file */
99     hooks[hook] = g_slist_append(hooks[hook], act);
100 }
101
102 void hooks_run_queue(void)
103 {
104     gint i;
105
106     for (i = 0; i < queue_size; ++i) {
107         const ObHookQueue *q = &run_queue[i];
108
109         //ob_debug("Running hook %s for client 0x%x", names[q->hook],
110         //         (q->client ? q->client->window : 0));
111         actions_run_acts(hooks[q->hook],
112                          OB_USER_ACTION_HOOK,
113                          0, -1, -1, 0,
114                          OB_FRAME_CONTEXT_NONE,
115                          q->client);
116     }
117     queue_size = 0;
118 }