XIPassiveGrab.c revision 10baa824
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{
43    xXIPassiveGrabDeviceReq *req;
44    xXIPassiveGrabDeviceReply reply;
45    xXIGrabModifierInfo *failed_mods;
46    int len = 0, i;
47    char *buff;
48
49    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
50
51    LockDisplay(dpy);
52    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
53	return -1;
54
55    if (mask->mask_len > INT_MAX - 3 ||
56        (mask->mask_len + 3)/4 >= 0xffff)
57        return -1;
58
59    buff = calloc(4, (mask->mask_len + 3)/4);
60    if (!buff)
61        return -1;
62
63    GetReq(XIPassiveGrabDevice, req);
64    req->reqType = extinfo->codes->major_opcode;
65    req->ReqType = X_XIPassiveGrabDevice;
66    req->deviceid = deviceid;
67    req->grab_mode = grab_mode;
68    req->paired_device_mode = paired_device_mode;
69    req->owner_events = owner_events;
70    req->grab_window = grab_window;
71    req->cursor = cursor;
72    req->detail = detail;
73    req->num_modifiers = num_modifiers;
74    req->mask_len = (mask->mask_len + 3)/4;
75    req->grab_type = grabtype;
76
77    len = req->mask_len + num_modifiers;
78    SetReqLen(req, len, len);
79
80    memcpy(buff, mask->mask, mask->mask_len);
81    Data(dpy, buff, req->mask_len * 4);
82    for (i = 0; i < num_modifiers; i++)
83        Data(dpy, (char*)&modifiers_inout[i].modifiers, 4);
84
85    free(buff);
86
87    if (!_XReply(dpy, (xReply *)&reply, 0, xFalse))
88    {
89	UnlockDisplay(dpy);
90	SyncHandle();
91	return -1;
92    }
93
94    failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo));
95    if (!failed_mods)
96        return -1;
97    _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));
98
99    for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++)
100    {
101        modifiers_inout[i].status = failed_mods[i].status;
102        modifiers_inout[i].modifiers = failed_mods[i].modifiers;
103    }
104    free(failed_mods);
105
106    UnlockDisplay(dpy);
107    SyncHandle();
108    return reply.num_modifiers;
109}
110
111int
112XIGrabButton(Display* dpy, int deviceid, int button,
113             Window grab_window, Cursor cursor,
114             int grab_mode, int paired_device_mode,
115             Bool owner_events, XIEventMask *mask,
116             int num_modifiers, XIGrabModifiers *modifiers_inout)
117{
118    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeButton, button,
119                                grab_window, cursor, grab_mode,
120                                paired_device_mode, owner_events, mask,
121                                num_modifiers, modifiers_inout);
122}
123
124int
125XIGrabKeycode(Display* dpy, int deviceid, int keycode,
126             Window grab_window, int grab_mode, int paired_device_mode,
127             Bool owner_events, XIEventMask *mask,
128             int num_modifiers, XIGrabModifiers *modifiers_inout)
129{
130    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeKeycode, keycode,
131                                grab_window, None, grab_mode, paired_device_mode,
132                                owner_events, mask, num_modifiers,
133                                modifiers_inout);
134}
135
136int
137XIGrabEnter(Display *dpy, int deviceid, Window grab_window, Cursor cursor,
138            int grab_mode, int paired_device_mode, Bool owner_events,
139            XIEventMask *mask, int num_modifiers,
140            XIGrabModifiers *modifiers_inout)
141{
142    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeEnter, 0,
143                                grab_window, cursor, grab_mode, paired_device_mode,
144                                owner_events, mask, num_modifiers,
145                                modifiers_inout);
146}
147
148int
149XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode,
150            int paired_device_mode, Bool owner_events, XIEventMask *mask,
151            int num_modifiers, XIGrabModifiers *modifiers_inout)
152{
153    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeFocusIn, 0,
154                                grab_window, None, grab_mode, paired_device_mode,
155                                owner_events, mask, num_modifiers,
156                                modifiers_inout);
157}
158
159int
160XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
161                 Bool owner_events, XIEventMask *mask,
162                 int num_modifiers, XIGrabModifiers *modifiers_inout)
163{
164    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
165
166    LockDisplay(dpy);
167    if (_XiCheckExtInit(dpy, XInput_2_2, extinfo) == -1)
168	return -1;
169
170    /* FIXME: allow selection of GrabMode for paired devices? */
171    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
172                                grab_window, None, XIGrabModeTouch,
173                                GrabModeAsync, owner_events, mask,
174                                num_modifiers, modifiers_inout);
175}
176
177
178static int
179_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
180                       Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
181{
182    xXIPassiveUngrabDeviceReq *req;
183    int i;
184
185    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
186
187    LockDisplay(dpy);
188    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
189	return -1;
190
191    GetReq(XIPassiveUngrabDevice, req);
192    req->reqType = extinfo->codes->major_opcode;
193    req->ReqType = X_XIPassiveUngrabDevice;
194    req->deviceid = deviceid;
195    req->grab_window = grab_window;
196    req->detail = detail;
197    req->num_modifiers = num_modifiers;
198    req->grab_type = grabtype;
199
200    SetReqLen(req, num_modifiers, num_modifiers);
201    for (i = 0; i < num_modifiers; i++)
202        Data32(dpy, &modifiers[i].modifiers, 4);
203
204    UnlockDisplay(dpy);
205    SyncHandle();
206    return Success;
207}
208
209int
210XIUngrabButton(Display* display, int deviceid, int button,Window grab_window,
211               int num_modifiers, XIGrabModifiers *modifiers)
212{
213    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button,
214                                  grab_window, num_modifiers, modifiers);
215}
216
217int
218XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window,
219               int num_modifiers, XIGrabModifiers *modifiers)
220{
221    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode,
222                                  grab_window, num_modifiers, modifiers);
223}
224
225
226int
227XIUngrabEnter(Display* display, int deviceid, Window grab_window,
228               int num_modifiers, XIGrabModifiers *modifiers)
229{
230    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0,
231                                  grab_window, num_modifiers, modifiers);
232}
233
234int
235XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
236               int num_modifiers, XIGrabModifiers *modifiers)
237{
238    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
239                                  grab_window, num_modifiers, modifiers);
240}
241
242int
243XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
244                   int num_modifiers, XIGrabModifiers *modifiers)
245{
246    XExtDisplayInfo *extinfo = XInput_find_display(display);
247
248    LockDisplay(display);
249    if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
250	return -1;
251
252    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
253                                  grab_window, num_modifiers, modifiers);
254}
255