add missing include, pass right args to font_draw
[openbox.git] / c / mbind.c
blobf363be688fb439239e13e66c1949beb73d73690e
1 #include "mbind.h"
2 #include "kbind.h"
3 #include "frame.h"
4 #include "openbox.h"
5 #include "eventdata.h"
6 #include "hooks.h"
8 #include <glib.h>
9 #ifdef HAVE_STDLIB_H
10 # include <stdlib.h>
11 #endif
13 /* GData of GSList*'s of PointerBinding*'s. */
14 static GData *bound_contexts;
16 static gboolean grabbed;
18 struct mbind_foreach_grab_temp {
19 Client *client;
20 gboolean grab;
23 typedef struct {
24 guint state;
25 guint button;
26 char *name;
27 } PointerBinding;
29 static gboolean translate(char *str, guint *state, guint *button)
31 char **parsed;
32 char *l;
33 int i;
34 gboolean ret = FALSE;
36 parsed = g_strsplit(str, "-", -1);
38 /* first, find the button (last token) */
39 l = NULL;
40 for (i = 0; parsed[i] != NULL; ++i)
41 l = parsed[i];
42 if (l == NULL)
43 goto translation_fail;
45 /* figure out the mod mask */
46 *state = 0;
47 for (i = 0; parsed[i] != l; ++i) {
48 guint m = kbind_translate_modifier(parsed[i]);
49 if (!m) goto translation_fail;
50 *state |= m;
53 /* figure out the button */
54 *button = atoi(l);
55 if (!*button) {
56 g_warning("Invalid button '%s' in pointer binding.", l);
57 goto translation_fail;
60 ret = TRUE;
62 translation_fail:
63 g_strfreev(parsed);
64 return ret;
67 void grab_button(Client *client, guint state, guint button, GQuark context,
68 gboolean grab)
70 Window win;
71 int mode = GrabModeAsync;
72 unsigned int mask;
74 if (context == g_quark_try_string("frame")) {
75 win = client->frame->window;
76 mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
77 } else if (context == g_quark_try_string("client")) {
78 win = client->frame->plate;
79 mode = GrabModeSync; /* this is handled in mbind_fire */
80 mask = ButtonPressMask; /* can't catch more than this with Sync mode
81 the release event is manufactured in
82 mbind_fire */
83 } else return;
85 if (grab)
86 XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
87 GrabModeAsync, None, None);
88 else
89 XUngrabButton(ob_display, button, state, win);
92 static void mbind_foreach_grab(GQuark key, gpointer data, gpointer user_data)
94 struct mbind_foreach_grab_temp *d = user_data;
95 PointerBinding *b = ((GSList *)data)->data;
96 if (b != NULL)
97 grab_button(d->client, b->state, b->button, key, d->grab);
100 void mbind_grab_all(Client *client, gboolean grab)
102 struct mbind_foreach_grab_temp bt;
103 bt.client = client;
104 bt.grab = grab;
105 g_datalist_foreach(&bound_contexts, mbind_foreach_grab, &bt);
108 void grab_all_clients(gboolean grab)
110 GSList *it;
112 for (it = client_list; it != NULL; it = it->next)
113 mbind_grab_all(it->data, grab);
116 void mbind_startup()
118 grabbed = FALSE;
119 g_datalist_init(&bound_contexts);
122 void mbind_shutdown()
124 if (grabbed)
125 mbind_grab_pointer(FALSE);
126 mbind_clearall();
127 g_datalist_clear(&bound_contexts);
130 gboolean mbind_add(char *name, GQuark context)
132 guint state, button;
133 PointerBinding *b;
134 GSList *it;
136 if (!translate(name, &state, &button))
137 return FALSE;
139 for (it = g_datalist_id_get_data(&bound_contexts, context);
140 it != NULL; it = it->next){
141 b = it->data;
142 if (b->state == state && b->button == button)
143 return TRUE; /* already bound */
146 grab_all_clients(FALSE);
148 /* add the binding */
149 b = g_new(PointerBinding, 1);
150 b->state = state;
151 b->button = button;
152 b->name = g_strdup(name);
153 g_datalist_id_set_data(&bound_contexts, context,
154 g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
155 grab_all_clients(TRUE);
157 return TRUE;
160 static void mbind_foreach_clear(GQuark key, gpointer data, gpointer user_data)
162 GSList *it;
163 user_data = user_data;
164 for (it = data; it != NULL; it = it->next) {
165 PointerBinding *b = it->data;
166 g_free(b->name);
167 g_free(b);
169 g_slist_free(data);
171 void mbind_clearall()
173 grab_all_clients(FALSE);
174 g_datalist_foreach(&bound_contexts, mbind_foreach_clear, NULL);
177 void mbind_fire(guint state, guint button, GQuark context, EventType type,
178 Client *client, int xroot, int yroot)
180 GSList *it;
182 if (grabbed) {
183 EventData *data;
184 data = eventdata_new_pointer(type, context, client, state, button,
185 NULL, xroot, yroot);
186 g_assert(data != NULL);
187 hooks_fire_pointer(data);
188 eventdata_free(data);
189 return;
192 for (it = g_datalist_id_get_data(&bound_contexts, context);
193 it != NULL; it = it->next){
194 PointerBinding *b = it->data;
195 if (b->state == state && b->button == button) {
196 EventData *data;
197 data = eventdata_new_pointer(type, context, client, state, button,
198 b->name, xroot, yroot);
199 g_assert(data != NULL);
200 hooks_fire(data);
201 eventdata_free(data);
202 break;
207 gboolean mbind_grab_pointer(gboolean grab)
209 gboolean ret = TRUE;
210 if (grab)
211 ret = XGrabPointer(ob_display, ob_root, FALSE, (ButtonPressMask |
212 ButtonReleaseMask |
213 ButtonMotionMask |
214 PointerMotionMask),
215 GrabModeAsync, GrabModeAsync, None, None,
216 CurrentTime) == GrabSuccess;
217 else
218 XUngrabPointer(ob_display, CurrentTime);
219 return ret;