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