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