2 * Copyright © 2009 Red Hat, Inc.
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:
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
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.
23 * Author: Peter Hutterer
26 /***********************************************************************
28 * Request to grab or ungrab input device.
32 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
36 #include "inputstr.h" /* DeviceIntPtr */
37 #include "windowstr.h" /* window structure */
38 #include <X11/extensions/XI2.h>
39 #include <X11/extensions/XI2proto.h>
42 #include "exglobals.h" /* BadDevice */
44 #include "xipassivegrab.h"
47 #include "inpututils.h"
50 SProcXIPassiveGrabDevice(ClientPtr client
)
55 REQUEST(xXIPassiveGrabDeviceReq
);
57 swaps(&stuff
->length
);
58 swaps(&stuff
->deviceid
);
59 swapl(&stuff
->grab_window
);
60 swapl(&stuff
->cursor
);
62 swapl(&stuff
->detail
);
63 swaps(&stuff
->mask_len
);
64 swaps(&stuff
->num_modifiers
);
66 mods
= (uint32_t *) &stuff
[1] + stuff
->mask_len
;
68 for (i
= 0; i
< stuff
->num_modifiers
; i
++, mods
++) {
72 return ProcXIPassiveGrabDevice(client
);
76 ProcXIPassiveGrabDevice(ClientPtr client
)
78 DeviceIntPtr dev
, mod_dev
;
79 xXIPassiveGrabDeviceReply rep
= {
81 .RepType
= X_XIPassiveGrabDevice
,
82 .sequenceNumber
= client
->sequence
,
88 xXIGrabModifierInfo
*modifiers_failed
;
89 GrabMask mask
= { 0 };
94 REQUEST(xXIPassiveGrabDeviceReq
);
95 REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq
);
97 if (stuff
->deviceid
== XIAllDevices
)
98 dev
= inputInfo
.all_devices
;
99 else if (stuff
->deviceid
== XIAllMasterDevices
)
100 dev
= inputInfo
.all_master_devices
;
102 ret
= dixLookupDevice(&dev
, stuff
->deviceid
, client
, DixGrabAccess
);
103 if (ret
!= Success
) {
104 client
->errorValue
= stuff
->deviceid
;
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
;
118 if ((stuff
->grab_type
== XIGrabtypeEnter
||
119 stuff
->grab_type
== XIGrabtypeFocusIn
||
120 stuff
->grab_type
== XIGrabtypeTouchBegin
) && stuff
->detail
!= 0) {
121 client
->errorValue
= stuff
->detail
;
125 if (stuff
->grab_type
== XIGrabtypeTouchBegin
&&
126 (stuff
->grab_mode
!= XIGrabModeTouch
||
127 stuff
->paired_device_mode
!= GrabModeAsync
)) {
128 client
->errorValue
= stuff
->grab_mode
;
132 if (XICheckInvalidMaskBits(client
, (unsigned char *) &stuff
[1],
133 stuff
->mask_len
* 4) != Success
)
136 mask
.xi2mask
= xi2mask_new();
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);
144 memset(¶m
, 0, sizeof(param
));
145 param
.grabtype
= XI2
;
146 param
.ownerEvents
= stuff
->owner_events
;
147 param
.grabWindow
= stuff
->grab_window
;
148 param
.cursor
= stuff
->cursor
;
150 if (IsKeyboardDevice(dev
)) {
151 param
.this_device_mode
= stuff
->grab_mode
;
152 param
.other_devices_mode
= stuff
->paired_device_mode
;
155 param
.this_device_mode
= stuff
->paired_device_mode
;
156 param
.other_devices_mode
= stuff
->grab_mode
;
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
;
169 dixLookupWindow((WindowPtr
*) &tmp
, stuff
->grab_window
, client
,
174 ret
= CheckGrabValues(client
, ¶m
);
178 modifiers
= (uint32_t *) &stuff
[1] + stuff
->mask_len
;
180 calloc(stuff
->num_modifiers
, sizeof(xXIGrabModifierInfo
));
181 if (!modifiers_failed
) {
186 mod_dev
= (IsFloating(dev
)) ? dev
: GetMaster(dev
, MASTER_KEYBOARD
);
188 for (i
= 0; i
< stuff
->num_modifiers
; i
++, modifiers
++) {
189 uint8_t status
= Success
;
191 param
.modifiers
= *modifiers
;
192 ret
= CheckGrabValues(client
, ¶m
);
196 switch (stuff
->grab_type
) {
197 case XIGrabtypeButton
:
198 status
= GrabButton(client
, dev
, mod_dev
, stuff
->detail
,
201 case XIGrabtypeKeycode
:
202 status
= GrabKey(client
, dev
, mod_dev
, stuff
->detail
,
205 case XIGrabtypeEnter
:
206 case XIGrabtypeFocusIn
:
207 status
= GrabWindow(client
, dev
, stuff
->grab_type
, ¶m
, &mask
);
209 case XIGrabtypeTouchBegin
:
210 status
= GrabTouch(client
, dev
, mod_dev
, ¶m
, &mask
);
214 if (status
!= GrabSuccess
) {
215 xXIGrabModifierInfo
*info
= modifiers_failed
+ rep
.num_modifiers
;
217 info
->status
= status
;
218 info
->modifiers
= *modifiers
;
220 swapl(&info
->modifiers
);
223 rep
.length
+= bytes_to_int32(sizeof(xXIGrabModifierInfo
));
227 WriteReplyToClient(client
, sizeof(rep
), &rep
);
228 if (rep
.num_modifiers
)
229 WriteToClient(client
, rep
.length
* 4, modifiers_failed
);
231 free(modifiers_failed
);
233 xi2mask_free(&mask
.xi2mask
);
238 SRepXIPassiveGrabDevice(ClientPtr client
, int size
,
239 xXIPassiveGrabDeviceReply
* rep
)
241 swaps(&rep
->sequenceNumber
);
243 swaps(&rep
->num_modifiers
);
245 WriteToClient(client
, size
, rep
);
249 SProcXIPassiveUngrabDevice(ClientPtr client
)
254 REQUEST(xXIPassiveUngrabDeviceReq
);
256 swaps(&stuff
->length
);
257 swapl(&stuff
->grab_window
);
258 swaps(&stuff
->deviceid
);
259 swapl(&stuff
->detail
);
260 swaps(&stuff
->num_modifiers
);
262 modifiers
= (uint32_t *) &stuff
[1];
264 for (i
= 0; i
< stuff
->num_modifiers
; i
++, modifiers
++)
267 return ProcXIPassiveUngrabDevice(client
);
271 ProcXIPassiveUngrabDevice(ClientPtr client
)
273 DeviceIntPtr dev
, mod_dev
;
279 REQUEST(xXIPassiveUngrabDeviceReq
);
280 REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq
);
282 if (stuff
->deviceid
== XIAllDevices
)
283 dev
= inputInfo
.all_devices
;
284 else if (stuff
->deviceid
== XIAllMasterDevices
)
285 dev
= inputInfo
.all_master_devices
;
287 rc
= dixLookupDevice(&dev
, stuff
->deviceid
, client
, DixGrabAccess
);
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
;
301 if ((stuff
->grab_type
== XIGrabtypeEnter
||
302 stuff
->grab_type
== XIGrabtypeFocusIn
||
303 stuff
->grab_type
== XIGrabtypeTouchBegin
) && stuff
->detail
!= 0) {
304 client
->errorValue
= stuff
->detail
;
308 rc
= dixLookupWindow(&win
, stuff
->grab_window
, client
, DixSetAttrAccess
);
312 mod_dev
= (IsFloating(dev
)) ? dev
: GetMaster(dev
, MASTER_KEYBOARD
);
314 tempGrab
= AllocGrab(NULL
);
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
;
325 case XIGrabtypeKeycode
:
326 tempGrab
->type
= XI_KeyPress
;
328 case XIGrabtypeEnter
:
329 tempGrab
->type
= XI_Enter
;
331 case XIGrabtypeFocusIn
:
332 tempGrab
->type
= XI_FocusIn
;
334 case XIGrabtypeTouchBegin
:
335 tempGrab
->type
= XI_TouchBegin
;
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
;
344 modifiers
= (uint32_t *) &stuff
[1];
346 for (i
= 0; i
< stuff
->num_modifiers
; i
++, modifiers
++) {
347 tempGrab
->modifiersDetail
.exact
= *modifiers
;
348 DeletePassiveGrabFromList(tempGrab
);