add a dispatched event for interactively moving a window.
[mikachu/openbox.git] / openbox / dispatch.c
1 #include "dispatch.h"
2 #include "extensions.h"
3
4 #include <glib.h>
5
6 typedef struct {
7     EventHandler h;
8     void *data;
9 } Func;
10
11 /* an array of GSList*s of Func*s */
12 static GSList **funcs;
13
14 void dispatch_startup()
15 {
16     guint i;
17     EventType j;
18
19     i = 0;
20     j = EVENT_RANGE;
21     while (j > 1) {
22         j >>= 1;
23         ++i;
24     }
25     funcs = g_new(GSList*, i);
26
27     for (i = 0, j = 1; j < EVENT_RANGE; ++i, j <<= 1)
28         funcs[i] = NULL;
29 }
30
31 void dispatch_shutdown()
32 {
33     guint i;
34     EventType j;
35     GSList *it;
36
37     for (i = 0, j = 1; j < EVENT_RANGE; ++i, j <<= 1) {
38         for (it = funcs[i]; it != NULL; it = it->next)
39             g_free(it->data);
40         g_slist_free(funcs[i]);
41         funcs[i] = NULL;
42     }
43
44     g_free(funcs);
45 }
46
47 void dispatch_register(EventMask mask, EventHandler h, void *data)
48 {
49     guint i;
50     EventType j;
51     GSList *it, *next;
52     EventMask m;
53     Func *f;
54
55     /* add to masks it needs to be registered for */
56     m = mask;
57     while (m) {
58         for (i = 0, j = 1; j < EVENT_RANGE; ++i, j <<= 1)
59             if (m & j) {
60                 for (it = funcs[i]; it != NULL; it = it->next) {
61                     f = it->data;
62                     if (f->h == h && f->data == data)
63                         break;
64                 }
65                 if (it == NULL) { /* wasn't already regged */
66                     f = g_new(Func, 1);
67                     f->h = h;
68                     f->data = data;
69                     funcs[i] = g_slist_append(funcs[i], f);
70                 }
71                 m ^= j; /* remove from the mask */
72             }
73         g_assert(j >= EVENT_RANGE); /* an invalid event is in the mask */
74     }
75
76     /* remove from masks its not registered for anymore */
77     for (i = 0, j = 1; j < EVENT_RANGE; ++i, j <<= 1) {
78         if (!(j & mask))
79             for (it = funcs[i]; it != NULL; it = next) {
80                 next = it->next;
81                 f = it->data;
82                 if (f->h == h && f->data == data) {
83                     g_free(f);
84                     funcs[i] = g_slist_delete_link(funcs[i], it);
85                 }
86             }
87     }
88 }
89
90 void dispatch_x(XEvent *xe, Client *c)
91 {
92     EventType e;
93     guint i;
94     GSList *it;
95     ObEvent obe;
96
97     switch (xe->type) {
98     case EnterNotify:
99         e = Event_X_EnterNotify;
100         break;
101     case LeaveNotify:
102         e = Event_X_LeaveNotify;
103         break;
104     case KeyPress:
105         e = Event_X_KeyPress;
106         break;
107     case KeyRelease:
108         e = Event_X_KeyRelease;
109         break;
110     case ButtonPress:
111         e = Event_X_ButtonPress;
112         break;
113     case ButtonRelease:
114         e = Event_X_ButtonRelease;
115         break;
116     case MotionNotify:
117         e = Event_X_MotionNotify;
118         break;
119     default:
120         /* XKB events */
121         if (xe->type == extensions_xkb_event_basep) {
122             switch (((XkbAnyEvent*)&e)->xkb_type) {
123             case XkbBellNotify:
124                 e = Event_X_Bell;
125                 break;
126             }
127         }
128         return;
129     }
130
131     obe.type = e;
132     obe.data.x.e = xe;
133     obe.data.x.client = c;
134
135     i = 0;
136     while (e > 1) {
137         e >>= 1;
138         ++i;
139     }
140
141     for (it = funcs[i]; it != NULL; it = it->next) {
142         Func *f = it->data;
143         f->h(&obe, f->data);
144     }
145 }
146
147 void dispatch_client(EventType e, Client *c, int num0, int num1)
148 {
149     guint i;
150     GSList *it;
151     ObEvent obe;
152
153     g_assert(c != NULL);
154
155     obe.type = e;
156     obe.data.c.client = c;
157     obe.data.c.num[0] = num0;
158     obe.data.c.num[1] = num1;
159
160     i = 0;
161     while (e > 1) {
162         e >>= 1;
163         ++i;
164     }
165
166     for (it = funcs[i]; it != NULL; it = it->next) {
167         Func *f = it->data;
168         f->h(&obe, f->data);
169     }
170 }
171
172 void dispatch_ob(EventType e, int num0, int num1)
173 {
174     guint i;
175     GSList *it;
176     ObEvent obe;
177
178     obe.type = e;
179     obe.data.o.num[0] = num0;
180     obe.data.o.num[1] = num1;
181
182     i = 0;
183     while (e > 1) {
184         e >>= 1;
185         ++i;
186     }
187
188     for (it = funcs[i]; it != NULL; it = it->next) {
189         Func *f = it->data;
190         f->h(&obe, f->data);
191     }
192 }
193
194 void dispatch_signal(int signal)
195 {
196     guint i;
197     EventType e = Event_Signal;
198     GSList *it;
199     ObEvent obe;
200
201     obe.type = e;
202     obe.data.s.signal = signal;
203
204     i = 0;
205     while (e > 1) {
206         e >>= 1;
207         ++i;
208     }
209
210     for (it = funcs[i]; it != NULL; it = it->next) {
211         Func *f = it->data;
212         f->h(&obe, f->data);
213     }
214 }
215
216 void dispatch_move(Client *c, int *x, int *y)
217 {
218     guint i;
219     EventType e = Event_Client_Moving;
220     GSList *it;
221     ObEvent obe;
222
223     obe.type = e;
224     obe.data.c.client = c;
225     obe.data.c.num[0] = *x;
226     obe.data.c.num[1] = *y;
227
228     i = 0;
229     while (e > 1) {
230         e >>= 1;
231         ++i;
232     }
233
234     for (it = funcs[i]; it != NULL; it = it->next) {
235         Func *f = it->data;
236         f->h(&obe, f->data);
237     }
238
239     *x = obe.data.c.num[0];
240     *y = obe.data.c.num[1];
241 }