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