Merge remote-tracking branch 'ajax/xserver-next'
This commit is contained in:
		
						commit
						0643c05651
					
				|  | @ -810,7 +810,7 @@ dnl specific modules against it | ||||||
| PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) | PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) | ||||||
| REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" | REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" | ||||||
| 
 | 
 | ||||||
| REQUIRED_MODULES="[fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" | REQUIRED_MODULES="[fixesproto >= 5.0] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" | ||||||
| 
 | 
 | ||||||
| if test "x$CONFIG_UDEV" = xyes && | if test "x$CONFIG_UDEV" = xyes && | ||||||
|  { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then |  { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then | ||||||
|  |  | ||||||
|  | @ -122,7 +122,7 @@ | ||||||
| #define SERVER_XF86VIDMODE_MINOR_VERSION	2 | #define SERVER_XF86VIDMODE_MINOR_VERSION	2 | ||||||
| 
 | 
 | ||||||
| /* Fixes */ | /* Fixes */ | ||||||
| #define SERVER_XFIXES_MAJOR_VERSION		4 | #define SERVER_XFIXES_MAJOR_VERSION		5 | ||||||
| #define SERVER_XFIXES_MINOR_VERSION		0 | #define SERVER_XFIXES_MINOR_VERSION		0 | ||||||
| 
 | 
 | ||||||
| /* X Input */ | /* X Input */ | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| if ENABLE_UNIT_TESTS | if ENABLE_UNIT_TESTS | ||||||
| if HAVE_LD_WRAP | if HAVE_LD_WRAP | ||||||
| SUBDIRS= . xi2 | SUBDIRS= . xi2 | ||||||
| noinst_PROGRAMS = xkb input xtest list misc | noinst_PROGRAMS = xkb input xtest list misc fixes | ||||||
| check_LTLIBRARIES = libxservertest.la | check_LTLIBRARIES = libxservertest.la | ||||||
| 
 | 
 | ||||||
| TESTS=$(noinst_PROGRAMS) | TESTS=$(noinst_PROGRAMS) | ||||||
|  | @ -19,6 +19,7 @@ input_LDADD=$(TEST_LDADD) | ||||||
| xtest_LDADD=$(TEST_LDADD) | xtest_LDADD=$(TEST_LDADD) | ||||||
| list_LDADD=$(TEST_LDADD) | list_LDADD=$(TEST_LDADD) | ||||||
| misc_LDADD=$(TEST_LDADD) | misc_LDADD=$(TEST_LDADD) | ||||||
|  | fixes_LDADD=$(TEST_LDADD) | ||||||
| 
 | 
 | ||||||
| libxservertest_la_LIBADD = \
 | libxservertest_la_LIBADD = \
 | ||||||
|             $(XSERVER_LIBS) \
 |             $(XSERVER_LIBS) \
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | } | ||||||
							
								
								
									
										399
									
								
								xfixes/cursor.c
								
								
								
								
							
							
						
						
									
										399
									
								
								xfixes/cursor.c
								
								
								
								
							|  | @ -1,5 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | ||||||
|  |  * Copyright 2010 Red Hat, Inc. | ||||||
|  * |  * | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  * Permission is hereby granted, free of charge, to any person obtaining a | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  * copy of this software and associated documentation files (the "Software"), | ||||||
|  | @ -50,13 +51,16 @@ | ||||||
| #include "cursorstr.h" | #include "cursorstr.h" | ||||||
| #include "dixevents.h" | #include "dixevents.h" | ||||||
| #include "servermd.h" | #include "servermd.h" | ||||||
|  | #include "mipointer.h" | ||||||
| #include "inputstr.h" | #include "inputstr.h" | ||||||
| #include "windowstr.h" | #include "windowstr.h" | ||||||
| #include "xace.h" | #include "xace.h" | ||||||
|  | #include "list.h" | ||||||
| 
 | 
 | ||||||
| static RESTYPE		CursorClientType; | static RESTYPE		CursorClientType; | ||||||
| static RESTYPE		CursorHideCountType; | static RESTYPE		CursorHideCountType; | ||||||
| static RESTYPE		CursorWindowType; | static RESTYPE		CursorWindowType; | ||||||
|  | RESTYPE			PointerBarrierType; | ||||||
| static CursorPtr	CursorCurrent[MAXDEVICES]; | static CursorPtr	CursorCurrent[MAXDEVICES]; | ||||||
| 
 | 
 | ||||||
| static DevPrivateKeyRec CursorScreenPrivateKeyRec; | static DevPrivateKeyRec CursorScreenPrivateKeyRec; | ||||||
|  | @ -107,6 +111,14 @@ typedef struct _CursorHideCountRec { | ||||||
|     XID			 resource; |     XID			 resource; | ||||||
| } CursorHideCountRec; | } CursorHideCountRec; | ||||||
| 
 | 
 | ||||||
