XIPassiveGrab.c revision f2d49d05
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
180
181static int
182_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
183                       Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
184{
185    xXIPassiveUngrabDeviceReq *req;
186    int i;
187
188    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
189
190    LockDisplay(dpy);
191    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
192	return -1;
193
194    GetReq(XIPassiveUngrabDevice, req);
195    req->reqType = extinfo->codes->major_opcode;
196    req->ReqType = X_XIPassiveUngrabDevice;
197    req->deviceid = deviceid;
198    req->grab_window = grab_window;
199    req->detail = detail;
200    req->num_modifiers = num_modifiers;
201    req->grab_type = grabtype;
202
203    SetReqLen(req, num_modifiers, num_modifiers);
204    for (i = 0; i < num_modifiers; i++)
205        Data32(dpy, &modifiers[i].modifiers, 4);
206
207    UnlockDisplay(dpy);
208    SyncHandle();
209    return Success;
210}
211
212int
213XIUngrabButton(Display* display, int deviceid, int button,Window grab_window,
214               int num_modifiers, XIGrabModifiers *modifiers)
215{
216    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button,
217                                  grab_window, num_modifiers, modifiers);
218}
219
220int
221XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window,
222               int num_modifiers, XIGrabModifiers *modifiers)
223{
224    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode,
225                                  grab_window, num_modifiers, modifiers);
226}
227
228
229int
230XIUngrabEnter(Display* display, int deviceid, Window grab_window,
231               int num_modifiers, XIGrabModifiers *modifiers)
232{
233    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0,
234                                  grab_window, num_modifiers, modifiers);
235}
236
237int
238XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
239               int num_modifiers, XIGrabModifiers *modifiers)
240{
241    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
242                                  grab_window, num_modifiers, modifiers);
243}
244
245int
246XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
247                   int num_modifiers, XIGrabModifiers *modifiers)
248{
249    XExtDisplayInfo *extinfo = XInput_find_display(display);
250
251    LockDisplay(display);
252    if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
253	return -1;
254    UnlockDisplay(display);
255
256    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
257                                  grab_window, num_modifiers, modifiers);
258}
259