Imported Upstream version 1.15.1
[deb_xorg-server.git] / Xi / xipassivegrab.c
CommitLineData
a09e091a
JB
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 * Author: Peter Hutterer
24 */
25
26/***********************************************************************
27 *
28 * Request to grab or ungrab input device.
29 *
30 */
31
32#ifdef HAVE_DIX_CONFIG_H
33#include <dix-config.h>
34#endif
35
36#include "inputstr.h" /* DeviceIntPtr */
37#include "windowstr.h" /* window structure */
38#include <X11/extensions/XI2.h>
39#include <X11/extensions/XI2proto.h>
40#include "swaprep.h"
41
42#include "exglobals.h" /* BadDevice */
43#include "exevents.h"
44#include "xipassivegrab.h"
45#include "dixgrabs.h"
46#include "misc.h"
47#include "inpututils.h"
48
49int
50SProcXIPassiveGrabDevice(ClientPtr client)
51{
52 int i;
53 uint32_t *mods;
54
55 REQUEST(xXIPassiveGrabDeviceReq);
56
57 swaps(&stuff->length);
58 swaps(&stuff->deviceid);
59 swapl(&stuff->grab_window);
60 swapl(&stuff->cursor);
61 swapl(&stuff->time);
62 swapl(&stuff->detail);
63 swaps(&stuff->mask_len);
64 swaps(&stuff->num_modifiers);
65
66 mods = (uint32_t *) &stuff[1] + stuff->mask_len;
67
68 for (i = 0; i < stuff->num_modifiers; i++, mods++) {
69 swapl(mods);
70 }
71
72 return ProcXIPassiveGrabDevice(client);
73}
74
75int
76ProcXIPassiveGrabDevice(ClientPtr client)
77{
78 DeviceIntPtr dev, mod_dev;
79 xXIPassiveGrabDeviceReply rep = {
80 .repType = X_Reply,
81 .RepType = X_XIPassiveGrabDevice,
82 .sequenceNumber = client->sequence,
83 .length = 0,
84 .num_modifiers = 0
85 };
86 int i, ret = Success;
87 uint32_t *modifiers;
88 xXIGrabModifierInfo *modifiers_failed;
89 GrabMask mask = { 0 };
90 GrabParameters param;
91 void *tmp;
92 int mask_len;
93
94 REQUEST(xXIPassiveGrabDeviceReq);
95 REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq);
96
97 if (stuff->deviceid == XIAllDevices)
98 dev = inputInfo.all_devices;
99 else if (stuff->deviceid == XIAllMasterDevices)
100 dev = inputInfo.all_master_devices;
101 else {
102 ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
103 if (ret != Success) {
104 client->errorValue = stuff->deviceid;
105 return ret;
106 }
107 }
108
109 if (stuff->grab_type != XIGrabtypeButton &&
110 stuff->grab_type != XIGrabtypeKeycode &&
111 stuff->grab_type != XIGrabtypeEnter &&
112 stuff->grab_type != XIGrabtypeFocusIn &&
113 stuff->grab_type != XIGrabtypeTouchBegin) {
114 client->errorValue = stuff->grab_type;
115 return BadValue;
116 }
117
118 if ((stuff->grab_type == XIGrabtypeEnter ||
119 stuff->grab_type == XIGrabtypeFocusIn ||
120 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
121 client->errorValue = stuff->detail;
122 return BadValue;
123 }
124
125 if (stuff->grab_type == XIGrabtypeTouchBegin &&
126 (stuff->grab_mode != XIGrabModeTouch ||
127 stuff->paired_device_mode != GrabModeAsync)) {
128 client->errorValue = stuff->grab_mode;
129 return BadValue;
130 }
131
132 if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1],
133 stuff->mask_len * 4) != Success)
134 return BadValue;
135
136 mask.xi2mask = xi2mask_new();
137 if (!mask.xi2mask)
138 return BadAlloc;
139
140 mask_len = min(xi2mask_mask_size(mask.xi2mask), stuff->mask_len * 4);
141 xi2mask_set_one_mask(mask.xi2mask, stuff->deviceid,
142 (unsigned char *) &stuff[1], mask_len * 4);
143
144 memset(&param, 0, sizeof(param));
145 param.grabtype = XI2;
146 param.ownerEvents = stuff->owner_events;
147 param.grabWindow = stuff->grab_window;
148 param.cursor = stuff->cursor;
149
150 if (IsKeyboardDevice(dev)) {
151 param.this_device_mode = stuff->grab_mode;
152 param.other_devices_mode = stuff->paired_device_mode;
153 }
154 else {
155 param.this_device_mode = stuff->paired_device_mode;
156 param.other_devices_mode = stuff->grab_mode;
157 }
158
159 if (stuff->cursor != None) {
160 ret = dixLookupResourceByType(&tmp, stuff->cursor,
161 RT_CURSOR, client, DixUseAccess);
162 if (ret != Success) {
163 client->errorValue = stuff->cursor;
164 goto out;
165 }
166 }
167
168 ret =
169 dixLookupWindow((WindowPtr *) &tmp, stuff->grab_window, client,
170 DixSetAttrAccess);
171 if (ret != Success)
172 goto out;
173
174 ret = CheckGrabValues(client, &param);
175 if (ret != Success)
176 goto out;
177
178 modifiers = (uint32_t *) &stuff[1] + stuff->mask_len;
179 modifiers_failed =
180 calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
181 if (!modifiers_failed) {
182 ret = BadAlloc;
183 goto out;
184 }
185
186 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
187
188 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) {
189 uint8_t status = Success;
190
191 param.modifiers = *modifiers;
192 ret = CheckGrabValues(client, &param);
193 if (ret != Success)
194 goto out;
195
196 switch (stuff->grab_type) {
197 case XIGrabtypeButton:
198 status = GrabButton(client, dev, mod_dev, stuff->detail,
199 &param, XI2, &mask);
200 break;
201 case XIGrabtypeKeycode:
202 status = GrabKey(client, dev, mod_dev, stuff->detail,
203 &param, XI2, &mask);
204 break;
205 case XIGrabtypeEnter:
206 case XIGrabtypeFocusIn:
207 status = GrabWindow(client, dev, stuff->grab_type, &param, &mask);
208 break;
209 case XIGrabtypeTouchBegin:
210 status = GrabTouch(client, dev, mod_dev, &param, &mask);
211 break;
212 }
213
214 if (status != GrabSuccess) {
215 xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
216
217 info->status = status;
218 info->modifiers = *modifiers;
219 if (client->swapped)
220 swapl(&info->modifiers);
221
222 rep.num_modifiers++;
223 rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
224 }
225 }
226
227 WriteReplyToClient(client, sizeof(rep), &rep);
228 if (rep.num_modifiers)
229 WriteToClient(client, rep.length * 4, modifiers_failed);
230
231 free(modifiers_failed);
232 out:
233 xi2mask_free(&mask.xi2mask);
234 return ret;
235}
236
237void
238SRepXIPassiveGrabDevice(ClientPtr client, int size,
239 xXIPassiveGrabDeviceReply * rep)
240{
241 swaps(&rep->sequenceNumber);
242 swapl(&rep->length);
243 swaps(&rep->num_modifiers);
244
245 WriteToClient(client, size, rep);
246}
247
248int
249SProcXIPassiveUngrabDevice(ClientPtr client)
250{
251 int i;
252 uint32_t *modifiers;
253
254 REQUEST(xXIPassiveUngrabDeviceReq);
255
256 swaps(&stuff->length);
257 swapl(&stuff->grab_window);
258 swaps(&stuff->deviceid);
259 swapl(&stuff->detail);
260 swaps(&stuff->num_modifiers);
261
262 modifiers = (uint32_t *) &stuff[1];
263
264 for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
265 swapl(modifiers);
266
267 return ProcXIPassiveUngrabDevice(client);
268}
269
270int
271ProcXIPassiveUngrabDevice(ClientPtr client)
272{
273 DeviceIntPtr dev, mod_dev;
274 WindowPtr win;
275 GrabPtr tempGrab;
276 uint32_t *modifiers;
277 int i, rc;
278
279 REQUEST(xXIPassiveUngrabDeviceReq);
280 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
281
282 if (stuff->deviceid == XIAllDevices)
283 dev = inputInfo.all_devices;
284 else if (stuff->deviceid == XIAllMasterDevices)
285 dev = inputInfo.all_master_devices;
286 else {
287 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
288 if (rc != Success)
289 return rc;
290 }
291
292 if (stuff->grab_type != XIGrabtypeButton &&
293 stuff->grab_type != XIGrabtypeKeycode &&
294 stuff->grab_type != XIGrabtypeEnter &&
295 stuff->grab_type != XIGrabtypeFocusIn &&
296 stuff->grab_type != XIGrabtypeTouchBegin) {
297 client->errorValue = stuff->grab_type;
298 return BadValue;
299 }
300
301 if ((stuff->grab_type == XIGrabtypeEnter ||
302 stuff->grab_type == XIGrabtypeFocusIn ||
303 stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
304 client->errorValue = stuff->detail;
305 return BadValue;
306 }
307
308 rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
309 if (rc != Success)
310 return rc;
311
312 mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
313
314 tempGrab = AllocGrab(NULL);
315 if (!tempGrab)
316 return BadAlloc;
317
318 tempGrab->resource = client->clientAsMask;
319 tempGrab->device = dev;
320 tempGrab->window = win;
321 switch (stuff->grab_type) {
322 case XIGrabtypeButton:
323 tempGrab->type = XI_ButtonPress;
324 break;
325 case XIGrabtypeKeycode:
326 tempGrab->type = XI_KeyPress;
327 break;
328 case XIGrabtypeEnter:
329 tempGrab->type = XI_Enter;
330 break;
331 case XIGrabtypeFocusIn:
332 tempGrab->type = XI_FocusIn;
333 break;
334 case XIGrabtypeTouchBegin:
335 tempGrab->type = XI_TouchBegin;
336 break;
337 }
338 tempGrab->grabtype = XI2;
339 tempGrab->modifierDevice = mod_dev;
340 tempGrab->modifiersDetail.pMask = NULL;
341 tempGrab->detail.exact = stuff->detail;
342 tempGrab->detail.pMask = NULL;
343
344 modifiers = (uint32_t *) &stuff[1];
345
346 for (i = 0; i < stuff->num_modifiers; i++, modifiers++) {
347 tempGrab->modifiersDetail.exact = *modifiers;
348 DeletePassiveGrabFromList(tempGrab);
349 }
350
351 FreeGrab(tempGrab);
352
353 return Success;
354}