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 | |
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>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/protocol-versions.h | 2 | ||||
-rw-r--r-- | test/Makefile.am | 3 | ||||
-rw-r--r-- | test/fixes.c | 327 | ||||
-rw-r--r-- | xfixes/cursor.c | 399 | ||||
-rw-r--r-- | xfixes/xfixes.c | 24 | ||||
-rw-r--r-- | xfixes/xfixes.h | 17 | ||||
-rw-r--r-- | xfixes/xfixesint.h | 16 |
8 files changed, 777 insertions, 13 deletions
diff --git a/configure.ac b/configure.ac index 655c0e4ba..ba1d1768f 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -810,7 +810,7 @@ dnl specific modules against it | |||
810 | PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) | 810 | PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN) |
811 | REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" | 811 | REQUIRED_LIBS="$REQUIRED_LIBS $LIBPIXMAN $LIBXFONT xau" |
812 | 812 | ||
813 | REQUIRED_MODULES="[fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" | 813 | REQUIRED_MODULES="[fixesproto >= 5.0] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] $SDK_REQUIRED_MODULES" |
814 | 814 | ||
815 | if test "x$CONFIG_UDEV" = xyes && | 815 | if test "x$CONFIG_UDEV" = xyes && |
816 | { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then | 816 | { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then |
diff --git a/include/protocol-versions.h b/include/protocol-versions.h index 8692ded8a..7b7a9f53c 100644 --- a/include/protocol-versions.h +++ b/include/protocol-versions.h | |||
@@ -122,7 +122,7 @@ | |||
122 | #define SERVER_XF86VIDMODE_MINOR_VERSION 2 | 122 | #define SERVER_XF86VIDMODE_MINOR_VERSION 2 |
123 | 123 | ||
124 | /* Fixes */ | 124 | /* Fixes */ |
125 | #define SERVER_XFIXES_MAJOR_VERSION 4 | 125 | #define SERVER_XFIXES_MAJOR_VERSION 5 |
126 | #define SERVER_XFIXES_MINOR_VERSION 0 | 126 | #define SERVER_XFIXES_MINOR_VERSION 0 |
127 | 127 | ||
128 | /* X Input */ | 128 | /* X Input */ |
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 @@ | |||
1 | if ENABLE_UNIT_TESTS | 1 | if ENABLE_UNIT_TESTS |
2 | if HAVE_LD_WRAP | 2 | if HAVE_LD_WRAP |
3 | SUBDIRS= . xi2 | 3 | SUBDIRS= . xi2 |
4 | noinst_PROGRAMS = xkb input xtest list misc | 4 | noinst_PROGRAMS = xkb input xtest list misc fixes |
5 | check_LTLIBRARIES = libxservertest.la | 5 | check_LTLIBRARIES = libxservertest.la |
6 | 6 | ||
7 | TESTS=$(noinst_PROGRAMS) | 7 | TESTS=$(noinst_PROGRAMS) |
@@ -19,6 +19,7 @@ input_LDADD=$(TEST_LDADD) | |||
19 | xtest_LDADD=$(TEST_LDADD) | 19 | xtest_LDADD=$(TEST_LDADD) |
20 | list_LDADD=$(TEST_LDADD) | 20 | list_LDADD=$(TEST_LDADD) |
21 | misc_LDADD=$(TEST_LDADD) | 21 | misc_LDADD=$(TEST_LDADD) |
22 | fixes_LDADD=$(TEST_LDADD) | ||
22 | 23 | ||
23 | libxservertest_la_LIBADD = \ | 24 | libxservertest_la_LIBADD = \ |
24 | $(XSERVER_LIBS) \ | 25 | $(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 @@ | |||
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 | static void | ||
35 | _fixes_test_direction(struct PointerBarrier *barrier, int d[4], int permitted) | ||
36 | { | ||
37 | BOOL blocking; | ||
38 | int i, j; | ||
39 | int dir = barrier_get_direction(d[0], d[1], d[2], d[3]); | ||
40 | |||
41 | barrier->directions = 0; | ||
42 | blocking = barrier_is_blocking_direction(barrier, dir); | ||
43 | assert(blocking); | ||
44 | |||
45 | for (j = 0; j <= BarrierNegativeY; j++) | ||
46 | { | ||
47 | for (i = 0; i <= BarrierNegativeY; i++) | ||
48 | { | ||
49 | barrier->directions |= 1 << i; | ||
50 | blocking = barrier_is_blocking_direction(barrier, dir); | ||
51 | assert((barrier->directions & permitted) == permitted ? !blocking : blocking); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | } | ||
56 | |||
57 | static void | ||
58 | fixes_pointer_barrier_direction_test(void) | ||
59 | { | ||
60 | struct PointerBarrier barrier; | ||
61 | |||
62 | int x = 100; | ||
63 | int y = 100; | ||
64 | |||
65 | int directions[8][4] = { | ||
66 | { x, y, x, y + 100}, /* S */ | ||
67 | { x + 50, y, x - 50, y + 100}, /* SW */ | ||
68 | { x + 100, y, x, y}, /* W */ | ||
69 | { x + 100, y + 50, x, y - 50}, /* NW */ | ||
70 | { x, y + 100, x, y}, /* N */ | ||
71 | { x - 50, y + 100, x + 50, y}, /* NE */ | ||
72 | { x, y, x + 100, y}, /* E */ | ||
73 | { x, y - 50, x + 100, y + 50}, /* SE */ | ||
74 | }; | ||
75 | |||
76 | barrier.x1 = x; | ||
77 | barrier.x2 = x; | ||
78 | barrier.y1 = y - 50; | ||
79 | barrier.y2 = y + 49; | ||
80 | |||
81 | |||
82 | _fixes_test_direction(&barrier, directions[0], BarrierPositiveY); | ||
83 | _fixes_test_direction(&barrier, directions[1], BarrierPositiveY | BarrierNegativeX); | ||
84 | _fixes_test_direction(&barrier, directions[2], BarrierNegativeX); | ||
85 | _fixes_test_direction(&barrier, directions[3], BarrierNegativeY | BarrierNegativeX); | ||
86 | _fixes_test_direction(&barrier, directions[4], BarrierNegativeY); | ||
87 | _fixes_test_direction(&barrier, directions[5], BarrierPositiveX | BarrierNegativeY); | ||
88 | _fixes_test_direction(&barrier, directions[6], BarrierPositiveX); | ||
89 | _fixes_test_direction(&barrier, directions[7], BarrierPositiveY | BarrierPositiveX); | ||
90 | |||
91 | |||
92 | } | ||
93 | |||
94 | |||
95 | static void | ||
96 | fixes_pointer_barriers_test(void) | ||
97 | { | ||
98 | struct PointerBarrier barrier; | ||
99 | int x1, y1, x2, y2; | ||
100 | double distance; | ||
101 | |||
102 | int x = 100; | ||
103 | int y = 100; | ||
104 | |||
105 | /* vert barrier */ | ||
106 | barrier.x1 = x; | ||
107 | barrier.x2 = x; | ||
108 | barrier.y1 = y - 50; | ||
109 | barrier.y2 = y + 50; | ||
110 | |||
111 | /* across at half-way */ | ||
112 | x1 = x + 1; | ||
113 | x2 = x - 1; | ||
114 | y1 = y; | ||
115 | y2 = y; | ||
116 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
117 | assert(distance == 1); | ||
118 | |||
119 | /* definitely not across */ | ||
120 | x1 = x + 10; | ||
121 | x2 = x + 5; | ||
122 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
123 | |||
124 | /* across, but outside of y range */ | ||
125 | x1 = x + 1; | ||
126 | x2 = x -1; | ||
127 | y1 = y + 100; | ||
128 | y2 = y + 100; | ||
129 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
130 | |||
131 | /* across, diagonally */ | ||
132 | x1 = x + 5; | ||
133 | x2 = x - 5; | ||
134 | y1 = y + 5; | ||
135 | y2 = y - 5; | ||
136 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
137 | |||
138 | /* across but outside boundary, diagonally */ | ||
139 | x1 = x + 5; | ||
140 | x2 = x - 5; | ||
141 | y1 = y + 100; | ||
142 | y2 = y + 50; | ||
143 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
144 | |||
145 | /* edge case: startpoint of movement on barrier → blocking */ | ||
146 | x1 = x; | ||
147 | x2 = x - 1; | ||
148 | y1 = y; | ||
149 | y2 = y; | ||
150 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
151 | |||
152 | /* edge case: startpoint of movement on barrier → not blocking, positive */ | ||
153 | x1 = x; | ||
154 | x2 = x + 1; | ||
155 | y1 = y; | ||
156 | y2 = y; | ||
157 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
158 | |||
159 | /* edge case: startpoint of movement on barrier → not blocking, negative */ | ||
160 | x1 = x - 1; | ||
161 | x2 = x - 2; | ||
162 | y1 = y; | ||
163 | y2 = y; | ||
164 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
165 | |||
166 | /* edge case: endpoint of movement on barrier → blocking */ | ||
167 | x1 = x + 1; | ||
168 | x2 = x; | ||
169 | y1 = y; | ||
170 | y2 = y; | ||
171 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
172 | |||
173 | /* startpoint on barrier but outside y range */ | ||
174 | x1 = x; | ||
175 | x2 = x - 1; | ||
176 | y1 = y + 100; | ||
177 | y2 = y + 100; | ||
178 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
179 | |||
180 | /* endpoint on barrier but outside y range */ | ||
181 | x1 = x + 1; | ||
182 | x2 = x; | ||
183 | y1 = y + 100; | ||
184 | y2 = y + 100; | ||
185 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
186 | |||
187 | |||
188 | /* horizontal barrier */ | ||
189 | barrier.x1 = x - 50; | ||
190 | barrier.x2 = x + 50; | ||
191 | barrier.y1 = y; | ||
192 | barrier.y2 = y; | ||
193 | |||
194 | /* across at half-way */ | ||
195 | x1 = x; | ||
196 | x2 = x; | ||
197 | y1 = y - 1; | ||
198 | y2 = y + 1; | ||
199 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
200 | |||
201 | /* definitely not across */ | ||
202 | y1 = y + 10; | ||
203 | y2 = y + 5; | ||
204 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
205 | |||
206 | /* across, but outside of y range */ | ||
207 | x1 = x + 100; | ||
208 | x2 = x + 100; | ||
209 | y1 = y + 1; | ||
210 | y2 = y -1; | ||
211 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
212 | |||
213 | /* across, diagonally */ | ||
214 | y1 = y + 5; | ||
215 | y2 = y - 5; | ||
216 | x1 = x + 5; | ||
217 | x2 = x - 5; | ||
218 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
219 | |||
220 | /* across but outside boundary, diagonally */ | ||
221 | y1 = y + 5; | ||
222 | y2 = y - 5; | ||
223 | x1 = x + 100; | ||
224 | x2 = x + 50; | ||
225 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
226 | |||
227 | /* edge case: startpoint of movement on barrier → blocking */ | ||
228 | y1 = y; | ||
229 | y2 = y - 1; | ||
230 | x1 = x; | ||
231 | x2 = x; | ||
232 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
233 | |||
234 | /* edge case: startpoint of movement on barrier → not blocking, positive */ | ||
235 | y1 = y; | ||
236 | y2 = y + 1; | ||
237 | x1 = x; | ||
238 | x2 = x; | ||
239 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
240 | |||
241 | /* edge case: startpoint of movement on barrier → not blocking, negative */ | ||
242 | y1 = y - 1; | ||
243 | y2 = y - 2; | ||
244 | x1 = x; | ||
245 | x2 = x; | ||
246 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
247 | |||
248 | /* edge case: endpoint of movement on barrier → blocking */ | ||
249 | y1 = y + 1; | ||
250 | y2 = y; | ||
251 | x1 = x; | ||
252 | x2 = x; | ||
253 | assert(barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
254 | |||
255 | /* startpoint on barrier but outside y range */ | ||
256 | y1 = y; | ||
257 | y2 = y - 1; | ||
258 | x1 = x + 100; | ||
259 | x2 = x + 100; | ||
260 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
261 | |||
262 | /* endpoint on barrier but outside y range */ | ||
263 | y1 = y + 1; | ||
264 | y2 = y; | ||
265 | x1 = x + 100; | ||
266 | x2 = x + 100; | ||
267 | assert(!barrier_is_blocking(&barrier, x1, y1, x2, y2, &distance)); | ||
268 | |||
269 | } | ||
270 | |||
271 | static void fixes_pointer_barrier_clamp_test(void) | ||
272 | { | ||
273 | struct PointerBarrier barrier; | ||
274 | |||
275 | int x = 100; | ||
276 | int y = 100; | ||
277 | |||
278 | int cx, cy; /* clamped */ | ||
279 | |||
280 | /* vert barrier */ | ||
281 | barrier.x1 = x; | ||
282 | barrier.x2 = x; | ||
283 | barrier.y1 = y - 50; | ||
284 | barrier.y2 = y + 49; | ||
285 | barrier.directions = 0; | ||
286 | |||
287 | cx = INT_MAX; | ||
288 | cy = INT_MAX; | ||
289 | barrier_clamp_to_barrier(&barrier, BarrierPositiveX, &cx, &cy); | ||
290 | assert(cx == barrier.x1 - 1); | ||
291 | assert(cy == INT_MAX); | ||
292 | |||
293 | cx = 0; | ||
294 | cy = INT_MAX; | ||
295 | barrier_clamp_to_barrier(&barrier, BarrierNegativeX, &cx, &cy); | ||
296 | assert(cx == barrier.x1); | ||
297 | assert(cy == INT_MAX); | ||
298 | |||
299 | /* horiz barrier */ | ||
300 | barrier.x1 = x - 50; | ||
301 | barrier.x2 = x + 49; | ||
302 | barrier.y1 = y; | ||
303 | barrier.y2 = y; | ||
304 | barrier.directions = 0; | ||
305 | |||
306 | cx = INT_MAX; | ||
307 | cy = INT_MAX; | ||
308 | barrier_clamp_to_barrier(&barrier, BarrierPositiveY, &cx, &cy); | ||
309 | assert(cx == INT_MAX); | ||
310 | assert(cy == barrier.y1 - 1); | ||
311 | |||
312 | cx = INT_MAX; | ||
313 | cy = 0; | ||
314 | barrier_clamp_to_barrier(&barrier, BarrierNegativeY, &cx, &cy); | ||
315 | assert(cx == INT_MAX); | ||
316 | assert(cy == barrier.y1); | ||
317 | } | ||
318 | |||
319 | int main(int argc, char** argv) | ||
320 | { | ||
321 | |||
322 | fixes_pointer_barriers_test(); | ||
323 | fixes_pointer_barrier_direction_test(); | ||
324 | fixes_pointer_barrier_clamp_test(); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
diff --git a/xfixes/cursor.c b/xfixes/cursor.c index fb608f694..01eb70d92 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | 2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |
3 | * Copyright 2010 Red Hat, Inc. | ||
3 | * | 4 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 6 | * copy of this software and associated documentation files (the "Software"), |
@@ -50,13 +51,16 @@ | |||
50 | #include "cursorstr.h" | 51 | #include "cursorstr.h" |
51 | #include "dixevents.h" | 52 | #include "dixevents.h" |
52 | #include "servermd.h" | 53 | #include "servermd.h" |
54 | #include "mipointer.h" | ||
53 | #include "inputstr.h" | 55 | #include "inputstr.h" |
54 | #include "windowstr.h" | 56 | #include "windowstr.h" |
55 | #include "xace.h" | 57 | #include "xace.h" |
58 | #include "list.h" | ||
56 | 59 | ||
57 | static RESTYPE CursorClientType; | 60 | static RESTYPE CursorClientType; |
58 | static RESTYPE CursorHideCountType; | 61 | static RESTYPE CursorHideCountType; |
59 | static RESTYPE CursorWindowType; | 62 | static RESTYPE CursorWindowType; |
63 | RESTYPE PointerBarrierType; | ||
60 | static CursorPtr CursorCurrent[MAXDEVICES]; | 64 | static CursorPtr CursorCurrent[MAXDEVICES]; |
61 | 65 | ||
62 | static DevPrivateKeyRec CursorScreenPrivateKeyRec; | 66 | static DevPrivateKeyRec CursorScreenPrivateKeyRec; |
@@ -107,6 +111,14 @@ typedef struct _CursorHideCountRec { | |||
107 | XID resource; | 111 | XID resource; |
108 | } CursorHideCountRec; | 112 | } CursorHideCountRec; |
109 | 113 | ||
114 | typedef struct PointerBarrierClient *PointerBarrierClientPtr; | ||
115 | |||
116 | struct PointerBarrierClient { | ||
117 | ScreenPtr screen; | ||
118 | struct PointerBarrier barrier; | ||
119 | struct list entry; | ||
120 | }; | ||
121 | |||
110 | /* | 122 | /* |
111 | * Wrap DisplayCursor to catch cursor change events | 123 | * Wrap DisplayCursor to catch cursor change events |
112 | */ | 124 | */ |
@@ -114,7 +126,9 @@ typedef struct _CursorHideCountRec { | |||
114 | typedef struct _CursorScreen { | 126 | typedef struct _CursorScreen { |
115 | DisplayCursorProcPtr DisplayCursor; | 127 | DisplayCursorProcPtr DisplayCursor; |
116 | CloseScreenProcPtr CloseScreen; | 128 | CloseScreenProcPtr CloseScreen; |
129 | ConstrainCursorHarderProcPtr ConstrainCursorHarder; | ||
117 | CursorHideCountPtr pCursorHideCounts; | 130 | CursorHideCountPtr pCursorHideCounts; |
131 | struct list barriers; | ||
118 | } CursorScreenRec, *CursorScreenPtr; | 132 | } CursorScreenRec, *CursorScreenPtr; |
119 | 133 | ||
120 | #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey)) | 134 | #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey)) |
@@ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen) | |||
184 | Bool ret; | 198 | Bool ret; |
185 | CloseScreenProcPtr close_proc; | 199 | CloseScreenProcPtr close_proc; |
186 | DisplayCursorProcPtr display_proc; | 200 | DisplayCursorProcPtr display_proc; |
201 | ConstrainCursorHarderProcPtr constrain_proc; | ||
187 | 202 | ||
188 | Unwrap (cs, pScreen, CloseScreen, close_proc); | 203 | Unwrap (cs, pScreen, CloseScreen, close_proc); |
189 | Unwrap (cs, pScreen, DisplayCursor, display_proc); | 204 | Unwrap (cs, pScreen, DisplayCursor, display_proc); |
205 | Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc); | ||
190 | deleteCursorHideCountsForScreen(pScreen); | 206 | deleteCursorHideCountsForScreen(pScreen); |
191 | ret = (*pScreen->CloseScreen) (index, pScreen); | 207 | ret = (*pScreen->CloseScreen) (index, pScreen); |
192 | free(cs); | 208 | free(cs); |
@@ -1029,6 +1045,382 @@ CursorFreeWindow (pointer data, XID id) | |||
1029 | return 1; | 1045 | return 1; |
1030 | } | 1046 | } |
1031 | 1047 | ||
1048 | static BOOL | ||
1049 | barrier_is_horizontal(const struct PointerBarrier *barrier) | ||
1050 | { | ||
1051 | return barrier->y1 == barrier->y2; | ||
1052 | } | ||
1053 | |||
1054 | static BOOL | ||
1055 | barrier_is_vertical(const struct PointerBarrier *barrier) | ||
1056 | { | ||
1057 | return barrier->x1 == barrier->x2; | ||
1058 | } | ||
1059 | |||
1060 | /** | ||
1061 | * @return The set of barrier movement directions the movement vector | ||
1062 | * x1/y1 → x2/y2 represents. | ||
1063 | */ | ||
1064 | int | ||
1065 | barrier_get_direction(int x1, int y1, int x2, int y2) | ||
1066 | { | ||
1067 | int direction = 0; | ||
1068 | |||
1069 | /* which way are we trying to go */ | ||
1070 | if (x2 > x1) | ||
1071 | direction |= BarrierPositiveX; | ||
1072 | if (x2 < x1) | ||
1073 | direction |= BarrierNegativeX; | ||
1074 | if (y2 > y1) | ||
1075 | direction |= BarrierPositiveY; | ||
1076 | if (y2 < y1) | ||
1077 | direction |= BarrierNegativeY; | ||
1078 | |||
1079 | return direction; | ||
1080 | } | ||
1081 | |||
1082 | /** | ||
1083 | * Test if the barrier may block movement in the direction defined by | ||
1084 | * x1/y1 → x2/y2. This function only tests whether the directions could be | ||
1085 | * blocked, it does not test if the barrier actually blocks the movement. | ||
1086 | * | ||
1087 | * @return TRUE if the barrier blocks the direction of movement or FALSE | ||
1088 | * otherwise. | ||
1089 | */ | ||
1090 | BOOL | ||
1091 | barrier_is_blocking_direction(const struct PointerBarrier *barrier, int direction) | ||
1092 | { | ||
1093 | /* Barriers define which way is ok, not which way is blocking */ | ||
1094 | return (barrier->directions & direction) != direction; | ||
1095 | } | ||
1096 | |||
1097 | /** | ||
1098 | * Test if the movement vector x1/y1 → x2/y2 is intersecting with the | ||
1099 | * barrier. A movement vector with the startpoint or endpoint adjacent to | ||
1100 | * the barrier itself counts as intersecting. | ||
1101 | * | ||
1102 | * @param x1 X start coordinate of movement vector | ||
1103 | * @param y1 Y start coordinate of movement vector | ||
1104 | * @param x2 X end coordinate of movement vector | ||
1105 | * @param y2 Y end coordinate of movement vector | ||
1106 | * @param[out] distance The distance between the start point and the | ||
1107 | * intersection with the barrier (if applicable). | ||
1108 | * @return TRUE if the barrier intersects with the given vector | ||
1109 | */ | ||
1110 | BOOL | ||
1111 | barrier_is_blocking(const struct PointerBarrier *barrier, | ||
1112 | int x1, int y1, int x2, int y2, | ||
1113 | double *distance) | ||
1114 | { | ||
1115 | BOOL rc = FALSE; | ||
1116 | float ua, ub, ud; | ||
1117 | int dir = barrier_get_direction(x1, y1, x2, y2); | ||
1118 | |||
1119 | /* Algorithm below doesn't handle edge cases well, hence the extra | ||
1120 | * checks. */ | ||
1121 | if (barrier_is_vertical(barrier)) { | ||
1122 | /* handle immediate barrier adjacency, moving away */ | ||
1123 | if (dir & BarrierPositiveX && x1 == barrier->x1) | ||
1124 | return FALSE; | ||
1125 | if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1)) | ||
1126 | return FALSE; | ||
1127 | /* startpoint adjacent to barrier, moving towards -> block */ | ||
1128 | if (x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) { | ||
1129 | *distance = 0; | ||
1130 | return TRUE; | ||
1131 | } | ||
1132 | } else { | ||
1133 | /* handle immediate barrier adjacency, moving away */ | ||
1134 | if (dir & BarrierPositiveY && y1 == barrier->y1) | ||
1135 | return FALSE; | ||
1136 | if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1)) | ||
1137 | return FALSE; | ||
1138 | /* startpoint adjacent to barrier, moving towards -> block */ | ||
1139 | if (y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) { | ||
1140 | *distance = 0; | ||
1141 | return TRUE; | ||
1142 | } | ||
1143 | } | ||
1144 | |||
1145 | /* not an edge case, compute distance */ | ||
1146 | ua = 0; | ||
1147 | ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 - barrier->x1) * (y2 - y1); | ||
1148 | if (ud != 0) { | ||
1149 | ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) - | ||
1150 | (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud; | ||
1151 | ub = ((x2 - x1) * (y1 - barrier->y1) - | ||
1152 | (y2 - y1) * (x1 - barrier->x1)) / ud; | ||
1153 | if (ua < 0 || ua > 1 || ub < 0 || ub > 1) | ||
1154 | ua = 0; | ||
1155 | } | ||
1156 | |||
1157 | if (ua > 0 && ua <= 1) | ||
1158 | { | ||
1159 | double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1); | ||
1160 | double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1); | ||
1161 | |||
1162 | *distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2)); | ||
1163 | rc = TRUE; | ||
1164 | } | ||
1165 | |||
1166 | return rc; | ||
1167 | } | ||
1168 | |||
1169 | /** | ||
1170 | * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2. | ||
1171 | * | ||
1172 | * @param dir Only barriers blocking movement in direction dir are checked | ||
1173 | * @param x1 X start coordinate of movement vector | ||
1174 | * @param y1 Y start coordinate of movement vector | ||
1175 | * @param x2 X end coordinate of movement vector | ||
1176 | * @param y2 Y end coordinate of movement vector | ||
1177 | * @return The barrier nearest to the movement origin that blocks this movement. | ||
1178 | */ | ||
1179 | static struct PointerBarrier* | ||
1180 | barrier_find_nearest(CursorScreenPtr cs, int dir, | ||
1181 | int x1, int y1, int x2, int y2) | ||
1182 | { | ||
1183 | struct PointerBarrierClient *c; | ||
1184 | struct PointerBarrier *nearest = NULL; | ||
1185 | double min_distance = INT_MAX; /* can't get higher than that in X anyway */ | ||
1186 | |||
1187 | list_for_each_entry(c, &cs->barriers, entry) { | ||
1188 | struct PointerBarrier *b = &c->barrier; | ||
1189 | double distance; | ||
1190 | |||
1191 | if (!barrier_is_blocking_direction(b, dir)) | ||
1192 | continue; | ||
1193 | |||
1194 | if (barrier_is_blocking(b, x1, y1, x2, y2, &distance)) | ||
1195 | { | ||
1196 | if (min_distance > distance) | ||
1197 | { | ||
1198 | min_distance = distance; | ||
1199 | nearest = b; | ||
1200 | } | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | return nearest; | ||
1205 | } | ||
1206 | |||
1207 | /** | ||
1208 | * Clamp to the given barrier given the movement direction specified in dir. | ||
1209 | * | ||
1210 | * @param barrier The barrier to clamp to | ||
1211 | * @param dir The movement direction | ||
1212 | * @param[out] x The clamped x coordinate. | ||
1213 | * @param[out] y The clamped x coordinate. | ||
1214 | */ | ||
1215 | void | ||
1216 | barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y) | ||
1217 | { | ||
1218 | if (barrier_is_vertical(barrier)) | ||
1219 | { | ||
1220 | if ((dir & BarrierNegativeX) & ~barrier->directions) | ||
1221 | *x = barrier->x1; | ||
1222 | if ((dir & BarrierPositiveX) & ~barrier->directions) | ||
1223 | *x = barrier->x1 - 1; | ||
1224 | } | ||
1225 | if (barrier_is_horizontal(barrier)) | ||
1226 | { | ||
1227 | if ((dir & BarrierNegativeY) & ~barrier->directions) | ||
1228 | *y = barrier->y1; | ||
1229 | if ((dir & BarrierPositiveY) & ~barrier->directions) | ||
1230 | *y = barrier->y1 - 1; | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | static void | ||
1235 | CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y) | ||
1236 | { | ||
1237 | CursorScreenPtr cs = GetCursorScreen(screen); | ||
1238 | |||
1239 | if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) { | ||
1240 | int ox, oy; | ||
1241 | int dir; | ||
1242 | struct PointerBarrier *nearest = NULL; | ||
1243 | |||
1244 | /* where are we coming from */ | ||
1245 | miPointerGetPosition(dev, &ox, &oy); | ||
1246 | |||
1247 | /* How this works: | ||
1248 | * Given the origin and the movement vector, get the nearest barrier | ||
1249 | * to the origin that is blocking the movement. | ||
1250 | * Clamp to that barrier. | ||
1251 | * Then, check from the clamped intersection to the original | ||
1252 | * destination, again finding the nearest barrier and clamping. | ||
1253 | */ | ||
1254 | dir = barrier_get_direction(ox, oy, *x, *y); | ||
1255 | |||
1256 | nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); | ||
1257 | if (nearest) { | ||
1258 | barrier_clamp_to_barrier(nearest, dir, x, y); | ||
1259 | |||
1260 | if (barrier_is_vertical(nearest)) { | ||
1261 | dir &= ~(BarrierNegativeX | BarrierPositiveX); | ||
1262 | ox = *x; | ||
1263 | } else if (barrier_is_horizontal(nearest)) { | ||
1264 | dir &= ~(BarrierNegativeY | BarrierPositiveY); | ||
1265 | oy = *y; | ||
1266 | } | ||
1267 | |||
1268 | nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y); | ||
1269 | if (nearest) { | ||
1270 | barrier_clamp_to_barrier(nearest, dir, x, y); | ||
1271 | } | ||
1272 | } | ||
1273 | } | ||
1274 | |||
1275 | if (cs->ConstrainCursorHarder) { | ||
1276 | screen->ConstrainCursorHarder = cs->ConstrainCursorHarder; | ||
1277 | screen->ConstrainCursorHarder(dev, screen, mode, x, y); | ||
1278 | screen->ConstrainCursorHarder = CursorConstrainCursorHarder; | ||
1279 | } | ||
1280 | } | ||
1281 | |||
1282 | static struct PointerBarrierClient * | ||
1283 | CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client, | ||
1284 | xXFixesCreatePointerBarrierReq *stuff) | ||
1285 | { | ||
1286 | CursorScreenPtr cs = GetCursorScreen(screen); | ||
1287 | struct PointerBarrierClient *ret = malloc(sizeof(*ret)); | ||
1288 | |||
1289 | if (ret) { | ||
1290 | ret->screen = screen; | ||
1291 | ret->barrier.x1 = min(stuff->x1, stuff->x2); | ||
1292 | ret->barrier.x2 = max(stuff->x1, stuff->x2); | ||
1293 | ret->barrier.y1 = min(stuff->y1, stuff->y2); | ||
1294 | ret->barrier.y2 = max(stuff->y1, stuff->y2); | ||
1295 | ret->barrier.directions = stuff->directions & 0x0f; | ||
1296 | if (barrier_is_horizontal(&ret->barrier)) | ||
1297 | ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX); | ||
1298 | if (barrier_is_vertical(&ret->barrier)) | ||
1299 | ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY); | ||
1300 | list_add(&ret->entry, &cs->barriers); | ||
1301 | } | ||
1302 | |||
1303 | return ret; | ||
1304 | } | ||
1305 | |||
1306 | int | ||
1307 | ProcXFixesCreatePointerBarrier (ClientPtr client) | ||
1308 | { | ||
1309 | int err; | ||
1310 | WindowPtr pWin; | ||
1311 | struct PointerBarrierClient *barrier; | ||
1312 | struct PointerBarrier b; | ||
1313 | REQUEST (xXFixesCreatePointerBarrierReq); | ||
1314 | |||
1315 | REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); | ||
1316 | LEGAL_NEW_RESOURCE(stuff->barrier, client); | ||
1317 | |||
1318 | err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess); | ||
1319 | if (err != Success) { | ||
1320 | client->errorValue = stuff->window; | ||
1321 | return err; | ||
1322 | } | ||
1323 | |||
1324 | /* This sure does need fixing. */ | ||
1325 | if (stuff->num_devices) | ||
1326 | return BadImplementation; | ||
1327 | |||
1328 | b.x1 = stuff->x1; | ||
1329 | b.x2 = stuff->x2; | ||
1330 | b.y1 = stuff->y1; | ||
1331 | b.y2 = stuff->y2; | ||
1332 | |||
1333 | if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b)) | ||
1334 | return BadValue; | ||
1335 | |||
1336 | /* no 0-sized barriers */ | ||
1337 | if (barrier_is_horizontal(&b) && barrier_is_vertical(&b)) | ||
1338 | return BadValue; | ||
1339 | |||
1340 | if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen, | ||
1341 | client, stuff))) | ||
1342 | return BadAlloc; | ||
1343 | |||
1344 | if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier)) | ||
1345 | return BadAlloc; | ||
1346 | |||
1347 | return Success; | ||
1348 | } | ||
1349 | |||
1350 | int | ||
1351 | SProcXFixesCreatePointerBarrier (ClientPtr client) | ||
1352 | { | ||
1353 | int n; | ||
1354 | REQUEST(xXFixesCreatePointerBarrierReq); | ||
1355 | |||
1356 | swaps(&stuff->length, n); | ||
1357 | REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq); | ||
1358 | swapl(&stuff->barrier, n); | ||
1359 | swapl(&stuff->window, n); | ||
1360 | swaps(&stuff->x1, n); | ||
1361 | swaps(&stuff->y1, n); | ||
1362 | swaps(&stuff->x2, n); | ||
1363 | swaps(&stuff->y2, n); | ||
1364 | swapl(&stuff->directions, n); | ||
1365 | return ProcXFixesVector[stuff->xfixesReqType](client); | ||
1366 | } | ||
1367 | |||
1368 | static int | ||
1369 | CursorFreeBarrier(void *data, XID id) | ||
1370 | { | ||
1371 | struct PointerBarrierClient *b = NULL, *barrier; | ||
1372 | ScreenPtr screen; | ||
1373 | CursorScreenPtr cs; | ||
1374 | |||
1375 | barrier = container_of(data, struct PointerBarrierClient, barrier); | ||
1376 | screen = barrier->screen; | ||
1377 | cs = GetCursorScreen(screen); | ||
1378 | |||
1379 | /* find and unlink from the screen private */ | ||
1380 | list_for_each_entry(b, &cs->barriers, entry) { | ||
1381 | if (b == barrier) { | ||
1382 | list_del(&b->entry); | ||
1383 | break; | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1387 | free(barrier); | ||
1388 | return Success; | ||
1389 | } | ||
1390 | |||
1391 | int | ||
1392 | ProcXFixesDestroyPointerBarrier (ClientPtr client) | ||
1393 | { | ||
1394 | int err; | ||
1395 | void *barrier; | ||
1396 | REQUEST (xXFixesDestroyPointerBarrierReq); | ||
1397 | |||
1398 | REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); | ||
1399 | |||
1400 | err = dixLookupResourceByType((void **)&barrier, stuff->barrier, | ||
1401 | PointerBarrierType, client, | ||
1402 | DixDestroyAccess); | ||
1403 | if (err != Success) { | ||
1404 | client->errorValue = stuff->barrier; | ||
1405 | return err; | ||
1406 | } | ||
1407 | |||
1408 | FreeResource(stuff->barrier, RT_NONE); | ||
1409 | return Success; | ||
1410 | } | ||
1411 | |||
1412 | int | ||
1413 | SProcXFixesDestroyPointerBarrier (ClientPtr client) | ||
1414 | { | ||
1415 | int n; | ||
1416 | REQUEST(xXFixesDestroyPointerBarrierReq); | ||
1417 | |||
1418 | swaps(&stuff->length, n); | ||
1419 | REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq); | ||
1420 | swapl(&stuff->barrier, n); | ||
1421 | return ProcXFixesVector[stuff->xfixesReqType](client); | ||
1422 | } | ||
1423 | |||
1032 | Bool | 1424 | Bool |
1033 | XFixesCursorInit (void) | 1425 | XFixesCursorInit (void) |
1034 | { | 1426 | { |
@@ -1048,8 +1440,10 @@ XFixesCursorInit (void) | |||
1048 | cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec)); | 1440 | cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec)); |
1049 | if (!cs) | 1441 | if (!cs) |
1050 | return FALSE; | 1442 | return FALSE; |
1443 | list_init(&cs->barriers); | ||
1051 | Wrap (cs, pScreen, CloseScreen, CursorCloseScreen); | 1444 | Wrap (cs, pScreen, CloseScreen, CursorCloseScreen); |
1052 | Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); | 1445 | Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor); |
1446 | Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder); | ||
1053 | cs->pCursorHideCounts = NULL; | 1447 | cs->pCursorHideCounts = NULL; |
1054 | SetCursorScreen (pScreen, cs); | 1448 | SetCursorScreen (pScreen, cs); |
1055 | } | 1449 | } |
@@ -1059,7 +1453,10 @@ XFixesCursorInit (void) | |||
1059 | "XFixesCursorHideCount"); | 1453 | "XFixesCursorHideCount"); |
1060 | CursorWindowType = CreateNewResourceType(CursorFreeWindow, | 1454 | CursorWindowType = CreateNewResourceType(CursorFreeWindow, |
1061 | "XFixesCursorWindow"); | 1455 | "XFixesCursorWindow"); |
1456 | PointerBarrierType = CreateNewResourceType(CursorFreeBarrier, | ||
1457 | "XFixesPointerBarrier"); | ||
1062 | 1458 | ||
1063 | return CursorClientType && CursorHideCountType && CursorWindowType; | 1459 | return CursorClientType && CursorHideCountType && CursorWindowType && |
1460 | PointerBarrierType; | ||
1064 | } | 1461 | } |
1065 | 1462 | ||
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c index 54f0df341..e0ebedd80 100644 --- a/xfixes/xfixes.c +++ b/xfixes/xfixes.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | 2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |
3 | * Copyright 2010 Red Hat, Inc. | ||
3 | * | 4 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 6 | * copy of this software and associated documentation files (the "Software"), |
@@ -47,10 +48,6 @@ | |||
47 | 48 | ||
48 | #include "xfixesint.h" | 49 | #include "xfixesint.h" |
49 | #include "protocol-versions.h" | 50 | #include "protocol-versions.h" |
50 | /* | ||
51 | * Must use these instead of the constants from xfixeswire.h. They advertise | ||
52 | * what we implement, not what the protocol headers define. | ||
53 | */ | ||
54 | 51 | ||
55 | static unsigned char XFixesReqCode; | 52 | static unsigned char XFixesReqCode; |
56 | int XFixesEventBase; | 53 | int XFixesEventBase; |
@@ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client) | |||
97 | 94 | ||
98 | /* Major version controls available requests */ | 95 | /* Major version controls available requests */ |
99 | static const int version_requests[] = { | 96 | static const int version_requests[] = { |
100 | X_XFixesQueryVersion, /* before client sends QueryVersion */ | 97 | X_XFixesQueryVersion, /* before client sends QueryVersion */ |
101 | X_XFixesGetCursorImage, /* Version 1 */ | 98 | X_XFixesGetCursorImage, /* Version 1 */ |
102 | X_XFixesChangeCursorByName, /* Version 2 */ | 99 | X_XFixesChangeCursorByName, /* Version 2 */ |
103 | X_XFixesExpandRegion, /* Version 3 */ | 100 | X_XFixesExpandRegion, /* Version 3 */ |
104 | X_XFixesShowCursor, /* Version 4 */ | 101 | X_XFixesShowCursor, /* Version 4 */ |
102 | X_XFixesDestroyPointerBarrier, /* Version 5 */ | ||
105 | }; | 103 | }; |
106 | 104 | ||
107 | #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) | 105 | #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) |
@@ -142,6 +140,9 @@ int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = { | |||
142 | /*************** Version 4 ****************/ | 140 | /*************** Version 4 ****************/ |
143 | ProcXFixesHideCursor, | 141 | ProcXFixesHideCursor, |
144 | ProcXFixesShowCursor, | 142 | ProcXFixesShowCursor, |
143 | /*************** Version 5 ****************/ | ||
144 | ProcXFixesCreatePointerBarrier, | ||
145 | ProcXFixesDestroyPointerBarrier, | ||
145 | }; | 146 | }; |
146 | 147 | ||
147 | static int | 148 | static int |
@@ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = { | |||
205 | /*************** Version 4 ****************/ | 206 | /*************** Version 4 ****************/ |
206 | SProcXFixesHideCursor, | 207 | SProcXFixesHideCursor, |
207 | SProcXFixesShowCursor, | 208 | SProcXFixesShowCursor, |
209 | /*************** Version 5 ****************/ | ||
210 | SProcXFixesCreatePointerBarrier, | ||
211 | SProcXFixesDestroyPointerBarrier, | ||
208 | }; | 212 | }; |
209 | 213 | ||
210 | static int | 214 | static int |
@@ -260,6 +264,8 @@ XFixesExtensionInit(void) | |||
260 | EventSwapVector[XFixesEventBase + XFixesCursorNotify] = | 264 | EventSwapVector[XFixesEventBase + XFixesCursorNotify] = |
261 | (EventSwapPtr) SXFixesCursorNotifyEvent; | 265 | (EventSwapPtr) SXFixesCursorNotifyEvent; |
262 | SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion); | 266 | SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion); |
267 | SetResourceTypeErrorValue(PointerBarrierType, | ||
268 | XFixesErrorBase + BadBarrier); | ||
263 | } | 269 | } |
264 | } | 270 | } |
265 | 271 | ||
diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h index 1638350c2..5765e64b5 100644 --- a/xfixes/xfixes.h +++ b/xfixes/xfixes.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "resource.h" | 30 | #include "resource.h" |
31 | 31 | ||
32 | extern _X_EXPORT RESTYPE RegionResType; | 32 | extern _X_EXPORT RESTYPE RegionResType; |
33 | extern _X_EXPORT RESTYPE PointerBarrierType; | ||
33 | extern _X_EXPORT int XFixesErrorBase; | 34 | extern _X_EXPORT int XFixesErrorBase; |
34 | 35 | ||
35 | #define VERIFY_REGION(pRegion, rid, client, mode) \ | 36 | #define VERIFY_REGION(pRegion, rid, client, mode) \ |
@@ -51,5 +52,21 @@ extern _X_EXPORT int XFixesErrorBase; | |||
51 | extern _X_EXPORT RegionPtr | 52 | extern _X_EXPORT RegionPtr |
52 | XFixesRegionCopy (RegionPtr pRegion); | 53 | XFixesRegionCopy (RegionPtr pRegion); |
53 | 54 | ||
55 | struct PointerBarrier { | ||
56 | CARD16 x1, x2, y1, y2; | ||
57 | CARD32 directions; | ||
58 | }; | ||
59 | |||
60 | |||
61 | extern int | ||
62 | barrier_get_direction(int, int, int, int); | ||
63 | extern BOOL | ||
64 | barrier_is_blocking(const struct PointerBarrier*, int, int, int, int, double*); | ||
65 | extern BOOL | ||
66 | barrier_is_blocking_direction(const struct PointerBarrier*, int); | ||
67 | extern void | ||
68 | barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y); | ||
69 | |||
70 | |||
54 | 71 | ||
55 | #endif /* _XFIXES_H_ */ | 72 | #endif /* _XFIXES_H_ */ |
diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h index d00536968..6ba276e8c 100644 --- a/xfixes/xfixesint.h +++ b/xfixes/xfixesint.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. | 2 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. |
3 | * Copyright 2010 Red Hat, Inc. | ||
3 | * | 4 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 6 | * copy of this software and associated documentation files (the "Software"), |
@@ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client); | |||
278 | int | 279 | int |
279 | SProcXFixesShowCursor (ClientPtr client); | 280 | SProcXFixesShowCursor (ClientPtr client); |
280 | 281 | ||
282 | /* Version 5 */ | ||
283 | |||
284 | int | ||
285 | ProcXFixesCreatePointerBarrier (ClientPtr client); | ||
286 | |||
287 | int | ||
288 | SProcXFixesCreatePointerBarrier (ClientPtr client); | ||
289 | |||
290 | int | ||
291 | ProcXFixesDestroyPointerBarrier (ClientPtr client); | ||
292 | |||
293 | int | ||
294 | SProcXFixesDestroyPointerBarrier (ClientPtr client); | ||
295 | |||
296 | /* Xinerama */ | ||
281 | extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr); | 297 | extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr); |
282 | void PanoramiXFixesInit (void); | 298 | void PanoramiXFixesInit (void); |
283 | void PanoramiXFixesReset (void); | 299 | void PanoramiXFixesReset (void); |