13 /* GData of GSList*'s of PointerBinding*'s. */
14 static GData *bound_contexts;
16 static gboolean grabbed;
18 struct mbind_foreach_grab_temp {
29 static gboolean translate(char *str, guint *state, guint *button)
36 parsed = g_strsplit(str, "-", -1);
38 /* first, find the button (last token) */
40 for (i = 0; parsed[i] != NULL; ++i)
43 goto translation_fail;
45 /* figure out the mod mask */
47 for (i = 0; parsed[i] != l; ++i) {
48 guint m = kbind_translate_modifier(parsed[i]);
49 if (!m) goto translation_fail;
53 /* figure out the button */
56 g_warning("Invalid button '%s' in pointer binding.", l);
57 goto translation_fail;
67 void grab_button(Client *client, guint state, guint button, GQuark context,
71 int mode = GrabModeAsync;
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
86 XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
87 GrabModeAsync, None, None);
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;
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;
105 g_datalist_foreach(&bound_contexts, mbind_foreach_grab, &bt);
108 void grab_all_clients(gboolean grab)
112 for (it = client_list; it != NULL; it = it->next)
113 mbind_grab_all(it->data, grab);
119 g_datalist_init(&bound_contexts);
122 void mbind_shutdown()
125 mbind_grab_pointer(FALSE);
127 g_datalist_clear(&bound_contexts);
130 gboolean mbind_add(char *name, GQuark context)
136 if (!translate(name, &state, &button))
139 for (it = g_datalist_id_get_data(&bound_contexts, context);
140 it != NULL; it = it->next){
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);
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);
160 static void mbind_foreach_clear(GQuark key, gpointer data, gpointer user_data)
163 user_data = user_data;
164 for (it = data; it != NULL; it = it->next) {
165 PointerBinding *b = it->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)
184 data = eventdata_new_pointer(type, context, client, state, button,
186 g_assert(data != NULL);
187 hooks_fire_pointer(data);
188 eventdata_free(data);
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) {
197 data = eventdata_new_pointer(type, context, client, state, button,
198 b->name, xroot, yroot);
199 g_assert(data != NULL);
201 eventdata_free(data);
207 gboolean mbind_grab_pointer(gboolean grab)
211 ret = XGrabPointer(ob_display, ob_root, FALSE, (ButtonPressMask |
215 GrabModeAsync, GrabModeAsync, None, None,
216 CurrentTime) == GrabSuccess;
218 XUngrabPointer(ob_display, CurrentTime);