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