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