XIPassiveGrab.c revision adfa0b0c
1/*
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <stdint.h>
29#include <X11/Xlibint.h>
30#include <X11/extensions/XI2proto.h>
31#include <X11/extensions/XInput2.h>
32#include <X11/extensions/extutil.h>
33#include <limits.h>
34#include "XIint.h"
35
36static int
37_XIPassiveGrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
38                     Window grab_window, Cursor cursor,
39                     int grab_mode, int paired_device_mode,
40                     Bool owner_events, XIEventMask *mask,
41                     int num_modifiers, XIGrabModifiers *modifiers_inout,
42                     Time time)
43{
44    xXIPassiveGrabDeviceReq *req;
45    xXIPassiveGrabDeviceReply reply;
46    xXIGrabModifierInfo *failed_mods;
47    int len = 0, i;
48    int ret = -1;
49    char *buff;
50
51    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
52
53    LockDisplay(dpy);
54    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
55	return -1;
56
57    if (mask->mask_len > INT_MAX - 3 ||
58        (mask->mask_len + 3)/4 >= 0xffff)
59        goto out;
60
61    buff = calloc(4, (mask->mask_len + 3)/4);
62    if (!buff)
63        goto out;
64
65    GetReq(XIPassiveGrabDevice, req);
66    req->reqType = extinfo->codes->major_opcode;
67    req->ReqType = X_XIPassiveGrabDevice;
68    req->deviceid = deviceid;
69    req->grab_mode = grab_mode;
70    req->paired_device_mode = paired_device_mode;
71    req->owner_events = owner_events;
72    req->grab_window = grab_window;
73    req->cursor = cursor;
74    req->detail = detail;
75    req->num_modifiers = num_modifiers;
76    req->mask_len = (mask->mask_len + 3)/4;
77    req->grab_type = grabtype;
78    req->time = time;
79
80    len = req->mask_len + num_modifiers;
81    SetReqLen(req, len, len);
82
83    memcpy(buff, mask->mask, mask->mask_len);
84    Data(dpy, buff, req->mask_len * 4);
85    for (i = 0; i < num_modifiers; i++)
86        Data(dpy, (char*)&modifiers_inout[i].modifiers, 4);
87
88    free(buff);
89
90    if (!_XReply(dpy, (xReply *)&reply, 0, xFalse))
91        goto out;
92
93    failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo));
94    if (!failed_mods)
95        goto out;
96    _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));
97
98    for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++)
99    {
100        modifiers_inout[i].status = failed_mods[i].status;
101        modifiers_inout[i].modifiers = failed_mods[i].modifiers;
102    }
103    free(failed_mods);
104
105    ret = reply.num_modifiers;
106
107 out:
108    UnlockDisplay(dpy);
109    SyncHandle();
110    return ret;
111}
112
113int
114XIGrabButton(Display* dpy, int deviceid, int button,
115             Window grab_window, Cursor cursor,
116             int grab_mode, int paired_device_mode,
117             Bool owner_events, XIEventMask *mask,
118             int num_modifiers, XIGrabModifiers *modifiers_inout)
119{
120    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeButton, button,
121                                grab_window, cursor, grab_mode,
122                                paired_device_mode, owner_events, mask,
123                                num_modifiers, modifiers_inout, CurrentTime);
124}
125
126int
127XIGrabKeycode(Display* dpy, int deviceid, int keycode,
128             Window grab_window, int grab_mode, int paired_device_mode,
129             Bool owner_events, XIEventMask *mask,
130             int num_modifiers, XIGrabModifiers *modifiers_inout)
131{
132    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeKeycode, keycode,
133                                grab_window, None, grab_mode, paired_device_mode,
134                                owner_events, mask, num_modifiers,
135                                modifiers_inout, CurrentTime);
136}
137
138int
139XIGrabEnter(Display *dpy, int deviceid, Window grab_window, Cursor cursor,
140            int grab_mode, int paired_device_mode, Bool owner_events,
141            XIEventMask *mask, int num_modifiers,
142            XIGrabModifiers *modifiers_inout)
143{
144    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeEnter, 0,
145                                grab_window, cursor, grab_mode, paired_device_mode,
146                                owner_events, mask, num_modifiers,
147                                modifiers_inout, CurrentTime);
148}
149
150int
151XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode,
152            int paired_device_mode, Bool owner_events, XIEventMask *mask,
153            int num_modifiers, XIGrabModifiers *modifiers_inout)
154{
155    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeFocusIn, 0,
156                                grab_window, None, grab_mode, paired_device_mode,
157                                owner_events, mask, num_modifiers,
158                                modifiers_inout, CurrentTime);
159}
160
161int
162XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
163                 Bool owner_events, XIEventMask *mask,
164                 int num_modifiers, XIGrabModifiers *modifiers_inout)
165{
166    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
167
168    LockDisplay(dpy);
169    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
170	return -1;
171    UnlockDisplay(dpy);
172
173    /* FIXME: allow selection of GrabMode for paired devices? */
174    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
175                                grab_window, None, XIGrabModeTouch,
176                                GrabModeAsync, owner_events, mask,
177                                num_modifiers, modifiers_inout, CurrentTime);
178}
179
180int XIGrabPinchGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
181                            int paired_device_mode, int owner_events,
182                            XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
183{
184    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
185
186    LockDisplay(dpy);
187    if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
188        return -1;
189    UnlockDisplay(dpy);
190
191    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGesturePinchBegin, 0,
192                                grab_window, None, grab_mode, paired_device_mode,
193                                owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
194}
195
196int XIGrabSwipeGestureBegin(Display* dpy, int deviceid, Window grab_window, int grab_mode,
197                            int paired_device_mode, int owner_events,
198                            XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout)
199{
200    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
201
202    LockDisplay(dpy);
203    if (_XiCheckExtInit(dpy, XInput_2_4, extinfo) == -1)
204        return -1;
205    UnlockDisplay(dpy);
206
207    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeGestureSwipeBegin, 0,
208                                grab_window, None, grab_mode, paired_device_mode,
209                                owner_events, mask, num_modifiers, modifiers_inout, CurrentTime);
210}
211
212static int
213_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
214                       Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
215{
216    xXIPassiveUngrabDeviceReq *req;
217    int i;
218
219    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
220
221    LockDisplay(dpy);
222    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
223	return -1;
224
225    GetReq(XIPassiveUngrabDevice, req);
226    req->reqType = extinfo->codes->major_opcode;
227    req->ReqType = X_XIPassiveUngrabDevice;
228    req->deviceid = deviceid;
229    req->grab_window = grab_window;
230    req->detail = detail;
231    req->num_modifiers = num_modifiers;
232    req->grab_type = grabtype;
233
234    SetReqLen(req, num_modifiers, num_modifiers);
235    for (i = 0; i < num_modifiers; i++)
236        Data32(dpy, &modifiers[i].modifiers, 4);
237
238    UnlockDisplay(dpy);
239    SyncHandle();
240    return Success;
241}
242
243int
244XIUngrabButton(Display* display, int deviceid, int button,Window grab_window,
245               int num_modifiers, XIGrabModifiers *modifiers)
246{
247    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button,
248                                  grab_window, num_modifiers, modifiers);
249}
250
251int
252XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window,
253               int num_modifiers, XIGrabModifiers *modifiers)
254{
255    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode,
256                                  grab_window, num_modifiers, modifiers);
257}
258
259
260int
261XIUngrabEnter(Display* display, int deviceid, Window grab_window,
262               int num_modifiers, XIGrabModifiers *modifiers)
263{
264    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0,
265                                  grab_window, num_modifiers, modifiers);
266}
267
268int
269XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
270               int num_modifiers, XIGrabModifiers *modifiers)
271{
272    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
273                                  grab_window, num_modifiers, modifiers);
274}
275
276int
277XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
278                   int num_modifiers, XIGrabModifiers *modifiers)
279{
280    XExtDisplayInfo *extinfo = XInput_find_display(display);
281
282    LockDisplay(display);
283    if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
284	return -1;
285    UnlockDisplay(display);
286
287    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
288                                  grab_window, num_modifiers, modifiers);
289}
290
291int XIUngrabPinchGestureBegin(Display* display, int deviceid, Window grab_window,
292                              int num_modifiers, XIGrabModifiers *modifiers)
293{
294    XExtDisplayInfo *extinfo = XInput_find_display(display);
295
296    LockDisplay(display);
297    if (_XiCheckExtInit(display, XInput_2_4, extinfo) == -1)
298        return -1;
299    UnlockDisplay(display);
300
301    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGesturePinchBegin, 0,
302                                  grab_window, num_modifiers, modifiers);
303}
304
305int XIUngrabSwipeGestureBegin(Display* display, int deviceid, Window grab_window,
306                              int num_modifiers, XIGrabModifiers *modifiers)
307{
308    XExtDisplayInfo *extinfo = XInput_find_display(display);
309
310    LockDisplay(display);
311    if (_XiCheckExtInit(display, XInput_2_4, extinfo) == -1)
312        return -1;
313    UnlockDisplay(display);
314
315    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeGestureSwipeBegin, 0,
316                                  grab_window, num_modifiers, modifiers);
317}
318