]> Dogcows Code - chaz/openbox/blob - c/mbind.c
merge the C branch into HEAD
[chaz/openbox] / c / mbind.c
1 #include "mbind.h"
2 #include "kbind.h"
3 #include "frame.h"
4 #include "openbox.h"
5 #include "eventdata.h"
6 #include "hooks.h"
7
8 #include <glib.h>
9 #ifdef HAVE_STDLIB_H
10 # include <stdlib.h>
11 #endif
12
13 /* GData of GSList*'s of PointerBinding*'s. */
14 static GData *bound_contexts;
15
16 static gboolean grabbed;
17
18 struct mbind_foreach_grab_temp {
19 Client *client;
20 gboolean grab;
21 };
22
23 typedef struct {
24 guint state;
25 guint button;
26 char *name;
27 } PointerBinding;
28
29 static gboolean translate(char *str, guint *state, guint *button)
30 {
31 char **parsed;
32 char *l;
33 int i;
34 gboolean ret = FALSE;
35
36 parsed = g_strsplit(str, "-", -1);
37
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;
44
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;
51 }
52
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;
58 }
59
60 ret = TRUE;
61
62 translation_fail:
63 g_strfreev(parsed);
64 return ret;
65 }
66
67 void grab_button(Client *client, guint state, guint button, GQuark context,
68 gboolean grab)
69 {
70 Window win;
71 int mode = GrabModeAsync;
72 unsigned int mask;
73
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;
84
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);
90 }
91
92 static void mbind_foreach_grab(GQuark key, gpointer data, gpointer user_data)
93 {
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);
98 }
99
100 void mbind_grab_all(Client *client, gboolean grab)
101 {
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);
106 }
107
108 void grab_all_clients(gboolean grab)
109 {
110 GSList *it;
111
112 for (it = client_list; it != NULL; it = it->next)
113 mbind_grab_all(it->data, grab);
114 }
115
116 void mbind_startup()
117 {
118 grabbed = FALSE;
119 g_datalist_init(&bound_contexts);
120 }
121
122 void mbind_shutdown()
123 {
124 if (grabbed)
125 mbind_grab_pointer(FALSE);
126 mbind_clearall();
127 g_datalist_clear(&bound_contexts);
128 }
129
130 gboolean mbind_add(char *name, GQuark context)
131 {
132 guint state, button;
133 PointerBinding *b;
134 GSList *it;
135
136 if (!translate(name, &state, &button))
137 return FALSE;
138
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 */
144 }
145
146 grab_all_clients(FALSE);
147
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);
156
157 return TRUE;
158 }
159
160 static void mbind_foreach_clear(GQuark key, gpointer data, gpointer user_data)
161 {
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);
168 }
169 g_slist_free(data);
170 }
171 void mbind_clearall()
172 {
173 grab_all_clients(FALSE);
174 g_datalist_foreach(&bound_contexts, mbind_foreach_clear, NULL);
175 }
176
177 void mbind_fire(guint state, guint button, GQuark context, EventType type,
178 Client *client, int xroot, int yroot)
179 {
180 GSList *it;
181
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;
190 }
191
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;
203 }
204 }
205 }
206
207 gboolean mbind_grab_pointer(gboolean grab)
208 {
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;
220 }
This page took 0.044189 seconds and 4 git commands to generate.