|  | typedef struct PointerBarrierClient *PointerBarrierClientPtr; | ||||||
|  | 
 | ||||||
|  | struct PointerBarrierClient { | ||||||
|  |     ScreenPtr screen; | ||||||
|  |     struct PointerBarrier barrier; | ||||||
|  |     struct list entry; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Wrap DisplayCursor to catch cursor change events |  * Wrap DisplayCursor to catch cursor change events | ||||||
|  */ |  */ | ||||||
|  | @ -114,7 +126,9 @@ typedef struct _CursorHideCountRec { | ||||||
| typedef struct _CursorScreen { | typedef struct _CursorScreen { | ||||||
|     DisplayCursorProcPtr	DisplayCursor; |     DisplayCursorProcPtr	DisplayCursor; | ||||||
|     CloseScreenProcPtr		CloseScreen; |     CloseScreenProcPtr		CloseScreen; | ||||||
|  |     ConstrainCursorHarderProcPtr ConstrainCursorHarder; | ||||||
|     CursorHideCountPtr          pCursorHideCounts; |     CursorHideCountPtr          pCursorHideCounts; | ||||||
|  |     struct list                 barriers; | ||||||
| } CursorScreenRec, *CursorScreenPtr; | } CursorScreenRec, *CursorScreenPtr; | ||||||
| 
 | 
 | ||||||
| #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey)) | #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey)) | ||||||
|  | @ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen) | ||||||
|     Bool		ret; |     Bool		ret; | ||||||
|     CloseScreenProcPtr	close_proc; |     CloseScreenProcPtr	close_proc; | ||||||
|     DisplayCursorProcPtr display_proc; |     DisplayCursorProcPtr display_proc; | ||||||
|  |     ConstrainCursorHarderProcPtr constrain_proc; | ||||||
| 
 | 
 | ||||||
|     Unwrap (cs, pScreen, CloseScreen, close_proc); |     Unwrap (cs, pScreen, CloseScreen, close_proc); | ||||||
|     Unwrap (cs, pScreen, DisplayCursor, display_proc); |     Unwrap (cs, pScreen, DisplayCursor, display_proc); | ||||||
|  |     Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc); | ||||||
|     deleteCursorHideCountsForScreen(pScreen); |     deleteCursorHideCountsForScreen(pScreen); | ||||||
|     ret = (*pScreen->CloseScreen) (index, pScreen); |     ret = (*pScreen->CloseScreen) (index, pScreen); | ||||||
|     free(cs); |     free(cs); | ||||||
|  | @ -1029,6 +1045,382 @@ CursorFreeWindow (pointer data, XID id) | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static BOOL | ||||||
|  | barrier_is_horizontal(const struct PointerBarrier *barrier) | ||||||
|  | { | ||||||
|  |     return barrier->y1 == barrier->y2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static BOOL | ||||||
|  | barrier_is_vertical(const struct PointerBarrier *barrier) | ||||||
|  | { | ||||||
|  |     return barrier->x1 == barrier->x2; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * @return The set of barrier movement directions the movement vector | ||||||
|  |  * x1/y1 → x2/y2 represents. | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | barrier_get_direction(int x1, int y1, int x2, int y2) | ||||||
|  | { | ||||||
|  |     int direction = 0; | ||||||
|  | 
 | ||||||
|  |     /* which way are we trying to go */ | ||||||
|  |     if (x2 > x1) | ||||||
|  | 	direction |= BarrierPositiveX; | ||||||
|  |     if (x2 < x1) | ||||||
|  | 	direction |= BarrierNegativeX; | ||||||
|  |     if (y2 > y1) | ||||||
|  | 	direction |= BarrierPositiveY; | ||||||
|  |     if (y2 < y1) | ||||||
|  | 	direction |= BarrierNegativeY; | ||||||
|  | 
 | ||||||
|  |     return direction; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Test if the barrier may block movement in the direction defined by | ||||||
|  |  * x1/y1 → x2/y2. This function only tests whether the directions could be | ||||||
|  |  * blocked, it does not test if the barrier actually blocks the movement. | ||||||
|  |  * | ||||||
|  |  * @return TRUE if the barrier blocks the direction of movement or FALSE | ||||||
|  |  * otherwise. | ||||||
|  |  */ | ||||||
|  | BOOL | ||||||
|  | barrier_is_blocking_direction(const struct PointerBarrier *barrier, int direction) | ||||||
|  | { | ||||||
|  |     /* Barriers define which way is ok, not which way is blocking */ | ||||||
|  |     return (barrier->directions & direction) != direction; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Test if the movement vector x1/y1 → x2/y2 is intersecting with the | ||||||
|  |  * barrier. A movement vector with the startpoint or endpoint adjacent to | ||||||
|  |  * the barrier itself counts as intersecting. | ||||||
|  |  * | ||||||
|  |  * @param x1 X start coordinate of movement vector | ||||||
|  |  * @param y1 Y start coordinate of movement vector | ||||||
|  |  * @param x2 X end coordinate of movement vector | ||||||
|  |  * @param y2 Y end coordinate of movement vector | ||||||
|  |  * @param[out] distance The distance between the start point and the | ||||||
|  |  * intersection with the barrier (if applicable). | ||||||
|  |  * @return TRUE if the barrier intersects with the given vector | ||||||
|  |  */ | ||||||
|  | BOOL | ||||||
|  | barrier_is_blocking(const struct PointerBarrier *barrier, | ||||||
|  | 		    int x1, int y1, int x2, int y2, | ||||||
|  | 		    double *distance) | ||||||
|  | { | ||||||
|  |     BOOL rc = FALSE; | ||||||
|  |     float ua, ub, ud; | ||||||
|  |     int dir = barrier_get_direction(x1, y1, x2, y2); | ||||||
|  | 
 | ||||||
|  |     /* Algorithm below doesn't handle edge cases well, hence the extra
 | ||||||
|  |      * checks. */ | ||||||
|  |     if (barrier_is_vertical(barrier)) { | ||||||
|  | 	/* handle immediate barrier adjacency, moving away */ | ||||||
|  | 	if (dir & BarrierPositiveX && x1 == barrier->x1) | ||||||
|  | 	    return FALSE; | ||||||
|  | 	if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1)) | ||||||
|  | 	    return FALSE; | ||||||
|  | 	/* startpoint adjacent to barrier, moving towards -> block */ | ||||||
|  | 	if (x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) { | ||||||
|  | 	    *distance = 0; | ||||||
|  | 	    return TRUE; | ||||||
|  | 	} | ||||||
|  |     } else { | ||||||
|  | 	/* handle immediate barrier adjacency, moving away */ | ||||||
|  | 	if (dir & BarrierPositiveY && y1 == barrier->y1) | ||||||
|  | 	    return FALSE; | ||||||
|  | 	if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1)) | ||||||
|  | 	    return FALSE; | ||||||
|  | 	/* startpoint adjacent to barrier, moving towards -> block */ | ||||||
|  | 	if (y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) { | ||||||
|  | 	    *distance = 0; | ||||||
|  | 	    return TRUE; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* not an edge case, compute distance */ | ||||||
|  |     ua = 0; | ||||||
|  |     ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 - barrier->x1) * (y2 - y1); | ||||||
|  |     if (ud != 0) { | ||||||
|  | 	ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) - | ||||||
|  | 	     (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud; | ||||||
|  | 	ub = ((x2 - x1) * (y1 - barrier->y1) - | ||||||
|  | 	     (y2 - y1) * (x1 - barrier->x1)) / ud; | ||||||
|  | 	if (ua < 0 || ua > 1 || ub < 0 || ub > 1) | ||||||
|  | 	    ua = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (ua > 0 && ua <= 1) | ||||||
|  |     { | ||||||
|  | 	double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1); | ||||||
|  | 	double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1); | ||||||
|  | 
 | ||||||
|  | 	*distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2)); | ||||||
|  | 	rc = TRUE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return rc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2. | ||||||
|  |  * | ||||||
|  |  * @param dir Only barriers blocking movement in direction dir are checked | ||||||
|  |  * @param x1 X start coordinate of movement vector | ||||||
|  |  * @param y1 Y start coordinate of movement vector | ||||||
|  |  * @param x2 X end coordinate of movement vector | ||||||
|  |  * @param y2 Y end coordinate of movement vector | ||||||
|  |  * @return The barrier nearest to the movement origin that blocks this movement. | ||||||
|  |  */ | ||||||
|  | static struct PointerBarrier* | ||||||
|  | barrier_find_nearest(CursorScreenPtr cs, int dir, | ||||||
|  | 		     int x1, int y1, int x2, int y2) | ||||||
|  | { | ||||||
|  |     struct PointerBarrierClient *c; | ||||||
|  |     struct PointerBarrier *nearest = NULL; | ||||||
|  |     double min_distance = INT_MAX; /* can't get higher than that in X anyway */ | ||||||
|  | 
 | ||||||
|  |     list_for_each_entry(c, &cs->barriers, entry) { | ||||||
|  | 	struct PointerBarrier *b = &c->barrier; | ||||||
|  | 	double distance; | ||||||
|  | 
 | ||||||
|  | 	if (!barrier_is_blocking_direction(b, dir)) | ||||||
|  | 	    continue; | ||||||
|  | 
 | ||||||
|  | 	if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) | ||||||
|  | 	{ | ||||||
|  | 	    if (min_distance > distance) | ||||||
|  | 	    { | ||||||
|  | 		min_distance = distance; | ||||||
|  | 		nearest = b; | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return nearest; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Clamp to the given barrier given the movement direction specified in dir. | ||||||
|  |  * | ||||||
|  |  * @param barrier The barrier to clamp to | ||||||
|  |  * @param dir The movement direction | ||||||
|  |  * @param[out] x The clamped x coordinate. | ||||||
|  |  * @param[out] y The clamped x coordinate. | ||||||
|  |  */ | ||||||
|  | void | ||||||
|  | barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y) | ||||||
|  | { | ||||||
|  |     if (barrier_is_vertical(barrier)) | ||||||
|  |     { | ||||||
|  | 	if ((dir & BarrierNegativeX) & ~barrier->directions) | ||||||
|  | 	    *x = barrier->x1; | ||||||
|  | 	if ((dir & BarrierPositiveX) & ~barrier->directions) | ||||||
|  | 	    *x = barrier->x1 - 1; | ||||||
|  |     } | ||||||
|  |     if (barrier_is_horizontal(barrier)) | ||||||
|  |     { | ||||||
|  | 	if ((dir & BarrierNegativeY) & ~barrier->directions) | ||||||
|  | 	    *y = barrier->y1; | ||||||
|  | 	if ((dir & BarrierPositiveY) & ~barrier->directions) | ||||||
|  | 	    *y = barrier->y1 - 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y) | ||||||
|  | { | ||||||
|  |     CursorScreenPtr cs = GetCursorScreen(screen); | ||||||
|  | 
 | ||||||
|  |     if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) { | ||||||
|  | 	int ox, oy; | ||||||
|  | 	int dir; | ||||||
|  | 	struct PointerBarrier *nearest = NULL; | ||||||
|  | 
 | ||||||
|  | 	/* where are we coming from */ | ||||||
|  | 	miPointerGetPosition(dev, &ox, &oy); | ||||||
|  | 
 | ||||||
|  | 	/* How this works:
 | ||||||
|  | 	 * Given the origin and the movement vector, get the nearest barrier | ||||||
|  | 	 * to the origin that is blocking the movement. | ||||||
|  | 	 * Clamp to that barrier. | ||||||
|  | 	 * Then, check from the clamped intersection to the original | ||||||
|  | 	 * destination, again finding the nearest barrier and clamping. | ||||||
|  | 	 */ | ||||||
|  | 	dir = barrier_get_direction(ox, oy, *x, *y); | ||||||
|  | 
 | ||||||
|  | 	nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); | ||||||
|  | 	if (nearest) { | ||||||
|  | 	    barrier_clamp_to_barrier(nearest, dir, x, y); | ||||||
|  | 
 | ||||||
|  | 	    if (barrier_is_vertical(nearest)) { | ||||||
|  | 		dir &= ~(BarrierNegativeX | BarrierPositiveX); | ||||||
|  | 		ox = *x; | ||||||
|  | 	    } else if (barrier_is_horizontal(nearest)) { | ||||||
|  | 		dir &= ~(BarrierNegativeY | BarrierPositiveY); | ||||||
|  | 		oy = *y; | ||||||
|  | 	    } | ||||||
|  | 
 | ||||||
|  | 	    nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); | ||||||
|  | 	    if (nearest) { | ||||||
|  | 		barrier_clamp_to_barrier(nearest, dir, x, y); | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (cs->ConstrainCursorHarder) { | ||||||
|  | 	screen->ConstrainCursorHarder = cs->ConstrainCursorHarder; | ||||||
|  | 	screen->ConstrainCursorHarder(dev, screen, mode, x, y); | ||||||
|  | 	screen->ConstrainCursorHarder = CursorConstrainCursorHarder; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct PointerBarrierClient * | ||||||
|  | CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, | ||||||
|  | 			   xXFixesCreatePointerBarrierReq *stuff) | ||||||
|  | { | ||||||
|  |     CursorScreenPtr cs = GetCursorScreen(screen); | ||||||
|  |     struct PointerBarrierClient *ret = malloc(sizeof(*ret)); | ||||||
|  | 
 | ||||||
|  |     if (ret) { | ||||||
|  | 	ret->screen = screen; | ||||||
|  | 	ret->barrier.x1 = min(stuff->x1, stuff->x2); | ||||||
|  | 	ret->barrier.x2 = max(stuff->x1, stuff->x2); | ||||||
|  | 	ret->barrier.y1 = min(stuff->y1, stuff->y2); | ||||||
|  | 	ret->barrier.y2 = max(stuff->y1, stuff->y2); | ||||||
|  | 	ret->barrier.directions = stuff->directions & 0x0f; | ||||||
|  | 	if (barrier_is_horizontal(&ret->barrier)) | ||||||
|  | 	    ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX); | ||||||
|  | 	if (barrier_is_vertical(&ret->barrier)) | ||||||
|  | 	    ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY); | ||||||
|  | 	list_add(&ret->entry, &cs->barriers); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | ProcXFixesCreatePointerBarrier (ClientPtr client) | ||||||
|  | { | ||||||
|  |     int err; | ||||||
|  |     WindowPtr pWin; | ||||||
|  |     struct PointerBarrierClient *barrier; | ||||||
|  |     struct PointerBarrier b; | ||||||
|  |     REQUEST (xXFixesCreatePointerBarrierReq); | ||||||
|  | 
 | ||||||
|  |     REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); | ||||||
|  |     LEGAL_NEW_RESOURCE(stuff->barrier, client); | ||||||
|  | 
 | ||||||
|  |     err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); | ||||||
|  |     if (err != Success) { | ||||||
|  | 	client->errorValue = stuff->window; | ||||||
|  | 	return err; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /* This sure does need fixing. */ | ||||||
|  |     if (stuff->num_devices) | ||||||
|  | 	return BadImplementation; | ||||||
|  | 
 | ||||||
|  |     b.x1 = stuff->x1; | ||||||
|  |     b.x2 = stuff->x2; | ||||||
|  |     b.y1 = stuff->y1; | ||||||
|  |     b.y2 = stuff->y2; | ||||||
|  | 
 | ||||||
|  |     if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b)) | ||||||
|  | 	return BadValue; | ||||||
|  | 
 | ||||||
|  |     /* no 0-sized barriers */ | ||||||
|  |     if (barrier_is_horizontal(&b) && barrier_is_vertical(&b)) | ||||||
|  | 	return BadValue; | ||||||
|  | 
 | ||||||
|  |     if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen, | ||||||
|  | 					       client, stuff))) | ||||||
|  | 	return BadAlloc; | ||||||
|  | 
 | ||||||
