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