1 /**
2  * Copyright © 2011 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 
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <X11/X.h>
31 #include <xfixesint.h>
32 #include <X11/extensions/xfixeswire.h>
33 
34 #include "tests-common.h"
35 
36 static void
_fixes_test_direction(struct PointerBarrier * barrier,int d[4],int permitted)37 _fixes_test_direction(struct PointerBarrier *barrier, int d[4], int permitted)
38 {
39     BOOL blocking;
40     int i, j;
41     int dir = barrier_get_direction(d[0], d[1], d[2], d[3]);
42 
43     barrier->directions = 0;
44     blocking = barrier_is_blocking_direction(barrier, dir);
45     assert(blocking);
46 
47     for (j = 0; j <= BarrierNegativeY; j++) {
48         for (i = 0; i <= BarrierNegativeY; i++) {
49             barrier->directions |= 1 << i;
50             blocking = barrier_is_blocking_direction(barrier, dir);
51             assert((barrier->directions & permitted) ==
52                    permitted ? !blocking : blocking);
53         }
54     }
55 
56 }
57 
58 static void
fixes_pointer_barrier_direction_test(void)59 fixes_pointer_barrier_direction_test(void)
60 {
61     struct PointerBarrier barrier;
62 
63     int x = 100;
64     int y = 100;
65 
66     int directions[8][4] = {
67         {x, y, x, y + 100},     /* S  */
68         {x + 50, y, x - 50, y + 100},   /* SW */
69         {x + 100, y, x, y},     /* W  */
70         {x + 100, y + 50, x, y - 50},   /* NW */
71         {x, y + 100, x, y},     /* N  */
72         {x - 50, y + 100, x + 50, y},   /* NE */
73         {x, y, x + 100, y},     /* E  */
74         {x, y - 50, x + 100, y + 50},   /* SE */
75     };
76 
77     barrier.x1 = x;
78     barrier.x2 = x;
79     barrier.y1 = y - 50;
80     barrier.y2 = y + 49;
81 
82     _fixes_test_direction(&barrier, directions[0], BarrierPositiveY);
83     _fixes_test_direction(&barrier, directions[1],
84                           BarrierPositiveY | BarrierNegativeX);
85     _fixes_test_direction(&barrier, directions[2], BarrierNegativeX);
86     _fixes_test_direction(&barrier, directions[3],
87                           BarrierNegativeY | BarrierNegativeX);
88     _fixes_test_direction(&barrier, directions[4], BarrierNegativeY);
89     _fixes_test_direction(&barrier, directions[5],
90                           BarrierPositiveX | BarrierNegativeY);
91     _fixes_test_direction(&barrier, directions[6], BarrierPositiveX);
92     _fixes_test_direction(&barrier, directions[7],
93                           BarrierPositiveY | BarrierPositiveX);
94 
95 }
96 
97 static void
fixes_pointer_barriers_test(void)98 fixes_pointer_barriers_test(void)
99 {
100     struct PointerBarrier barrier;
101     int x1, y1, x2, y2;
102     double distance;
103 
104     int x = 100;
105     int y = 100;
106 
107     /* vert barrier */
108     barrier.x1 = x;
109     barrier.x2 = x;
110     barrier.y1 = y - 50;
111     barrier.y2 = y + 50;
112 
113     /* across at half-way */
114     x1 = x + 1;
115     x2 = x - 1;
116     y1 = y;
117     y2 = y;
118     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
119     assert(distance == 1);
120 
121     /* definitely not across */
122     x1 = x + 10;
123     x2 = x + 5;
124     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
125 
126     /* across, but outside of y range */
127     x1 = x + 1;
128     x2 = x - 1;
129     y1 = y + 100;
130     y2 = y + 100;
131     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
132 
133     /* across, diagonally */
134     x1 = x + 5;
135     x2 = x - 5;
136     y1 = y + 5;
137     y2 = y - 5;
138     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
139 
140     /* across but outside boundary, diagonally */
141     x1 = x + 5;
142     x2 = x - 5;
143     y1 = y + 100;
144     y2 = y + 50;
145     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
146 
147     /* edge case: startpoint of movement on barrier → blocking */
148     x1 = x;
149     x2 = x - 1;
150     y1 = y;
151     y2 = y;
152     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
153 
154     /* edge case: startpoint of movement on barrier → not blocking, positive */
155     x1 = x;
156     x2 = x + 1;
157     y1 = y;
158     y2 = y;
159     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
160 
161     /* edge case: startpoint of movement on barrier → not blocking, negative */
162     x1 = x - 1;
163     x2 = x - 2;
164     y1 = y;
165     y2 = y;
166     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
167 
168     /* edge case: endpoint of movement on barrier → blocking */
169     x1 = x + 1;
170     x2 = x;
171     y1 = y;
172     y2 = y;
173     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
174 
175     /* startpoint on barrier but outside y range */
176     x1 = x;
177     x2 = x - 1;
178     y1 = y + 100;
179     y2 = y + 100;
180     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
181 
182     /* endpoint on barrier but outside y range */
183     x1 = x + 1;
184     x2 = x;
185     y1 = y + 100;
186     y2 = y + 100;
187     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
188 
189     /* horizontal barrier */
190     barrier.x1 = x - 50;
191     barrier.x2 = x + 50;
192     barrier.y1 = y;
193     barrier.y2 = y;
194 
195     /* across at half-way */
196     x1 = x;
197     x2 = x;
198     y1 = y - 1;
199     y2 = y + 1;
200     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
201 
202     /* definitely not across */
203     y1 = y + 10;
204     y2 = y + 5;
205     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
206 
207     /* across, but outside of y range */
208     x1 = x + 100;
209     x2 = x + 100;
210     y1 = y + 1;
211     y2 = y - 1;
212     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
213 
214     /* across, diagonally */
215     y1 = y + 5;
216     y2 = y - 5;
217     x1 = x + 5;
218     x2 = x - 5;
219     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
220 
221     /* across but outside boundary, diagonally */
222     y1 = y + 5;
223     y2 = y - 5;
224     x1 = x + 100;
225     x2 = x + 50;
226     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
227 
228     /* edge case: startpoint of movement on barrier → blocking */
229     y1 = y;
230     y2 = y - 1;
231     x1 = x;
232     x2 = x;
233     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
234 
235     /* edge case: startpoint of movement on barrier → not blocking, positive */
236     y1 = y;
237     y2 = y + 1;
238     x1 = x;
239     x2 = x;
240     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
241 
242     /* edge case: startpoint of movement on barrier → not blocking, negative */
243     y1 = y - 1;
244     y2 = y - 2;
245     x1 = x;
246     x2 = x;
247     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
248 
249     /* edge case: endpoint of movement on barrier → blocking */
250     y1 = y + 1;
251     y2 = y;
252     x1 = x;
253     x2 = x;
254     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
255 
256     /* startpoint on barrier but outside y range */
257     y1 = y;
258     y2 = y - 1;
259     x1 = x + 100;
260     x2 = x + 100;
261     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
262 
263     /* endpoint on barrier but outside y range */
264     y1 = y + 1;
265     y2 = y;
266     x1 = x + 100;
267     x2 = x + 100;
268     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
269 
270     /* ray vert barrier */
271     barrier.x1 = x;
272     barrier.x2 = x;
273     barrier.y1 = -1;
274     barrier.y2 = y + 100;
275 
276     /* ray barrier simple case */
277     y1 = y;
278     y2 = y;
279     x1 = x + 50;
280     x2 = x - 50;
281     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
282 
283     /* endpoint outside y range; should be blocked */
284     y1 = y - 1000;
285     y2 = y - 1000;
286     x1 = x + 50;
287     x2 = x - 50;
288     assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
289 
290     /* endpoint outside y range */
291     y1 = y + 150;
292     y2 = y + 150;
293     x1 = x + 50;
294     x2 = x - 50;
295     assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance));
296 }
297 
298 static void
fixes_pointer_barrier_clamp_test(void)299 fixes_pointer_barrier_clamp_test(void)
300 {
301     struct PointerBarrier barrier;
302 
303     int x = 100;
304     int y = 100;
305 
306     int cx, cy;                 /* clamped */
307 
308     /* vert barrier */
309     barrier.x1 = x;
310     barrier.x2 = x;
311     barrier.y1 = y - 50;
312     barrier.y2 = y + 49;
313     barrier.directions = 0;
314 
315     cx = INT_MAX;
316     cy = INT_MAX;
317     barrier_clamp_to_barrier(&barrier, BarrierPositiveX, &cx, &cy);
318     assert(cx == barrier.x1 - 1);
319     assert(cy == INT_MAX);
320 
321     cx = 0;
322     cy = INT_MAX;
323     barrier_clamp_to_barrier(&barrier, BarrierNegativeX, &cx, &cy);
324     assert(cx == barrier.x1);
325     assert(cy == INT_MAX);
326 
327     /* horiz barrier */
328     barrier.x1 = x - 50;
329     barrier.x2 = x + 49;
330     barrier.y1 = y;
331     barrier.y2 = y;
332     barrier.directions = 0;
333 
334     cx = INT_MAX;
335     cy = INT_MAX;
336     barrier_clamp_to_barrier(&barrier, BarrierPositiveY, &cx, &cy);
337     assert(cx == INT_MAX);
338     assert(cy == barrier.y1 - 1);
339 
340     cx = INT_MAX;
341     cy = 0;
342     barrier_clamp_to_barrier(&barrier, BarrierNegativeY, &cx, &cy);
343     assert(cx == INT_MAX);
344     assert(cy == barrier.y1);
345 }
346 
347 int
fixes_test(void)348 fixes_test(void)
349 {
350 
351     fixes_pointer_barriers_test();
352     fixes_pointer_barrier_direction_test();
353     fixes_pointer_barrier_clamp_test();
354 
355     return 0;
356 }
357