|  |     if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier)) | ||||||
|  | 	return BadAlloc; | ||||||
|  | 
 | ||||||
|  |     return Success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | SProcXFixesCreatePointerBarrier (ClientPtr client) | ||||||
|  | { | ||||||
|  |     int n; | ||||||
|  |     REQUEST(xXFixesCreatePointerBarrierReq); | ||||||
|  | 
 | ||||||
|  |     swaps(&stuff->length, n); | ||||||
|  |     REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); | ||||||
|  |     swapl(&stuff->barrier, n); | ||||||
|  |     swapl(&stuff->window, n); | ||||||
|  |     swaps(&stuff->x1, n); | ||||||
|  |     swaps(&stuff->y1, n); | ||||||
|  |     swaps(&stuff->x2, n); | ||||||
|  |     swaps(&stuff->y2, n); | ||||||
|  |     swapl(&stuff->directions, n); | ||||||
|  |     return ProcXFixesVector[stuff->xfixesReqType](client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int | ||||||
|  | CursorFreeBarrier(void *data, XID id) | ||||||
|  | { | ||||||
|  |     struct PointerBarrierClient *b = NULL, *barrier; | ||||||
|  |     ScreenPtr screen; | ||||||
|  |     CursorScreenPtr cs; | ||||||
|  | 
 | ||||||
|  |     barrier = container_of(data, struct PointerBarrierClient, barrier); | ||||||
|  |     screen = barrier->screen; | ||||||
|  |     cs = GetCursorScreen(screen); | ||||||
|  | 
 | ||||||
|  |     /* find and unlink from the screen private */ | ||||||
|  |     list_for_each_entry(b, &cs->barriers, entry) { | ||||||
|  | 	if (b == barrier) { | ||||||
|  | 	    list_del(&b->entry); | ||||||
|  | 	    break; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     free(barrier); | ||||||
|  |     return Success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | ProcXFixesDestroyPointerBarrier (ClientPtr client) | ||||||
|  | { | ||||||
|  |     int err; | ||||||
|  |     void *barrier; | ||||||
|  |     REQUEST (xXFixesDestroyPointerBarrierReq); | ||||||
|  | 
 | ||||||
|  |     REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); | ||||||
|  | 
 | ||||||
|  |     err = dixLookupResourceByType((void **)&barrier, stuff->barrier, | ||||||
|  | 				  PointerBarrierType, client, | ||||||
|  | 				  DixDestroyAccess); | ||||||
|  |     if (err != Success) { | ||||||
|  | 	client->errorValue = stuff->barrier; | ||||||
|  | 	return err; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     FreeResource(stuff->barrier, RT_NONE); | ||||||
|  |     return Success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | SProcXFixesDestroyPointerBarrier (ClientPtr client) | ||||||
|  | { | ||||||
|  |     int n; | ||||||
|  |     REQUEST(xXFixesDestroyPointerBarrierReq); | ||||||
|  | 
 | ||||||
|  |     swaps(&stuff->length, n); | ||||||
|  |     REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); | ||||||
|  |     swapl(&stuff->barrier, n); | ||||||
|  |     return ProcXFixesVector[stuff->xfixesReqType](client); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Bool | Bool | ||||||
| XFixesCursorInit (void) | XFixesCursorInit (void) | ||||||
| { | { | ||||||
|  | @ -1048,8 +1440,10 @@ XFixesCursorInit (void) | ||||||
| 	cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec)); | 	cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec)); | ||||||
| 	if (!cs) | 	if (!cs) | ||||||
| 	    return FALSE; | 	    return FALSE; | ||||||
|  | 	list_init(&cs->barriers); | ||||||
| 	Wrap (cs, pScreen, CloseScreen, CursorCloseScreen); | 	Wrap (cs, pScreen, CloseScreen, CursorCloseScreen); | ||||||
| 	Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); | 	Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); | ||||||
|  | 	Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder); | ||||||
| 	cs->pCursorHideCounts = NULL; | 	cs->pCursorHideCounts = NULL; | ||||||
| 	SetCursorScreen (pScreen, cs); | 	SetCursorScreen (pScreen, cs); | ||||||
|     } |     } | ||||||
|  | @ -1059,7 +1453,10 @@ XFixesCursorInit (void) | ||||||
| 						"XFixesCursorHideCount"); | 						"XFixesCursorHideCount"); | ||||||
|     CursorWindowType = CreateNewResourceType(CursorFreeWindow, |     CursorWindowType = CreateNewResourceType(CursorFreeWindow, | ||||||
| 					     "XFixesCursorWindow"); | 					     "XFixesCursorWindow"); | ||||||
|  |     PointerBarrierType = CreateNewResourceType(CursorFreeBarrier, | ||||||
|  | 					      "XFixesPointerBarrier"); | ||||||
| 
 | 
 | ||||||
