1 /*
2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2004-2015 Kim Woelders
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24 #include "config.h"
25
26 #include <X11/Xlib.h>
27 #if USE_XI2
28 #include <X11/extensions/XInput2.h>
29 #define DEV_PTR Mode.events.xi2_ptr
30 #define DEV_KBD Mode.events.xi2_kbd
31 #endif
32
33 #include "E.h"
34 #include "cursors.h"
35 #include "grabs.h"
36 #include "xwin.h"
37
38 static int
_GrabKeyboard(Win win,int sync_kbd)39 _GrabKeyboard(Win win, int sync_kbd)
40 {
41 int rc;
42
43 #if USE_XI2
44 EXIEventMask em;
45
46 EXIMaskSetup(&em, DEV_KBD, KeyPressMask | KeyReleaseMask);
47 rc = XIGrabDevice(disp, DEV_KBD, WinGetXwin(win), CurrentTime, NoXID,
48 GrabModeAsync, sync_kbd ? GrabModeSync : GrabModeAsync,
49 False, &em.em);
50 #else
51 rc = XGrabKeyboard(disp, WinGetXwin(win), False,
52 GrabModeAsync, sync_kbd ? GrabModeSync : GrabModeAsync,
53 CurrentTime);
54 #endif
55
56 #if 0
57 Eprintf("%s: %#lx sync=%d rc=%d\n", __func__, WinGetXwin(win), sync_kbd, rc);
58 #endif
59
60 return rc;
61 }
62
63 int
GrabKeyboardSet(Win win)64 GrabKeyboardSet(Win win)
65 {
66 return _GrabKeyboard(win, 0);
67 }
68
69 int
GrabKeyboardFreeze(Win win)70 GrabKeyboardFreeze(Win win)
71 {
72 return _GrabKeyboard(win, 1);
73 }
74
75 int
GrabKeyboardRelease(void)76 GrabKeyboardRelease(void)
77 {
78 int rc;
79
80 #if USE_XI2
81 rc = XIUngrabDevice(disp, DEV_KBD, CurrentTime);
82 #else
83 rc = XUngrabKeyboard(disp, CurrentTime);
84 #endif
85
86 #if 0
87 Eprintf("%s: %d\n", __func__, rc);
88 #endif
89 return rc;
90 }
91
92 int
GrabPointerSet(Win win,unsigned int csr,int confine __UNUSED__)93 GrabPointerSet(Win win, unsigned int csr, int confine __UNUSED__)
94 {
95 int rc;
96
97 #if USE_XI2
98 EXIEventMask em;
99
100 EXIMaskSetup(&em, DEV_PTR,
101 ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
102 rc = XIGrabDevice(disp, DEV_PTR, WinGetXwin(win), CurrentTime, ECsrGet(csr),
103 GrabModeAsync, GrabModeAsync, False, &em.em);
104 #else
105 EX_Window confine_to = (confine) ? WinGetXwin(VROOT) : NoXID;
106
107 rc = XGrabPointer(disp, WinGetXwin(win), False,
108 ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
109 ButtonMotionMask | EnterWindowMask | LeaveWindowMask,
110 GrabModeAsync, GrabModeAsync, confine_to, ECsrGet(csr),
111 CurrentTime);
112 #endif
113
114 Mode.grabs.pointer_grab_window = WinGetXwin(win);
115 Mode.grabs.pointer_grab_active = 1;
116
117 if (EDebug(EDBUG_TYPE_GRABS))
118 Eprintf("%s: %#x, rc=%d\n", __func__, Mode.grabs.pointer_grab_window, rc);
119
120 return rc;
121 }
122
123 void
GrabPointerRelease(void)124 GrabPointerRelease(void)
125 {
126 #if USE_XI2
127 XIUngrabDevice(disp, DEV_PTR, CurrentTime);
128 #else
129 XUngrabPointer(disp, CurrentTime);
130 #endif
131
132 if (EDebug(EDBUG_TYPE_GRABS))
133 Eprintf("%s: %#x\n", __func__, Mode.grabs.pointer_grab_window);
134
135 Mode.grabs.pointer_grab_active = 0;
136 Mode.grabs.pointer_grab_window = NoXID;
137 }
138
139 void
GrabPointerThaw(void)140 GrabPointerThaw(void)
141 {
142 #if USE_XI2
143 XIAllowEvents(disp, DEV_PTR, XIReplayDevice, CurrentTime);
144 #else
145 XAllowEvents(disp, ReplayPointer, CurrentTime);
146 #endif
147 }
148
149 void
GrabButtonSet(unsigned int button,unsigned int modifiers,Win win,unsigned int event_mask,unsigned int csr,int confine __UNUSED__)150 GrabButtonSet(unsigned int button, unsigned int modifiers, Win win,
151 unsigned int event_mask, unsigned int csr, int confine __UNUSED__)
152 {
153 Bool owner_events = False;
154 int pointer_mode = GrabModeSync;
155 int keyboard_mode = GrabModeAsync;
156 int i;
157
158 #if USE_XI2
159 EXIEventMask em;
160 XIGrabModifiers modifiers_inouts[8];
161 int num_modifiers;
162
163 EXIMaskSetup(&em, DEV_PTR, event_mask);
164
165 if (modifiers == AnyModifier)
166 {
167 num_modifiers = 1;
168 modifiers_inouts[0].modifiers = XIAnyModifier;
169 modifiers_inouts[0].status = 0;
170 }
171 else
172 {
173 num_modifiers = 0;
174 for (i = 0; i < 8; i++)
175 {
176 if (i && !Mode.masks.mod_combos[i])
177 continue;
178 modifiers_inouts[num_modifiers].modifiers =
179 modifiers | Mode.masks.mod_combos[i];
180 modifiers_inouts[num_modifiers].status = 0;
181 num_modifiers++;
182 }
183 }
184 XIGrabButton(disp, DEV_PTR, button, WinGetXwin(win), ECsrGet(csr),
185 pointer_mode, keyboard_mode, owner_events,
186 &em.em, num_modifiers, modifiers_inouts);
187 #else
188 EX_Window confine_to = (confine) ? WinGetXwin(win) : NoXID;
189
190 if (modifiers == AnyModifier)
191 {
192 XGrabButton(disp, button, modifiers,
193 WinGetXwin(win), owner_events, event_mask, pointer_mode,
194 keyboard_mode, confine_to, ECsrGet(csr));
195 return;
196 }
197
198 for (i = 0; i < 8; i++)
199 {
200 if (i && !Mode.masks.mod_combos[i])
201 continue;
202 XGrabButton(disp, button, modifiers | Mode.masks.mod_combos[i],
203 WinGetXwin(win), owner_events, event_mask, pointer_mode,
204 keyboard_mode, confine_to, ECsrGet(csr));
205 }
206 #endif
207 }
208
209 void
GrabButtonRelease(unsigned int button,unsigned int modifiers,Win win)210 GrabButtonRelease(unsigned int button, unsigned int modifiers, Win win)
211 {
212 int i;
213
214 #if USE_XI2
215 XIGrabModifiers modifiers_inouts[8];
216 int num_modifiers;
217
218 if (modifiers == AnyModifier)
219 {
220 num_modifiers = 1;
221 modifiers_inouts[0].modifiers = XIAnyModifier;
222 modifiers_inouts[0].status = 0;
223 }
224 else
225 {
226 num_modifiers = 0;
227 for (i = 0; i < 8; i++)
228 {
229 if (i && !Mode.masks.mod_combos[i])
230 continue;
231 modifiers_inouts[num_modifiers].modifiers =
232 modifiers | Mode.masks.mod_combos[i];
233 modifiers_inouts[num_modifiers].status = 0;
234 num_modifiers++;
235 }
236 }
237 XIUngrabButton(disp, DEV_PTR, button, WinGetXwin(win),
238 num_modifiers, modifiers_inouts);
239 #else
240 if (modifiers == AnyModifier)
241 {
242 XUngrabButton(disp, button, modifiers, WinGetXwin(win));
243 return;
244 }
245
246 for (i = 0; i < 8; i++)
247 {
248 if (i && !Mode.masks.mod_combos[i])
249 continue;
250 XUngrabButton(disp, button, modifiers | Mode.masks.mod_combos[i],
251 WinGetXwin(win));
252 }
253 #endif
254 }
255
256 void
GrabKeySet(unsigned int keycode,unsigned int modifiers,Win win)257 GrabKeySet(unsigned int keycode, unsigned int modifiers, Win win)
258 {
259 Bool owner_events = False;
260 int pointer_mode = GrabModeAsync;
261 int keyboard_mode = GrabModeSync;
262 int i;
263
264 #if USE_XI2
265 EXIEventMask em;
266 XIGrabModifiers modifiers_inouts[8];
267 int num_modifiers;
268
269 EXIMaskSetup(&em, DEV_KBD, KeyPressMask | KeyReleaseMask);
270
271 if (modifiers == AnyModifier)
272 {
273 num_modifiers = 1;
274 modifiers_inouts[0].modifiers = XIAnyModifier;
275 modifiers_inouts[0].status = 0;
276 }
277 else
278 {
279 num_modifiers = 0;
280 for (i = 0; i < 8; i++)
281 {
282 if (i && !Mode.masks.mod_combos[i])
283 continue;
284 modifiers_inouts[num_modifiers].modifiers =
285 modifiers | Mode.masks.mod_combos[i];
286 modifiers_inouts[num_modifiers].status = 0;
287 num_modifiers++;
288 }
289 }
290 XIGrabKeycode(disp, DEV_KBD, keycode, WinGetXwin(win),
291 keyboard_mode, pointer_mode, owner_events,
292 &em.em, num_modifiers, modifiers_inouts);
293 #else
294
295 if (modifiers == AnyModifier)
296 {
297 XGrabKey(disp, keycode, modifiers, WinGetXwin(win), owner_events,
298 pointer_mode, keyboard_mode);
299 return;
300 }
301
302 for (i = 0; i < 8; i++)
303 {
304 if (i && !Mode.masks.mod_combos[i])
305 continue;
306 XGrabKey(disp, keycode, modifiers | Mode.masks.mod_combos[i],
307 WinGetXwin(win), owner_events, pointer_mode, keyboard_mode);
308 }
309 #endif
310 }
311
312 void
GrabKeyRelease(unsigned int keycode,unsigned int modifiers,Win win)313 GrabKeyRelease(unsigned int keycode, unsigned int modifiers, Win win)
314 {
315 int i;
316
317 #if USE_XI2
318 XIGrabModifiers modifiers_inouts[8];
319 int num_modifiers;
320
321 if (modifiers == AnyModifier)
322 {
323 num_modifiers = 1;
324 modifiers_inouts[0].modifiers = XIAnyModifier;
325 modifiers_inouts[0].status = 0;
326 }
327 else
328 {
329 num_modifiers = 0;
330 for (i = 0; i < 8; i++)
331 {
332 if (i && !Mode.masks.mod_combos[i])
333 continue;
334 modifiers_inouts[num_modifiers].modifiers =
335 modifiers | Mode.masks.mod_combos[i];
336 modifiers_inouts[num_modifiers].status = 0;
337 num_modifiers++;
338 }
339 }
340 XIUngrabKeycode(disp, DEV_KBD, keycode, WinGetXwin(win),
341 num_modifiers, modifiers_inouts);
342 #else
343
344 if (modifiers == AnyModifier)
345 {
346 XUngrabKey(disp, keycode, modifiers, WinGetXwin(win));
347 return;
348 }
349
350 for (i = 0; i < 8; i++)
351 {
352 if (i && !Mode.masks.mod_combos[i])
353 continue;
354 XUngrabKey(disp, keycode, modifiers | Mode.masks.mod_combos[i],
355 WinGetXwin(win));
356 }
357 #endif
358 }
359