1*4882a593Smuzhiyun /**
2*4882a593Smuzhiyun * Copyright © 2011 Red Hat, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun * Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*4882a593Smuzhiyun * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
25*4882a593Smuzhiyun #include <dix-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <stdio.h>
29*4882a593Smuzhiyun #include <stdlib.h>
30*4882a593Smuzhiyun #include <X11/X.h>
31*4882a593Smuzhiyun #include <xfixesint.h>
32*4882a593Smuzhiyun #include <X11/extensions/xfixeswire.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include "tests-common.h"
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun static void
_fixes_test_direction(struct PointerBarrier * barrier,int d[4],int permitted)37*4882a593Smuzhiyun _fixes_test_direction(struct PointerBarrier *barrier, int d[4], int permitted)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun BOOL blocking;
40*4882a593Smuzhiyun int i, j;
41*4882a593Smuzhiyun int dir = barrier_get_direction(d[0], d[1], d[2], d[3]);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun barrier->directions = 0;
44*4882a593Smuzhiyun blocking = barrier_is_blocking_direction(barrier, dir);
45*4882a593Smuzhiyun assert(blocking);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun for (j = 0; j <= BarrierNegativeY; j++) {
48*4882a593Smuzhiyun for (i = 0; i <= BarrierNegativeY; i++) {
49*4882a593Smuzhiyun barrier->directions |= 1 << i;
50*4882a593Smuzhiyun blocking = barrier_is_blocking_direction(barrier, dir);
51*4882a593Smuzhiyun assert((barrier->directions & permitted) ==
52*4882a593Smuzhiyun permitted ? !blocking : blocking);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun static void
fixes_pointer_barrier_direction_test(void)59*4882a593Smuzhiyun fixes_pointer_barrier_direction_test(void)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun struct PointerBarrier barrier;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun int x = 100;
64*4882a593Smuzhiyun int y = 100;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun int directions[8][4] = {
67*4882a593Smuzhiyun {x, y, x, y + 100}, /* S */
68*4882a593Smuzhiyun {x + 50, y, x - 50, y + 100}, /* SW */
69*4882a593Smuzhiyun {x + 100, y, x, y}, /* W */
70*4882a593Smuzhiyun {x + 100, y + 50, x, y - 50}, /* NW */
71*4882a593Smuzhiyun {x, y + 100, x, y}, /* N */
72*4882a593Smuzhiyun {x - 50, y + 100, x + 50, y}, /* NE */
73*4882a593Smuzhiyun {x, y, x + 100, y}, /* E */
74*4882a593Smuzhiyun {x, y - 50, x + 100, y + 50}, /* SE */
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun barrier.x1 = x;
78*4882a593Smuzhiyun barrier.x2 = x;
79*4882a593Smuzhiyun barrier.y1 = y - 50;
80*4882a593Smuzhiyun barrier.y2 = y + 49;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[0], BarrierPositiveY);
83*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[1],
84*4882a593Smuzhiyun BarrierPositiveY | BarrierNegativeX);
85*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[2], BarrierNegativeX);
86*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[3],
87*4882a593Smuzhiyun BarrierNegativeY | BarrierNegativeX);
88*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[4], BarrierNegativeY);
89*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[5],
90*4882a593Smuzhiyun BarrierPositiveX | BarrierNegativeY);
91*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[6], BarrierPositiveX);
92*4882a593Smuzhiyun _fixes_test_direction(&barrier, directions[7],
93*4882a593Smuzhiyun BarrierPositiveY | BarrierPositiveX);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun static void
fixes_pointer_barriers_test(void)98*4882a593Smuzhiyun fixes_pointer_barriers_test(void)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun struct PointerBarrier barrier;
101*4882a593Smuzhiyun int x1, y1, x2, y2;
102*4882a593Smuzhiyun double distance;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun int x = 100;
105*4882a593Smuzhiyun int y = 100;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* vert barrier */
108*4882a593Smuzhiyun barrier.x1 = x;
109*4882a593Smuzhiyun barrier.x2 = x;
110*4882a593Smuzhiyun barrier.y1 = y - 50;
111*4882a593Smuzhiyun barrier.y2 = y + 50;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* across at half-way */
114*4882a593Smuzhiyun x1 = x + 1;
115*4882a593Smuzhiyun x2 = x - 1;
116*4882a593Smuzhiyun y1 = y;
117*4882a593Smuzhiyun y2 = y;
118*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
119*4882a593Smuzhiyun assert(distance == 1);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun /* definitely not across */
122*4882a593Smuzhiyun x1 = x + 10;
123*4882a593Smuzhiyun x2 = x + 5;
124*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* across, but outside of y range */
127*4882a593Smuzhiyun x1 = x + 1;
128*4882a593Smuzhiyun x2 = x - 1;
129*4882a593Smuzhiyun y1 = y + 100;
130*4882a593Smuzhiyun y2 = y + 100;
131*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* across, diagonally */
134*4882a593Smuzhiyun x1 = x + 5;
135*4882a593Smuzhiyun x2 = x - 5;
136*4882a593Smuzhiyun y1 = y + 5;
137*4882a593Smuzhiyun y2 = y - 5;
138*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* across but outside boundary, diagonally */
141*4882a593Smuzhiyun x1 = x + 5;
142*4882a593Smuzhiyun x2 = x - 5;
143*4882a593Smuzhiyun y1 = y + 100;
144*4882a593Smuzhiyun y2 = y + 50;
145*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → blocking */
148*4882a593Smuzhiyun x1 = x;
149*4882a593Smuzhiyun x2 = x - 1;
150*4882a593Smuzhiyun y1 = y;
151*4882a593Smuzhiyun y2 = y;
152*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → not blocking, positive */
155*4882a593Smuzhiyun x1 = x;
156*4882a593Smuzhiyun x2 = x + 1;
157*4882a593Smuzhiyun y1 = y;
158*4882a593Smuzhiyun y2 = y;
159*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → not blocking, negative */
162*4882a593Smuzhiyun x1 = x - 1;
163*4882a593Smuzhiyun x2 = x - 2;
164*4882a593Smuzhiyun y1 = y;
165*4882a593Smuzhiyun y2 = y;
166*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /* edge case: endpoint of movement on barrier → blocking */
169*4882a593Smuzhiyun x1 = x + 1;
170*4882a593Smuzhiyun x2 = x;
171*4882a593Smuzhiyun y1 = y;
172*4882a593Smuzhiyun y2 = y;
173*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* startpoint on barrier but outside y range */
176*4882a593Smuzhiyun x1 = x;
177*4882a593Smuzhiyun x2 = x - 1;
178*4882a593Smuzhiyun y1 = y + 100;
179*4882a593Smuzhiyun y2 = y + 100;
180*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* endpoint on barrier but outside y range */
183*4882a593Smuzhiyun x1 = x + 1;
184*4882a593Smuzhiyun x2 = x;
185*4882a593Smuzhiyun y1 = y + 100;
186*4882a593Smuzhiyun y2 = y + 100;
187*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* horizontal barrier */
190*4882a593Smuzhiyun barrier.x1 = x - 50;
191*4882a593Smuzhiyun barrier.x2 = x + 50;
192*4882a593Smuzhiyun barrier.y1 = y;
193*4882a593Smuzhiyun barrier.y2 = y;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /* across at half-way */
196*4882a593Smuzhiyun x1 = x;
197*4882a593Smuzhiyun x2 = x;
198*4882a593Smuzhiyun y1 = y - 1;
199*4882a593Smuzhiyun y2 = y + 1;
200*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* definitely not across */
203*4882a593Smuzhiyun y1 = y + 10;
204*4882a593Smuzhiyun y2 = y + 5;
205*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /* across, but outside of y range */
208*4882a593Smuzhiyun x1 = x + 100;
209*4882a593Smuzhiyun x2 = x + 100;
210*4882a593Smuzhiyun y1 = y + 1;
211*4882a593Smuzhiyun y2 = y - 1;
212*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /* across, diagonally */
215*4882a593Smuzhiyun y1 = y + 5;
216*4882a593Smuzhiyun y2 = y - 5;
217*4882a593Smuzhiyun x1 = x + 5;
218*4882a593Smuzhiyun x2 = x - 5;
219*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* across but outside boundary, diagonally */
222*4882a593Smuzhiyun y1 = y + 5;
223*4882a593Smuzhiyun y2 = y - 5;
224*4882a593Smuzhiyun x1 = x + 100;
225*4882a593Smuzhiyun x2 = x + 50;
226*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → blocking */
229*4882a593Smuzhiyun y1 = y;
230*4882a593Smuzhiyun y2 = y - 1;
231*4882a593Smuzhiyun x1 = x;
232*4882a593Smuzhiyun x2 = x;
233*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → not blocking, positive */
236*4882a593Smuzhiyun y1 = y;
237*4882a593Smuzhiyun y2 = y + 1;
238*4882a593Smuzhiyun x1 = x;
239*4882a593Smuzhiyun x2 = x;
240*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* edge case: startpoint of movement on barrier → not blocking, negative */
243*4882a593Smuzhiyun y1 = y - 1;
244*4882a593Smuzhiyun y2 = y - 2;
245*4882a593Smuzhiyun x1 = x;
246*4882a593Smuzhiyun x2 = x;
247*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* edge case: endpoint of movement on barrier → blocking */
250*4882a593Smuzhiyun y1 = y + 1;
251*4882a593Smuzhiyun y2 = y;
252*4882a593Smuzhiyun x1 = x;
253*4882a593Smuzhiyun x2 = x;
254*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* startpoint on barrier but outside y range */
257*4882a593Smuzhiyun y1 = y;
258*4882a593Smuzhiyun y2 = y - 1;
259*4882a593Smuzhiyun x1 = x + 100;
260*4882a593Smuzhiyun x2 = x + 100;
261*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /* endpoint on barrier but outside y range */
264*4882a593Smuzhiyun y1 = y + 1;
265*4882a593Smuzhiyun y2 = y;
266*4882a593Smuzhiyun x1 = x + 100;
267*4882a593Smuzhiyun x2 = x + 100;
268*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* ray vert barrier */
271*4882a593Smuzhiyun barrier.x1 = x;
272*4882a593Smuzhiyun barrier.x2 = x;
273*4882a593Smuzhiyun barrier.y1 = -1;
274*4882a593Smuzhiyun barrier.y2 = y + 100;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* ray barrier simple case */
277*4882a593Smuzhiyun y1 = y;
278*4882a593Smuzhiyun y2 = y;
279*4882a593Smuzhiyun x1 = x + 50;
280*4882a593Smuzhiyun x2 = x - 50;
281*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /* endpoint outside y range; should be blocked */
284*4882a593Smuzhiyun y1 = y - 1000;
285*4882a593Smuzhiyun y2 = y - 1000;
286*4882a593Smuzhiyun x1 = x + 50;
287*4882a593Smuzhiyun x2 = x - 50;
288*4882a593Smuzhiyun assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /* endpoint outside y range */
291*4882a593Smuzhiyun y1 = y + 150;
292*4882a593Smuzhiyun y2 = y + 150;
293*4882a593Smuzhiyun x1 = x + 50;
294*4882a593Smuzhiyun x2 = x - 50;
295*4882a593Smuzhiyun assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun static void
fixes_pointer_barrier_clamp_test(void)299*4882a593Smuzhiyun fixes_pointer_barrier_clamp_test(void)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun struct PointerBarrier barrier;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun int x = 100;
304*4882a593Smuzhiyun int y = 100;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun int cx, cy; /* clamped */
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /* vert barrier */
309*4882a593Smuzhiyun barrier.x1 = x;
310*4882a593Smuzhiyun barrier.x2 = x;
311*4882a593Smuzhiyun barrier.y1 = y - 50;
312*4882a593Smuzhiyun barrier.y2 = y + 49;
313*4882a593Smuzhiyun barrier.directions = 0;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun cx = INT_MAX;
316*4882a593Smuzhiyun cy = INT_MAX;
317*4882a593Smuzhiyun barrier_clamp_to_barrier(&barrier, BarrierPositiveX, &cx, &cy);
318*4882a593Smuzhiyun assert(cx == barrier.x1 - 1);
319*4882a593Smuzhiyun assert(cy == INT_MAX);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun cx = 0;
322*4882a593Smuzhiyun cy = INT_MAX;
323*4882a593Smuzhiyun barrier_clamp_to_barrier(&barrier, BarrierNegativeX, &cx, &cy);
324*4882a593Smuzhiyun assert(cx == barrier.x1);
325*4882a593Smuzhiyun assert(cy == INT_MAX);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun /* horiz barrier */
328*4882a593Smuzhiyun barrier.x1 = x - 50;
329*4882a593Smuzhiyun barrier.x2 = x + 49;
330*4882a593Smuzhiyun barrier.y1 = y;
331*4882a593Smuzhiyun barrier.y2 = y;
332*4882a593Smuzhiyun barrier.directions = 0;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun cx = INT_MAX;
335*4882a593Smuzhiyun cy = INT_MAX;
336*4882a593Smuzhiyun barrier_clamp_to_barrier(&barrier, BarrierPositiveY, &cx, &cy);
337*4882a593Smuzhiyun assert(cx == INT_MAX);
338*4882a593Smuzhiyun assert(cy == barrier.y1 - 1);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun cx = INT_MAX;
341*4882a593Smuzhiyun cy = 0;
342*4882a593Smuzhiyun barrier_clamp_to_barrier(&barrier, BarrierNegativeY, &cx, &cy);
343*4882a593Smuzhiyun assert(cx == INT_MAX);
344*4882a593Smuzhiyun assert(cy == barrier.y1);
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun int
fixes_test(void)348*4882a593Smuzhiyun fixes_test(void)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun fixes_pointer_barriers_test();
352*4882a593Smuzhiyun fixes_pointer_barrier_direction_test();
353*4882a593Smuzhiyun fixes_pointer_barrier_clamp_test();
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun return 0;
356*4882a593Smuzhiyun }
357