[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xorg-server: Changes to 'debian-experimental'



 ChangeLog                   |   94 ++++++++++
 configure.ac                |   14 -
 debian/changelog            |    7 
 debian/control              |    4 
 debian/serverminver         |    2 
 debian/watch                |    1 
 dix/main.c                  |    2 
 include/privates.h          |    2 
 include/protocol-versions.h |    2 
 m4/xorg-tls.m4              |    6 
 test/Makefile.am            |    3 
 test/fixes.c                |  327 ++++++++++++++++++++++++++++++++++++
 xfixes/cursor.c             |  399 +++++++++++++++++++++++++++++++++++++++++++-
 xfixes/xfixes.c             |   24 +-
 xfixes/xfixes.h             |   17 +
 xfixes/xfixesint.h          |   16 +
 16 files changed, 886 insertions(+), 34 deletions(-)

New commits:
commit c437bd08fbe6d5c93f8d98c1f139d7ad8e34b413
Author: Cyril Brulebois <kibi@debian.org>
Date:   Fri Jun 3 01:25:38 2011 +0200

    Bump xutils-dev again for even newer macros.

diff --git a/debian/control b/debian/control
index cc0d83e..3ed0e07 100644
--- a/debian/control
+++ b/debian/control
@@ -17,7 +17,7 @@ Build-Depends:
  flex,
  automake,
  libtool,
- xutils-dev (>= 1:7.6+3),
+ xutils-dev (>= 1:7.6+4),
  xfonts-utils (>= 1:7.5+1),
  x11proto-bigreqs-dev (>= 1:1.1.0),
  x11proto-composite-dev (>= 1:0.4),

commit edeb8b9598c072d82d7d32eca67809b8dec103b9
Author: Cyril Brulebois <kibi@debian.org>
Date:   Fri Jun 3 01:25:34 2011 +0200

    Bump x11proto-fixes-dev build-dep for pointer barriers support.

diff --git a/debian/changelog b/debian/changelog
index 63cbca9..bec6c1b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,7 @@ xorg-server (2:1.10.99.901-1) UNRELEASED; urgency=low
   * Bump pixman build-dep/dep to 0.21.8.
   * Bump xutils-dev build-dep for new macros.
   * Drop libglib2.0-dev build-dep, no longer needed for unit tests.
+  * Bump x11proto-fixes-dev build-dep for pointer barriers support.
 
  -- Cyril Brulebois <kibi@debian.org>  Tue, 31 May 2011 13:52:04 +0200
 
diff --git a/debian/control b/debian/control
index 678362f..cc0d83e 100644
--- a/debian/control
+++ b/debian/control
@@ -23,7 +23,7 @@ Build-Depends:
  x11proto-composite-dev (>= 1:0.4),
  x11proto-core-dev (>= 7.0.17),
  x11proto-damage-dev (>= 1.1),
- x11proto-fixes-dev (>= 1:4.1),
+ x11proto-fixes-dev (>= 1:5.0),
  x11proto-kb-dev (>= 1.0.3),
  x11proto-xinerama-dev,
  x11proto-randr-dev (>= 1.2.99.3),

commit c6d66c12cf11ccd736aa05f1dbf963084e95bc00
Author: Cyril Brulebois <kibi@debian.org>
Date:   Fri Jun 3 01:25:28 2011 +0200

    Update serverminver accordingly.

diff --git a/debian/serverminver b/debian/serverminver
index 01f0694..5580dc9 100644
--- a/debian/serverminver
+++ b/debian/serverminver
@@ -1,3 +1,3 @@
-2:1.10.99.1
+2:1.10.99.901
 ABI_VIDEODRV_VERSION:11.0
 ABI_XINPUT_VERSION:13.0

commit bea957121f69b452f73a4a2873d25f344bda4d21
Author: Cyril Brulebois <kibi@debian.org>
Date:   Fri Jun 3 01:11:50 2011 +0200

    Bump changelogs.

diff --git a/ChangeLog b/ChangeLog
index 3a4c7bc..b7df3cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,81 @@
+commit db228d3d07a6d831f53e4c05c878327ad4d045eb
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Jun 1 11:20:10 2011 -0700
+
+    Version bumped to 1.10.99.901 (1.11 RC1)
+    
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0643c056512d10be8db223d18d6563292d57e916
+Merge: a2e6cfc d45f5b2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 31 23:45:07 2011 -0700
+
+    Merge remote-tracking branch 'ajax/xserver-next'
+
+commit a2e6cfc18aec1c0027b51572b03ec9f2ab074b56
+Merge: bc04065 8d84fd2
+Author: Keith Packard <keithp@keithp.com>
+Date:   Tue May 31 23:42:52 2011 -0700
+
+    Merge remote-tracking branch 'sandmann/for-keithp'
+
+commit d45f5b2493bc0a2882bf972849b5c9c50cd533ca
+Author: Adam Jackson <ajax@redhat.com>
+Date:   Wed May 25 05:54:35 2011 -0400
+
+    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>
+
+commit bc04065b5ce277f3ac3491ff221a60ef3c7605cf
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Fri May 20 19:24:34 2011 -0700
+
+    "privates.h", line 198: warning: void function cannot return value
+    
+    Providing an argument to return in a function with void return type
+    is not allowed by the C standard, and makes the Sun compilers unhappy.
+    (They actually flag it as an error, unless using a new enough version
+     to be able to downgrade it to a warning with "-features=extensions".)
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+    Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+    Reviewed-by: Daniel Stone <daniel@fooishbar.org>
+    Reviewed-by: Cyril Brulebois <kibi@debian.org>
+
+commit eadf5021794782fde861d471ed408675f4926b89
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Mon May 2 19:48:42 2011 -0700
+
+    Use XORG_STRICT_OPTION from util-macros 1.14 to set -Werror flags
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+    Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+
+commit 9275b1fb6f82a6971c4177ddd3d5a859a8f24119
+Author: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date:   Mon May 2 19:47:44 2011 -0700
+
+    Use XORG_COMPILER_BRAND from util-macros 1.14 to check for SUNCC
+    
+    Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
+
 commit 4621bb270a36d35d4ab67f1d7fb47674683dfc5b
 Author: Peter Hutterer <peter.hutterer@who-t.net>
 Date:   Wed May 18 15:00:54 2011 +1000
@@ -26,6 +104,22 @@ Date:   Mon Jan 31 14:43:01 2011 +1000
     Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
     Acked-by: Dan Nicholson <dbn.lists@gmail.com>
 
+commit 8d84fd2566f8466b6152724df7eefc73780df093
+Author: Søren Sandmann Pedersen <ssp@redhat.com>
+Date:   Wed May 25 12:14:05 2011 -0400
+
+    Don't call pixman_disable_out_of_bounds_workaround() anymore
+    
+    Pixman used to have a workaround for a bug in old X servers, and this
+    function was used to disable that workaround in servers known to be
+    fixed.
+    
+    Since 0.22, which the X server depends on, the workaround doesn't
+    exist anymore, so there is no point disabling it.
+    
+    Reviewed-by: Cyril Brulebois <kibi at debian.org>
+    Signed-off-by: Soren Sandmann <sandmann@cs.au.dk>
+
 commit b6c7b9b2f39e970cedb6bc1e073f901e28cb0fa3
 Author: Aaron Plattner <aplattner@nvidia.com>
 Date:   Tue May 24 16:02:42 2011 -0700
diff --git a/debian/changelog b/debian/changelog
index 5ab7974..63cbca9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,6 @@
-xorg-server (2:1.10.99.1-1) UNRELEASED; urgency=low
+xorg-server (2:1.10.99.901-1) UNRELEASED; urgency=low
 
-  * New upstream snapshot. The version string is Debian-specific, and
-    should sort nicely before 1.10.99.901, which should be the first
-    release candidate for 1.11.
+  * New upstream release candidate.
   * Bump serverminver, as well as input and video ABI.
   * Adapt 15-nouveau.diff to cope with the glxdricommon-ification of
     GLX probing. Nouveau users might still see an error (EE) mentioning

commit 9226b6058c5501c43ad711ce7131e17af306d5f3
Author: Cyril Brulebois <kibi@debian.org>
Date:   Fri Jun 3 01:07:25 2011 +0200

    Mention git URL in a comment.

diff --git a/debian/watch b/debian/watch
index 249555d..60a37d4 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,2 +1,3 @@
+#git=git://anongit.freedesktop.org/xorg/xserver
 version=3
 http://xorg.freedesktop.org/releases/individual/xserver/ xorg-server-(.*)\.tar\.gz

commit db228d3d07a6d831f53e4c05c878327ad4d045eb
Author: Keith Packard <keithp@keithp.com>
Date:   Wed Jun 1 11:20:10 2011 -0700

    Version bumped to 1.10.99.901 (1.11 RC1)
    
    Signed-off-by: Keith Packard <keithp@keithp.com>

diff --git a/configure.ac b/configure.ac
index fcb8ea9..22566c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,8 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([xorg-server], 1.10.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="unreleased"
+AC_INIT([xorg-server], 1.10.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2011-06-01"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE

commit d45f5b2493bc0a2882bf972849b5c9c50cd533ca
Author: Adam Jackson <ajax@redhat.com>
Date:   Wed May 25 05:54:35 2011 -0400

    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>

diff --git a/configure.ac b/configure.ac
index 655c0e4..ba1d176 100644
--- a/configure.ac
+++ b/configure.ac
@@ -810,7 +810,7 @@ dnl specific modules against it
 PKG_CHECK_MODULES(PIXMAN, $LIBPIXMAN)
 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 &&
  { 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 8692ded..7b7a9f5 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -122,7 +122,7 @@
 #define SERVER_XF86VIDMODE_MINOR_VERSION	2
 
 /* Fixes */
-#define SERVER_XFIXES_MAJOR_VERSION		4
+#define SERVER_XFIXES_MAJOR_VERSION		5
 #define SERVER_XFIXES_MINOR_VERSION		0
 
 /* X Input */
diff --git a/test/Makefile.am b/test/Makefile.am
index b7ee070..5574e7d 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 0000000..8c804ba
--- /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;
+}
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index fb608f6..01eb70d 100644
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -1,5 +1,6 @@
 /*
  * 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
  * copy of this software and associated documentation files (the "Software"),
@@ -50,13 +51,16 @@
 #include "cursorstr.h"
 #include "dixevents.h"
 #include "servermd.h"
+#include "mipointer.h"
 #include "inputstr.h"
 #include "windowstr.h"
 #include "xace.h"
+#include "list.h"
 
 static RESTYPE		CursorClientType;
 static RESTYPE		CursorHideCountType;
 static RESTYPE		CursorWindowType;
+RESTYPE			PointerBarrierType;
 static CursorPtr	CursorCurrent[MAXDEVICES];
 
 static DevPrivateKeyRec CursorScreenPrivateKeyRec;
@@ -107,6 +111,14 @@ typedef struct _CursorHideCountRec {
     XID			 resource;
 } CursorHideCountRec;
 
+typedef struct PointerBarrierClient *PointerBarrierClientPtr;
+
+struct PointerBarrierClient {
+    ScreenPtr screen;
+    struct PointerBarrier barrier;
+    struct list entry;
+};
+
 /*
  * Wrap DisplayCursor to catch cursor change events
  */
@@ -114,7 +126,9 @@ typedef struct _CursorHideCountRec {
 typedef struct _CursorScreen {
     DisplayCursorProcPtr	DisplayCursor;
     CloseScreenProcPtr		CloseScreen;
+    ConstrainCursorHarderProcPtr ConstrainCursorHarder;
     CursorHideCountPtr          pCursorHideCounts;
+    struct list                 barriers;
 } CursorScreenRec, *CursorScreenPtr;
 
 #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
@@ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen)
     Bool		ret;
     CloseScreenProcPtr	close_proc;
     DisplayCursorProcPtr display_proc;
+    ConstrainCursorHarderProcPtr constrain_proc;
 
     Unwrap (cs, pScreen, CloseScreen, close_proc);
     Unwrap (cs, pScreen, DisplayCursor, display_proc);
+    Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc);
     deleteCursorHideCountsForScreen(pScreen);
     ret = (*pScreen->CloseScreen) (index, pScreen);
     free(cs);
@@ -1029,6 +1045,382 @@ CursorFreeWindow (pointer data, XID id)
     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;


Reply to: