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