XIPassiveGrab.c revision 32ed59c1
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    int ret = -1;
48    char *buff;
49
50    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
51
52    LockDisplay(dpy);
53    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
54	return -1;
55
56    if (mask->mask_len > INT_MAX - 3 ||
57        (mask->mask_len + 3)/4 >= 0xffff)
58        goto out;
59
60    buff = calloc(4, (mask->mask_len + 3)/4);
61    if (!buff)
62        goto out;
63
64    GetReq(XIPassiveGrabDevice, req);
65    req->reqType = extinfo->codes->major_opcode;
66    req->ReqType = X_XIPassiveGrabDevice;
67    req->deviceid = deviceid;
68    req->grab_mode = grab_mode;
69    req->paired_device_mode = paired_device_mode;
70    req->owner_events = owner_events;
71    req->grab_window = grab_window;
72    req->cursor = cursor;
73    req->detail = detail;
74    req->num_modifiers = num_modifiers;
75    req->mask_len = (mask->mask_len + 3)/4;
76    req->grab_type = grabtype;
77
78    len = req->mask_len + num_modifiers;
79    SetReqLen(req, len, len);
80
81    memcpy(buff, mask->mask, mask->mask_len);
82    Data(dpy, buff, req->mask_len * 4);
83    for (i = 0; i < num_modifiers; i++)
84        Data(dpy, (char*)&modifiers_inout[i].modifiers, 4);
85
86    free(buff);
87
88    if (!_XReply(dpy, (xReply *)&reply, 0, xFalse))
89        goto out;
90
91    failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo));
92    if (!failed_mods)
93        goto out;
94    _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));
95
96    for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++)
97    {
98        modifiers_inout[i].status = failed_mods[i].status;
99        modifiers_inout[i].modifiers = failed_mods[i].modifiers;
100    }
101    free(failed_mods);
102
103    ret = reply.num_modifiers;
104
105 out:
106    UnlockDisplay(dpy);
107    SyncHandle();
108    return ret;
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    UnlockDisplay(dpy);
170
171    /* FIXME: allow selection of GrabMode for paired devices? */
172    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
173                                grab_window, None, XIGrabModeTouch,
174                                GrabModeAsync, owner_events, mask,
175                                num_modifiers, modifiers_inout);
176}
177
178
179static int
180_XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
181                       Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
182{
183    xXIPassiveUngrabDeviceReq *req;
184    int i;
185
186    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
187
188    LockDisplay(dpy);
189    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
190	return -1;
191
192    GetReq(XIPassiveUngrabDevice, req);
193    req->reqType = extinfo->codes->major_opcode;
194    req->ReqType = X_XIPassiveUngrabDevice;
195    req->deviceid = deviceid;
196    req->grab_window = grab_window;
197    req->detail = detail;
198    req->num_modifiers = num_modifiers;
199    req->grab_type = grabtype;
200
201    SetReqLen(req, num_modifiers, num_modifiers);
202    for (i = 0; i < num_modifiers; i++)
203        Data32(dpy, &modifiers[i].modifiers, 4);
204
205    UnlockDisplay(dpy);
206    SyncHandle();
207    return Success;
208}
209
210int
211XIUngrabButton(Display* display, int deviceid, int button,Window grab_window,
212               int num_modifiers, XIGrabModifiers *modifiers)
213{
214    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeButton, button,
215                                  grab_window, num_modifiers, modifiers);
216}
217
218int
219XIUngrabKeycode(Display* display, int deviceid, int keycode, Window grab_window,
220               int num_modifiers, XIGrabModifiers *modifiers)
221{
222    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeKeycode, keycode,
223                                  grab_window, num_modifiers, modifiers);
224}
225
226
227int
228XIUngrabEnter(Display* display, int deviceid, Window grab_window,
229               int num_modifiers, XIGrabModifiers *modifiers)
230{
231    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeEnter, 0,
232                                  grab_window, num_modifiers, modifiers);
233}
234
235int
236XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
237               int num_modifiers, XIGrabModifiers *modifiers)
238{
239    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
240                                  grab_window, num_modifiers, modifiers);
241}
242
243int
244XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
245                   int num_modifiers, XIGrabModifiers *modifiers)
246{
247    XExtDisplayInfo *extinfo = XInput_find_display(display);
248
249    LockDisplay(display);
250    if (_XiCheckExtInit(display, XInput_2_2, extinfo) == -1)
251	return -1;
252
253    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
254                                  grab_window, num_modifiers, modifiers);
255}
256