|     return CursorClientType && CursorHideCountType && CursorWindowType; |     return CursorClientType && CursorHideCountType && CursorWindowType && | ||||||
|  | 	   PointerBarrierType; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | ||||||
|  |  * Copyright 2010 Red Hat, Inc. | ||||||
|  * |  * | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  * Permission is hereby granted, free of charge, to any person obtaining a | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  * copy of this software and associated documentation files (the "Software"), | ||||||
|  | @ -47,10 +48,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "xfixesint.h" | #include "xfixesint.h" | ||||||
| #include "protocol-versions.h" | #include "protocol-versions.h" | ||||||
| /*
 |  | ||||||
|  * Must use these instead of the constants from xfixeswire.h.  They advertise |  | ||||||
|  * what we implement, not what the protocol headers define. |  | ||||||
|  */ |  | ||||||
| 
 | 
 | ||||||
| static unsigned char	XFixesReqCode; | static unsigned char	XFixesReqCode; | ||||||
| int		XFixesEventBase; | int		XFixesEventBase; | ||||||
|  | @ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client) | ||||||
| 
 | 
 | ||||||
| /* Major version controls available requests */ | /* Major version controls available requests */ | ||||||
| static const int version_requests[] = { | static const int version_requests[] = { | ||||||
|     X_XFixesQueryVersion,	/* before client sends QueryVersion */ |     X_XFixesQueryVersion,	    /* before client sends QueryVersion */ | ||||||
|     X_XFixesGetCursorImage,	/* Version 1 */ |     X_XFixesGetCursorImage,	    /* Version 1 */ | ||||||
|     X_XFixesChangeCursorByName,	/* Version 2 */ |     X_XFixesChangeCursorByName,	    /* Version 2 */ | ||||||
|     X_XFixesExpandRegion,	/* Version 3 */ |     X_XFixesExpandRegion,	    /* Version 3 */ | ||||||
|     X_XFixesShowCursor,	        /* Version 4 */ |     X_XFixesShowCursor,		    /* Version 4 */ | ||||||
|  |     X_XFixesDestroyPointerBarrier,  /* Version 5 */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0])) | #define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0])) | ||||||
|  | @ -142,6 +140,9 @@ int	(*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = { | ||||||
| /*************** Version 4 ****************/ | /*************** Version 4 ****************/ | ||||||
|     ProcXFixesHideCursor, |     ProcXFixesHideCursor, | ||||||
|     ProcXFixesShowCursor, |     ProcXFixesShowCursor, | ||||||
|  | /*************** Version 5 ****************/ | ||||||
|  |     ProcXFixesCreatePointerBarrier, | ||||||
|  |     ProcXFixesDestroyPointerBarrier, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
|  | @ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = { | ||||||
| /*************** Version 4 ****************/ | /*************** Version 4 ****************/ | ||||||
|     SProcXFixesHideCursor, |     SProcXFixesHideCursor, | ||||||
|     SProcXFixesShowCursor, |     SProcXFixesShowCursor, | ||||||
|  | /*************** Version 5 ****************/ | ||||||
|  |     SProcXFixesCreatePointerBarrier, | ||||||
|  |     SProcXFixesDestroyPointerBarrier, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
|  | @ -260,6 +264,8 @@ XFixesExtensionInit(void) | ||||||
| 	EventSwapVector[XFixesEventBase + XFixesCursorNotify] = | 	EventSwapVector[XFixesEventBase + XFixesCursorNotify] = | ||||||
| 	    (EventSwapPtr) SXFixesCursorNotifyEvent; | 	    (EventSwapPtr) SXFixesCursorNotifyEvent; | ||||||
| 	SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion); | 	SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion); | ||||||
|  | 	SetResourceTypeErrorValue(PointerBarrierType, | ||||||
|  | 				  XFixesErrorBase + BadBarrier); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
| 
 | 
 | ||||||
| extern _X_EXPORT RESTYPE RegionResType; | extern _X_EXPORT RESTYPE RegionResType; | ||||||
|  | extern _X_EXPORT RESTYPE PointerBarrierType; | ||||||
| extern _X_EXPORT int XFixesErrorBase; | extern _X_EXPORT int XFixesErrorBase; | ||||||
| 
 | 
 | ||||||
| #define VERIFY_REGION(pRegion, rid, client, mode)			\ | #define VERIFY_REGION(pRegion, rid, client, mode)			\ | ||||||
|  | @ -51,5 +52,21 @@ extern _X_EXPORT int XFixesErrorBase; | ||||||
| extern _X_EXPORT RegionPtr | extern _X_EXPORT RegionPtr | ||||||
| XFixesRegionCopy (RegionPtr pRegion); | XFixesRegionCopy (RegionPtr pRegion); | ||||||
| 
 | 
 | ||||||
|  | struct PointerBarrier { | ||||||
|  |     CARD16 x1, x2, y1, y2; | ||||||
|  |     CARD32 directions; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | extern int | ||||||
|  | barrier_get_direction(int, int, int, int); | ||||||
|  | extern BOOL | ||||||
|  | barrier_is_blocking(const struct PointerBarrier*, int, int, int, int, double*); | ||||||
|  | extern BOOL | ||||||
|  | barrier_is_blocking_direction(const struct PointerBarrier*, int); | ||||||
|  | extern void | ||||||
|  | barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| #endif /* _XFIXES_H_ */ | #endif /* _XFIXES_H_ */ | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | ||||||
|  |  * Copyright 2010 Red Hat, Inc. | ||||||
|  * |  * | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  * Permission is hereby granted, free of charge, to any person obtaining a | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  * copy of this software and associated documentation files (the "Software"), | ||||||
|  | @ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client); | ||||||
| int  | int  | ||||||
| SProcXFixesShowCursor (ClientPtr client); | SProcXFixesShowCursor (ClientPtr client); | ||||||
| 
 | 
 | ||||||
|  | /* Version 5 */ | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | ProcXFixesCreatePointerBarrier (ClientPtr client); | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | SProcXFixesCreatePointerBarrier (ClientPtr client); | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | ProcXFixesDestroyPointerBarrier (ClientPtr client); | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | SProcXFixesDestroyPointerBarrier (ClientPtr client); | ||||||
|  | 
 | ||||||
|  | /* Xinerama */ | ||||||
| extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr); | extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr); | ||||||
| void PanoramiXFixesInit (void); | void PanoramiXFixesInit (void); | ||||||
| void PanoramiXFixesReset (void); | void PanoramiXFixesReset (void); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue