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.
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
29 * Protocol testing for XISelectEvents request.
33 * Wrap XISetEventMask to intercept when the server tries to apply the event
34 * mask. Ensure that the mask passed in is equivalent to the one supplied by
35 * the client. Ensure that invalid devices and invalid masks return errors
39 * BadValue for num_masks < 0
40 * BadWindow for invalid windows
41 * BadDevice for non-existing devices
42 * BadImplemenation for devices >= 0xFF
43 * BadValue if HierarchyChanged bit is set for devices other than
45 * BadValue for invalid mask bits
46 * Sucecss for excessive mask lengths
52 #include <X11/Xproto.h>
53 #include <X11/extensions/XI2proto.h>
55 #include "windowstr.h"
56 #include "extinit.h" /* for XInputExtensionInit */
57 #include "scrnintstr.h"
58 #include "exglobals.h"
59 #include "xiselectev.h"
61 #include "protocol-common.h"
63 static unsigned char *data
[4096 * 20]; /* the request data buffer */
66 __wrap_XISetEventMask(DeviceIntPtr dev
, WindowPtr win
, int len
,
72 /* dixLookupWindow requires a lot of setup not necessary for this test.
73 * Simple wrapper that returns either one of the fake root window or the
74 * fake client window. If the requested ID is neither of those wanted,
75 * return whatever the real dixLookupWindow does.
78 __wrap_dixLookupWindow(WindowPtr
*win
, XID id
, ClientPtr client
, Mask access
)
80 if (id
== root
.drawable
.id
) {
84 else if (id
== window
.drawable
.id
) {
89 return __real_dixLookupWindow(win
, id
, client
, access
);
93 request_XISelectEvent(xXISelectEventsReq
* req
, int error
)
98 xXIEventMask
*mask
, *next
;
100 req
->length
= (sz_xXISelectEventsReq
/ 4);
101 mask
= (xXIEventMask
*) &req
[1];
102 for (i
= 0; i
< req
->num_masks
; i
++) {
103 req
->length
+= sizeof(xXIEventMask
) / 4 + mask
->mask_len
;
104 mask
= (xXIEventMask
*) ((char *) &mask
[1] + mask
->mask_len
* 4);
107 client
= init_client(req
->length
, req
);
109 rc
= ProcXISelectEvents(&client
);
112 client
.swapped
= TRUE
;
114 mask
= (xXIEventMask
*) &req
[1];
115 for (i
= 0; i
< req
->num_masks
; i
++) {
116 next
= (xXIEventMask
*) ((char *) &mask
[1] + mask
->mask_len
* 4);
117 swaps(&mask
->deviceid
);
118 swaps(&mask
->mask_len
);
124 swaps(&req
->num_masks
);
125 rc
= SProcXISelectEvents(&client
);
130 _set_bit(unsigned char *bits
, int bit
)
133 if (bit
>= XI_TouchBegin
&& bit
<= XI_TouchOwnership
) {
134 SetBit(bits
, XI_TouchBegin
);
135 SetBit(bits
, XI_TouchUpdate
);
136 SetBit(bits
, XI_TouchEnd
);
141 _clear_bit(unsigned char *bits
, int bit
)
144 if (bit
>= XI_TouchBegin
&& bit
<= XI_TouchOwnership
) {
145 ClearBit(bits
, XI_TouchBegin
);
146 ClearBit(bits
, XI_TouchUpdate
);
147 ClearBit(bits
, XI_TouchEnd
);
152 request_XISelectEvents_masks(xXISelectEventsReq
* req
)
156 int nmasks
= (XI2LASTEVENT
+ 7) / 8;
159 mask
= (xXIEventMask
*) &req
[1];
160 req
->win
= ROOT_WINDOW_ID
;
162 /* if a clients submits more than 100 masks, consider it insane and untested */
163 for (i
= 1; i
<= 1000; i
++) {
165 mask
->deviceid
= XIAllDevices
;
168 * mask_len is 0 -> Success
171 request_XISelectEvent(req
, Success
);
174 * mask may be larger than needed for XI2LASTEVENT.
175 * Test setting each valid mask bit, while leaving unneeded bits 0.
178 bits
= (unsigned char *) &mask
[1];
179 mask
->mask_len
= (nmasks
+ 3) / 4 * 10;
180 memset(bits
, 0, mask
->mask_len
* 4);
181 for (j
= 0; j
<= XI2LASTEVENT
; j
++) {
183 request_XISelectEvent(req
, Success
);
188 * mask may be larger than needed for XI2LASTEVENT.
189 * Test setting all valid mask bits, while leaving unneeded bits 0.
192 bits
= (unsigned char *) &mask
[1];
193 mask
->mask_len
= (nmasks
+ 3) / 4 * 10;
194 memset(bits
, 0, mask
->mask_len
* 4);
196 for (j
= 0; j
<= XI2LASTEVENT
; j
++) {
198 request_XISelectEvent(req
, Success
);
202 * mask is larger than needed for XI2LASTEVENT. If any unneeded bit
205 bits
= (unsigned char *) &mask
[1];
206 mask
->mask_len
= (nmasks
+ 3) / 4 * 10;
207 memset(bits
, 0, mask
->mask_len
* 4);
209 for (j
= XI2LASTEVENT
+ 1; j
< mask
->mask_len
* 4; j
++) {
211 request_XISelectEvent(req
, BadValue
);
216 * Mask len is a sensible length, only valid bits are set -> Success
218 bits
= (unsigned char *) &mask
[1];
219 mask
->mask_len
= (nmasks
+ 3) / 4;
220 memset(bits
, 0, mask
->mask_len
* 4);
221 for (j
= 0; j
<= XI2LASTEVENT
; j
++) {
223 request_XISelectEvent(req
, Success
);
227 * HierarchyChanged bit is BadValue for devices other than
230 bits
= (unsigned char *) &mask
[1];
231 mask
->mask_len
= (nmasks
+ 3) / 4;
232 memset(bits
, 0, mask
->mask_len
* 4);
233 SetBit(bits
, XI_HierarchyChanged
);
234 mask
->deviceid
= XIAllDevices
;
235 request_XISelectEvent(req
, Success
);
236 for (j
= 1; j
< devices
.num_devices
; j
++) {
238 request_XISelectEvent(req
, BadValue
);
242 * All bits set minus hierarchy changed bit -> Success
244 bits
= (unsigned char *) &mask
[1];
245 mask
->mask_len
= (nmasks
+ 3) / 4;
246 memset(bits
, 0, mask
->mask_len
* 4);
247 for (j
= 0; j
<= XI2LASTEVENT
; j
++)
249 _clear_bit(bits
, XI_HierarchyChanged
);
250 for (j
= 1; j
< 6; j
++) {
252 request_XISelectEvent(req
, Success
);
256 (xXIEventMask
*) ((char *) mask
+ sizeof(xXIEventMask
) +
262 test_XISelectEvents(void)
266 xXISelectEventsReq
*req
;
268 req
= (xXISelectEventsReq
*) data
;
270 request_init(req
, XISelectEvents
);
272 printf("Testing for BadValue on zero-length masks\n");
273 /* zero masks are BadValue, regardless of the window */
277 request_XISelectEvent(req
, BadValue
);
279 req
->win
= ROOT_WINDOW_ID
;
280 request_XISelectEvent(req
, BadValue
);
282 req
->win
= CLIENT_WINDOW_ID
;
283 request_XISelectEvent(req
, BadValue
);
285 printf("Testing for BadWindow.\n");
286 /* None window is BadWindow, regardless of the masks.
287 * We don't actually need to set the masks here, BadWindow must occur
288 * before checking the masks.
292 request_XISelectEvent(req
, BadWindow
);
295 request_XISelectEvent(req
, BadWindow
);
297 req
->num_masks
= 0xFF;
298 request_XISelectEvent(req
, BadWindow
);
300 /* request size is 3, so 0xFFFC is the highest num_mask that doesn't
301 * overflow req->length */
302 req
->num_masks
= 0xFFFC;
303 request_XISelectEvent(req
, BadWindow
);
305 printf("Triggering num_masks/length overflow\n");
306 req
->win
= ROOT_WINDOW_ID
;
307 /* Integer overflow - req->length can't hold that much */
308 req
->num_masks
= 0xFFFF;
309 request_XISelectEvent(req
, BadLength
);
311 req
->win
= ROOT_WINDOW_ID
;
314 printf("Triggering bogus mask length error\n");
315 mask
= (xXIEventMask
*) &req
[1];
317 mask
->mask_len
= 0xFFFF;
318 request_XISelectEvent(req
, BadLength
);
320 /* testing various device ids */
321 printf("Testing existing device ids.\n");
322 for (i
= 0; i
< 6; i
++) {
323 mask
= (xXIEventMask
*) &req
[1];
326 req
->win
= ROOT_WINDOW_ID
;
328 request_XISelectEvent(req
, Success
);
331 printf("Testing non-existing device ids.\n");
332 for (i
= 6; i
<= 0xFFFF; i
++) {
333 req
->win
= ROOT_WINDOW_ID
;
335 mask
= (xXIEventMask
*) &req
[1];
338 request_XISelectEvent(req
, BadDevice
);
341 request_XISelectEvents_masks(req
);
345 main(int argc
, char **argv
)
349 test_XISelectEvents();