af46282c8e3ba786528ec0db6e9e218bbb5ed707
[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"
48 int
49 SProcXIPassiveGrabDevice(ClientPtr client)
50 {
51     int i;
52     char n;
53     xXIModifierInfo *mods;
55     REQUEST(xXIPassiveGrabDeviceReq);
57     swaps(&stuff->length, n);
58     swaps(&stuff->deviceid, n);
59     swapl(&stuff->grab_window, n);
60     swapl(&stuff->cursor, n);
61     swapl(&stuff->time, n);
62     swapl(&stuff->detail, n);
63     swaps(&stuff->mask_len, n);
64     swaps(&stuff->num_modifiers, n);
66     mods = (xXIModifierInfo*)&stuff[1];
68     for (i = 0; i < stuff->num_modifiers; i++, mods++)
69     {
70         swapl(&mods->base_mods, n);
71         swapl(&mods->latched_mods, n);
72         swapl(&mods->locked_mods, n);
73     }
75     return ProcXIPassiveGrabDevice(client);
76 }
78 int
79 ProcXIPassiveGrabDevice(ClientPtr client)
80 {
81     DeviceIntPtr dev, mod_dev;
82     xXIPassiveGrabDeviceReply rep;
83     int i, ret = Success;
84     uint8_t status;
85     uint32_t *modifiers;
86     xXIGrabModifierInfo *modifiers_failed;
87     GrabMask mask;
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     {
115         client->errorValue = stuff->grab_type;
116         return BadValue;
117     }
119     if ((stuff->grab_type == XIGrabtypeEnter ||
120          stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
121     {
122         client->errorValue = stuff->detail;
123         return BadValue;
124     }
126     if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
127                                stuff->mask_len * 4) != Success)
128         return BadValue;
130     mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
131     memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
132     memcpy(mask.xi2mask[stuff->deviceid], &stuff[1], mask_len * 4);
134     rep.repType = X_Reply;
135     rep.RepType = X_XIPassiveGrabDevice;
136     rep.length = 0;
137     rep.sequenceNumber = client->sequence;
138     rep.num_modifiers = 0;
140     memset(&param, 0, sizeof(param));
141     param.grabtype = GRABTYPE_XI2;
142     param.ownerEvents = stuff->owner_events;
143     param.grabWindow = stuff->grab_window;
144     param.cursor = stuff->cursor;
146     if (IsKeyboardDevice(dev)) {
147         param.this_device_mode = stuff->grab_mode;
148         param.other_devices_mode = stuff->paired_device_mode;
149     } else {
150         param.this_device_mode = stuff->paired_device_mode;
151         param.other_devices_mode = stuff->grab_mode;
152     }
154     if (stuff->cursor != None)
155     {
156         status = dixLookupResourceByType(&tmp, stuff->cursor,
157                                          RT_CURSOR, client, DixUseAccess);
158         if (status != Success)
159         {
160             client->errorValue = stuff->cursor;
161             return status;
162         }
163     }
165     status = dixLookupWindow((WindowPtr*)&tmp, stuff->grab_window, client, DixSetAttrAccess);
166     if (status != Success)
167         return status;
169     status = CheckGrabValues(client, &param);
170     if (status != Success)
171         return status;
173     modifiers = (uint32_t*)&stuff[1] + stuff->mask_len;
174     modifiers_failed = calloc(stuff->num_modifiers, sizeof(xXIGrabModifierInfo));
175     if (!modifiers_failed)
176         return BadAlloc;
178     mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
180     for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
181     {
182         param.modifiers = *modifiers;
183         switch(stuff->grab_type)
184         {
185             case XIGrabtypeButton:
186                 status = GrabButton(client, dev, mod_dev, stuff->detail,
187                                     &param, GRABTYPE_XI2, &mask);
188                 break;
189             case XIGrabtypeKeycode:
190                 status = GrabKey(client, dev, mod_dev, stuff->detail,
191                                  &param, GRABTYPE_XI2, &mask);
192                 break;
193             case XIGrabtypeEnter:
194             case XIGrabtypeFocusIn:
195                 status = GrabWindow(client, dev, stuff->grab_type,
196                                     &param, &mask);
197                 break;
198         }
200         if (status != GrabSuccess)
201         {
202             xXIGrabModifierInfo *info = modifiers_failed + rep.num_modifiers;
204             info->status = status;
205             info->modifiers = *modifiers;
206             if (client->swapped)
207                 swapl(&info->modifiers, n);
209             rep.num_modifiers++;
210             rep.length += bytes_to_int32(sizeof(xXIGrabModifierInfo));
211         }
212     }
214     WriteReplyToClient(client, sizeof(rep), &rep);
215     if (rep.num_modifiers)
216         WriteToClient(client, rep.length * 4, (char*)modifiers_failed);
218     free(modifiers_failed);
219     return ret;
222 void
223 SRepXIPassiveGrabDevice(ClientPtr client, int size,
224                         xXIPassiveGrabDeviceReply * rep)
226     char n;
228     swaps(&rep->sequenceNumber, n);
229     swapl(&rep->length, n);
230     swaps(&rep->num_modifiers, n);
232     WriteToClient(client, size, (char *)rep);
235 int
236 SProcXIPassiveUngrabDevice(ClientPtr client)
238     char n;
239     int i;
240     uint32_t *modifiers;
242     REQUEST(xXIPassiveUngrabDeviceReq);
244     swaps(&stuff->length, n);
245     swapl(&stuff->grab_window, n);
246     swaps(&stuff->deviceid, n);
247     swapl(&stuff->detail, n);
248     swaps(&stuff->num_modifiers, n);
250     modifiers = (uint32_t*)&stuff[1];
252     for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
253         swapl(modifiers, n);
255     return ProcXIPassiveUngrabDevice(client);
258 int
259 ProcXIPassiveUngrabDevice(ClientPtr client)
261     DeviceIntPtr dev, mod_dev;
262     WindowPtr win;
263     GrabRec tempGrab;
264     uint32_t* modifiers;
265     int i, rc;
267     REQUEST(xXIPassiveUngrabDeviceReq);
268     REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq);
270     if (stuff->deviceid == XIAllDevices)
271         dev = inputInfo.all_devices;
272     else if (stuff->deviceid == XIAllMasterDevices)
273         dev = inputInfo.all_master_devices;
274     else
275     {
276         rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
277         if (rc != Success)
278             return rc;
279     }
281     if (stuff->grab_type != XIGrabtypeButton &&
282         stuff->grab_type != XIGrabtypeKeycode &&
283         stuff->grab_type != XIGrabtypeEnter &&
284         stuff->grab_type != XIGrabtypeFocusIn)
285     {
286         client->errorValue = stuff->grab_type;
287         return BadValue;
288     }
290     if ((stuff->grab_type == XIGrabtypeEnter ||
291          stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
292     {
293         client->errorValue = stuff->detail;
294         return BadValue;
295     }
297     rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
298     if (rc != Success)
299         return rc;
301     mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD);
303     tempGrab.resource = client->clientAsMask;
304     tempGrab.device = dev;
305     tempGrab.window = win;
306     switch(stuff->grab_type)
307     {
308         case XIGrabtypeButton:  tempGrab.type = XI_ButtonPress; break;
309         case XIGrabtypeKeycode:  tempGrab.type = XI_KeyPress;    break;
310         case XIGrabtypeEnter:   tempGrab.type = XI_Enter;       break;
311         case XIGrabtypeFocusIn: tempGrab.type = XI_FocusIn;     break;
312     }
313     tempGrab.grabtype = GRABTYPE_XI2;
314     tempGrab.modifierDevice = mod_dev;
315     tempGrab.modifiersDetail.pMask = NULL;
316     tempGrab.detail.exact = stuff->detail;
317     tempGrab.detail.pMask = NULL;
319     modifiers = (uint32_t*)&stuff[1];
321     for (i = 0; i < stuff->num_modifiers; i++, modifiers++)
322     {
323         tempGrab.modifiersDetail.exact = *modifiers;
324         DeletePassiveGrabFromList(&tempGrab);
325     }
327     return Success;