diff options
author | Adam Jackson <ajax@redhat.com> | 2011-05-25 05:54:35 -0400 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2011-05-31 15:10:51 -0400 |
commit | d45f5b2493bc0a2882bf972849b5c9c50cd533ca (patch) | |
tree | 08ee6bc366efad2b49299a6f6b350042c8d5af0b /test | |
parent | 4621bb270a36d35d4ab67f1d7fb47674683dfc5b (diff) |
fixes: Add support for pointer barriers
Implements pointer barriers as specified by version 5 of the XFIXES
protocol. Barriers are axis-aligned, zero-width lines that block pointer
movement for relative input devices. Barriers may block motion in either
the positive or negative direction, or both.
v3:
- Fix off-by-one in version_requests array
- Port to non-glib test harness
- Fix review notes from Søren Sandmann Pedersen, add tests to match
Co-authored-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile.am | 3 | ||||
-rw-r--r-- | test/fixes.c | 327 |
2 files changed, 329 insertions, 1 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index b7ee070a1..5574e7d1e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,7 @@ if ENABLE_UNIT_TESTS if HAVE_LD_WRAP SUBDIRS= . xi2 -noinst_PROGRAMS = xkb input xtest list misc +noinst_PROGRAMS = xkb input xtest list misc fixes check_LTLIBRARIES = libxservertest.la TESTS=$(noinst_PROGRAMS) @@ -19,6 +19,7 @@ input_LDADD=$(TEST_LDADD) xtest_LDADD=$(TEST_LDADD) list_LDADD=$(TEST_LDADD) misc_LDADD=$(TEST_LDADD) +fixes_LDADD=$(TEST_LDADD) libxservertest_la_LIBADD = \ $(XSERVER_LIBS) \ diff --git a/test/fixes.c b/test/fixes.c new file mode 100644 index 000000000..8c804ba26 --- /dev/null +++ b/test/fixes.c @@ -0,0 +1,327 @@ +/** + * Copyright © 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <X11/X.h> +#include <xfixesint.h> +#include <X11/extensions/xfixeswire.h> + +static void +_fixes_test_direction(struct PointerBarrier *barrier, int d[4], int permitted) +{ + BOOL blocking; + int i, j; + int dir = barrier_get_direction(d[0], d[1], d[2], d[3]); + + barrier->directions = 0; + blocking = barrier_is_blocking_direction(barrier, dir); + assert(blocking); + + for (j = 0; j <= BarrierNegativeY; j++) + { + for (i = 0; i <= BarrierNegativeY; i++) + { + barrier->directions |= 1 << i; + blocking = barrier_is_blocking_direction(barrier, dir); + assert((barrier->directions & permitted) == permitted ? !blocking : blocking); + } + } + +} + +static void +fixes_pointer_barrier_direction_test(void) +{ + struct PointerBarrier barrier; + + int x = 100; + int y = 100; + + int directions[8][4] = { + { x, y, x, y + 100}, /* S */ + { x + 50, y, x - 50, y + 100}, /* SW */ + { x + 100, y, x, y}, /* W */ + { x + 100, y + 50, x, y - 50}, /* NW */ + { x, y + 100, x, y}, /* N */ + { x - 50, y + 100, x + 50, y}, /* NE */ + { x, y, x + 100, y}, /* E */ + { x, y - 50, x + 100, y + 50}, /* SE */ + }; + + barrier.x1 = x; + barrier.x2 = x; + barrier.y1 = y - 50; + barrier.y2 = y + 49; + + + _fixes_test_direction(&barrier, directions[0], BarrierPositiveY); + _fixes_test_direction(&barrier, directions[1], BarrierPositiveY | BarrierNegativeX); + _fixes_test_direction(&barrier, directions[2], BarrierNegativeX); + _fixes_test_direction(&barrier, directions[3], BarrierNegativeY | BarrierNegativeX); + _fixes_test_direction(&barrier, directions[4], BarrierNegativeY); + _fixes_test_direction(&barrier, directions[5], BarrierPositiveX | BarrierNegativeY); + _fixes_test_direction(&barrier, directions[6], BarrierPositiveX); + _fixes_test_direction(&barrier, directions[7], BarrierPositiveY | BarrierPositiveX); + + +} + + +static void +fixes_pointer_barriers_test(void) +{ + struct PointerBarrier barrier; + int x1, y1, x2, y2; + double distance; + + int x = 100; + int y = 100; + + /* vert barrier */ + barrier.x1 = x; + barrier.x2 = x; + barrier.y1 = y - 50; + barrier.y2 = y + 50; + + /* across at half-way */ + x1 = x + 1; + x2 = x - 1; + y1 = y; + y2 = y; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + assert(distance == 1); + + /* definitely not across */ + x1 = x + 10; + x2 = x + 5; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across, but outside of y range */ + x1 = x + 1; + x2 = x -1; + y1 = y + 100; + y2 = y + 100; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across, diagonally */ + x1 = x + 5; + x2 = x - 5; + y1 = y + 5; + y2 = y - 5; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across but outside boundary, diagonally */ + x1 = x + 5; + x2 = x - 5; + y1 = y + 100; + y2 = y + 50; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → blocking */ + x1 = x; + x2 = x - 1; + y1 = y; + y2 = y; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → not blocking, positive */ + x1 = x; + x2 = x + 1; + y1 = y; + y2 = y; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → not blocking, negative */ + x1 = x - 1; + x2 = x - 2; + y1 = y; + y2 = y; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: endpoint of movement on barrier → blocking */ + x1 = x + 1; + x2 = x; + y1 = y; + y2 = y; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* startpoint on barrier but outside y range */ + x1 = x; + x2 = x - 1; + y1 = y + 100; + y2 = y + 100; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* endpoint on barrier but outside y range */ + x1 = x + 1; + x2 = x; + y1 = y + 100; + y2 = y + 100; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + + /* horizontal barrier */ + barrier.x1 = x - 50; + barrier.x2 = x + 50; + barrier.y1 = y; + barrier.y2 = y; + + /* across at half-way */ + x1 = x; + x2 = x; + y1 = y - 1; + y2 = y + 1; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* definitely not across */ + y1 = y + 10; + y2 = y + 5; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across, but outside of y range */ + x1 = x + 100; + x2 = x + 100; + y1 = y + 1; + y2 = y -1; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across, diagonally */ + y1 = y + 5; + y2 = y - 5; + x1 = x + 5; + x2 = x - 5; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* across but outside boundary, diagonally */ + y1 = y + 5; + y2 = y - 5; + x1 = x + 100; + x2 = x + 50; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → blocking */ + y1 = y; + y2 = y - 1; + x1 = x; + x2 = x; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → not blocking, positive */ + y1 = y; + y2 = y + 1; + x1 = x; + x2 = x; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: startpoint of movement on barrier → not blocking, negative */ + y1 = y - 1; + y2 = y - 2; + x1 = x; + x2 = x; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* edge case: endpoint of movement on barrier → blocking */ + y1 = y + 1; + y2 = y; + x1 = x; + x2 = x; + assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* startpoint on barrier but outside y range */ + y1 = y; + y2 = y - 1; + x1 = x + 100; + x2 = x + 100; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + + /* endpoint on barrier but outside y range */ + y1 = y + 1; + y2 = y; + x1 = x + 100; + x2 = x + 100; + assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); + +} + +static void fixes_pointer_barrier_clamp_test(void) +{ + struct PointerBarrier barrier; + + int x = 100; + int y = 100; + + int cx, cy; /* clamped */ + + /* vert barrier */ + barrier.x1 = x; + barrier.x2 = x; + barrier.y1 = y - 50; + barrier.y2 = y + 49; + barrier.directions = 0; + + cx = INT_MAX; + cy = INT_MAX; + barrier_clamp_to_barrier(&barrier, BarrierPositiveX, &cx, &cy); + assert(cx == barrier.x1 - 1); + assert(cy == INT_MAX); + + cx = 0; + cy = INT_MAX; + barrier_clamp_to_barrier(&barrier, BarrierNegativeX, &cx, &cy); + assert(cx == barrier.x1); + assert(cy == INT_MAX); + + /* horiz barrier */ + barrier.x1 = x - 50; + barrier.x2 = x + 49; + barrier.y1 = y; + barrier.y2 = y; + barrier.directions = 0; + + cx = INT_MAX; + cy = INT_MAX; + barrier_clamp_to_barrier(&barrier, BarrierPositiveY, &cx, &cy); + assert(cx == INT_MAX); + assert(cy == barrier.y1 - 1); + + cx = INT_MAX; + cy = 0; + barrier_clamp_to_barrier(&barrier, BarrierNegativeY, &cx, &cy); + assert(cx == INT_MAX); + assert(cy == barrier.y1); +} + +int main(int argc, char** argv) +{ + + fixes_pointer_barriers_test(); + fixes_pointer_barrier_direction_test(); + fixes_pointer_barrier_clamp_test(); + + return 0; +} |