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

xorg-server: Changes to 'ubuntu'



 debian/changelog                                   |   13 
 debian/patches/500_pointer_barrier_thresholds.diff | 1231 +++++++++++++++++++--
 2 files changed, 1175 insertions(+), 69 deletions(-)

New commits:
commit 1aeebd5760baafc1bb6d6ac05b538a6fb45e42ae
Author: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Date:   Fri Mar 2 09:05:17 2012 +1100

    Multiple additions to pointer-barrier patch:
    
    *) Add build-time tests for pointer barrier behaviour
    *) Fix barrier corners incorrectly allowing the pointer through
    *) Fix barrier notify events being sent from the SIGIO context (LP: 946954)
    *) Add new build-depends for pointer barrier tests

diff --git a/debian/changelog b/debian/changelog
index 1fbc21e..f238360 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+xorg-server (2:1.11.4-0ubuntu5) UNRELEASED; urgency=low
+
+  * debian/patches/500_pointer_barrier_thresholds.diff:
+    - Don't try to send events from the context of the SIGIO handler.  That
+      leads to the dark side, or at least to server freezes when trying to
+      reveal the launcher in Unity (LP: #946954)
+    - Add build-time tests to make check for barrier behaviour.
+  * debian/control:
+    - Add xserver-xorg-video-dummy, libxtst-dev, libgtest-dev, and
+      libxorg-gtest-dev to build-depends for new tests.
+
+ -- Christopher James Halse Rogers <raof@ubuntu.com>  Tue, 06 Mar 2012 17:41:20 +1100
+
 xorg-server (2:1.11.4-0ubuntu4) precise; urgency=low
 
   * debian/patches/500_pointer_barrier_thresholds.diff:
diff --git a/debian/control b/debian/control
index 7da92bf..731617b 100644
--- a/debian/control
+++ b/debian/control
@@ -78,6 +78,10 @@ Build-Depends:
 # unit tests
  xkb-data,
  x11-xkb-utils,
+ libxtst-dev,
+ xserver-xorg-video-dummy,
+ libgtest-dev,
+ libxorg-gtest-dev,
 Standards-Version: 3.9.2
 Vcs-Git: git://git.debian.org/git/pkg-xorg/xserver/xorg-server
 Vcs-Browser: http://git.debian.org/?p=pkg-xorg/xserver/xorg-server.git
diff --git a/debian/patches/500_pointer_barrier_thresholds.diff b/debian/patches/500_pointer_barrier_thresholds.diff
index aeb983f..9e255ad 100644
--- a/debian/patches/500_pointer_barrier_thresholds.diff
+++ b/debian/patches/500_pointer_barrier_thresholds.diff
@@ -1,7 +1,7 @@
 Index: xorg-server/include/protocol-versions.h
 ===================================================================
---- xorg-server.orig/include/protocol-versions.h	2012-02-29 14:01:49.926067501 +1100
-+++ xorg-server/include/protocol-versions.h	2012-02-29 14:02:32.866067406 +1100
+--- xorg-server.orig/include/protocol-versions.h	2012-03-07 22:24:45.540697115 +1100
++++ xorg-server/include/protocol-versions.h	2012-03-08 07:40:35.472111389 +1100
 @@ -122,7 +122,7 @@
  #define SERVER_XF86VIDMODE_MINOR_VERSION	2
  
@@ -13,8 +13,8 @@ Index: xorg-server/include/protocol-versions.h
  /* X Input */
 Index: xorg-server/xfixes/cursor.c
 ===================================================================
---- xorg-server.orig/xfixes/cursor.c	2012-02-29 14:01:49.934067502 +1100
-+++ xorg-server/xfixes/cursor.c	2012-02-29 14:02:32.870067406 +1100
+--- xorg-server.orig/xfixes/cursor.c	2012-03-07 22:24:45.580697117 +1100
++++ xorg-server/xfixes/cursor.c	2012-03-08 11:00:53.155469738 +1100
 @@ -61,6 +61,7 @@
  static RESTYPE		CursorHideCountType;
  static RESTYPE		CursorWindowType;
@@ -43,38 +43,119 @@ Index: xorg-server/xfixes/cursor.c
  } CursorScreenRec, *CursorScreenPtr;
  
  #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
-@@ -1232,18 +1239,90 @@
+@@ -1118,7 +1125,8 @@
+ 
+     /* Algorithm below doesn't handle edge cases well, hence the extra
+      * checks. */
+-    if (barrier_is_vertical(barrier)) {
++    if (barrier_is_vertical(barrier) &&
++	(dir & (BarrierPositiveX | BarrierNegativeX))) {
+ 	/* handle immediate barrier adjacency, moving away */
+ 	if (dir & BarrierPositiveX && x1 == barrier->x1)
+ 	    return FALSE;
+@@ -1129,7 +1137,8 @@
+ 	    *distance = 0;
+ 	    return TRUE;
+ 	}
+-    } else {
++    } else if (barrier_is_horizontal(barrier) &&
++		(dir & (BarrierPositiveY | BarrierNegativeY))){
+ 	/* handle immediate barrier adjacency, moving away */
+ 	if (dir & BarrierPositiveY && y1 == barrier->y1)
+ 	    return FALSE;
+@@ -1231,6 +1240,127 @@
+     }
  }
  
- static void
-+SendBarrierEvent(CursorScreenPtr cs, struct PointerBarrier *barrier,
-+		 int x, int y, int velocity, Bool threshold_exceeded)
++/*
++ * ConstrainCursorHarder is called from the SIGIO context.
++ * This means we cannot safely send a client event from anything in
++ * CursorConstrainCursorHarder's callgraph.
++ *
++ * Allocate a set of WorkQueue items to use.
++ */
++
++struct BarrierEventStore {
++    WorkQueueRec wq_item;
++    xXFixesBarrierNotifyEvent ev;
++    Bool in_use;
++};
++
++/* Let's guess that 100 events is enough of a buffer. */
++#define BARRIER_EVENT_QUEUE_SIZE 100
++struct BarrierEventStore barrierEventQueue[BARRIER_EVENT_QUEUE_SIZE];
++
++static void
++CursorWorkQueueDestroyProc (WorkQueuePtr this)
++{
++    struct BarrierEventStore *store;
++    store = container_of (this, struct BarrierEventStore, wq_item);
++
++    store->in_use = FALSE;
++}
++
++static Bool
++CursorSendBarrierEvent (ClientPtr client, pointer eventStore)
++{
++    struct BarrierEventStore *store = (struct BarrierEventStore *)eventStore;
++    WriteEventsToClient (client, 1, (xEvent *)&store->ev);
++
++    return TRUE;
++}
++
++static struct BarrierEventStore *
++CursorFindFreeEventStore (void)
++{
++    for (int i = 0; i < BARRIER_EVENT_QUEUE_SIZE; ++i) {
++	if (!barrierEventQueue[i].in_use) {
++	    return &barrierEventQueue[i];
++	}
++    }
++    return NULL;
++}
++
++static void
++QueueBarrierEvent(CursorScreenPtr cs, struct PointerBarrier *barrier,
++		  int x, int y, int velocity, Bool threshold_exceeded)
 +{
 +    PointerBarrierEventClientPtr client;
++    struct BarrierEventStore *store;
 +    list_for_each_entry(client, &cs->barrierClients, entry) {
-+	xXFixesBarrierNotifyEvent	ev;
-+	ev.type = XFixesEventBase + XFixesBarrierNotify;
-+	ev.subtype = threshold_exceeded ? XFixesBarrierThresholdExceededNotify :
-+					  XFixesBarrierHitNotify;
-+	ev.event_id = barrier->barrierEventID;
-+	ev.barrier = barrier->barrier;
-+	ev.x = x;
-+	ev.y = y;
-+	ev.velocity = velocity;
-+	ev.timestamp = currentTime.milliseconds;
++	store = CursorFindFreeEventStore ();
++	if (store == NULL) {
++	    ErrorF ("[xfixes] Barrier event queue full.  Dropping further events\n");
++	    return;
++	}
++
++	store->in_use = TRUE;
++
++	store->ev.type = XFixesEventBase + XFixesBarrierNotify;
++	store->ev.subtype = threshold_exceeded ? XFixesBarrierThresholdExceededNotify :
++					         XFixesBarrierHitNotify;
++	store->ev.event_id = barrier->barrierEventID;
++	store->ev.barrier = barrier->barrier;
++	store->ev.x = x;
++	store->ev.y = y;
++	store->ev.velocity = velocity;
++	store->ev.timestamp = currentTime.milliseconds;
 +
 +	if (client->client->swapped) {
 +	    int n;
 +
-+	    swapl(&ev.event_id, n);
-+	    swapl(&ev.barrier, n);
-+	    swaps(&ev.x, n);
-+	    swaps(&ev.y, n);
-+	    swapl(&ev.velocity, n);
-+	    swapl(&ev.timestamp, n);
++	    swapl(&store->ev.event_id, n);
++	    swapl(&store->ev.barrier, n);
++	    swaps(&store->ev.x, n);
++	    swaps(&store->ev.y, n);
++	    swapl(&store->ev.velocity, n);
++	    swapl(&store->ev.timestamp, n);
 +	}
-+	
-+	WriteEventsToClient (client->client, 1, (xEvent *) &ev);
++
++	store->wq_item.function = CursorSendBarrierEvent;
++	store->wq_item.client = client->client;
++	store->wq_item.closure = store;
++	store->wq_item.destroyProc = CursorWorkQueueDestroyProc;
++
++	QueueWorkItem (&store->wq_item); 
 +    }
 +}
 +
@@ -104,13 +185,13 @@ Index: xorg-server/xfixes/cursor.c
 +    *vel_x = abs(dx) * 1000.0 / dt;
 +    *vel_y = abs(dy) * 1000.0 / dt;
 +
-+    last_timestamp = timestamp;  
++    last_timestamp = timestamp;
 +}
 +
-+static void
+ static void
  CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
  {
-     CursorScreenPtr cs = GetCursorScreen(screen);
+@@ -1238,12 +1368,23 @@
  
      if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
  	int ox, oy;
@@ -134,7 +215,7 @@ Index: xorg-server/xfixes/cursor.c
  	/* How this works:
  	 * Given the origin and the movement vector, get the nearest barrier
  	 * to the origin that is blocking the movement.
-@@ -1251,12 +1330,28 @@
+@@ -1251,11 +1392,27 @@
  	 * Then, check from the clamped intersection to the original
  	 * destination, again finding the nearest barrier and clamping.
  	 */
@@ -160,13 +241,12 @@ Index: xorg-server/xfixes/cursor.c
 +		barrier_clamp_to_barrier(nearest, dir, x, y);
 +		nearest->hit = TRUE;
 +	    }
++
++	    QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
  
-+	    SendBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
-+		
  	    if (barrier_is_vertical(nearest)) {
  		dir &= ~(BarrierNegativeX | BarrierPositiveX);
- 		ox = *x;
-@@ -1265,11 +1360,31 @@
+@@ -1265,11 +1422,31 @@
  		oy = *y;
  	    }
  
@@ -189,7 +269,7 @@ Index: xorg-server/xfixes/cursor.c
 +		    nearest->hit = TRUE;
 +		}
 +
-+		SendBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
++		QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
  	    }
  	}
 +
@@ -200,7 +280,7 @@ Index: xorg-server/xfixes/cursor.c
      }
  
      if (cs->ConstrainCursorHarder) {
-@@ -1284,15 +1399,45 @@
+@@ -1284,15 +1461,45 @@
  			   xXFixesCreatePointerBarrierReq *stuff)
  {
      CursorScreenPtr cs = GetCursorScreen(screen);
@@ -247,7 +327,7 @@ Index: xorg-server/xfixes/cursor.c
  	if (barrier_is_horizontal(&ret->barrier))
  	    ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
  	if (barrier_is_vertical(&ret->barrier))
-@@ -1365,6 +1510,69 @@
+@@ -1365,6 +1572,69 @@
      return ProcXFixesVector[stuff->xfixesReqType](client);
  }
  
@@ -317,7 +397,7 @@ Index: xorg-server/xfixes/cursor.c
  static int
  CursorFreeBarrier(void *data, XID id)
  {
-@@ -1421,6 +1629,118 @@
+@@ -1421,6 +1691,118 @@
      return ProcXFixesVector[stuff->xfixesReqType](client);
  }
  
@@ -352,7 +432,7 @@ Index: xorg-server/xfixes/cursor.c
 +	ret->client = client;
 +	ret->eventMask = stuff->eventMask;
 +	ret->window = stuff->window;
-+	ret->resource = FakeClientID (client->index);      
++	ret->resource = FakeClientID (client->index);
 +      list_add(&ret->entry, &cs->barrierClients);
 +    }
 +
@@ -382,7 +462,7 @@ Index: xorg-server/xfixes/cursor.c
 +
 +    if (!AddResource (eventClient->resource, PointerBarrierClientType, eventClient))
 +      return BadAlloc;
-+    
++
 +    return Success;
 +}
 +
@@ -416,7 +496,7 @@ Index: xorg-server/xfixes/cursor.c
 +    }
 +
 +    barrier->releaseEventID = stuff->event_id;
-+    
++
 +    return Success;
 +}
 +
@@ -436,7 +516,7 @@ Index: xorg-server/xfixes/cursor.c
  Bool
  XFixesCursorInit (void)
  {
-@@ -1441,6 +1761,7 @@
+@@ -1441,6 +1823,7 @@
  	if (!cs)
  	    return FALSE;
  	list_init(&cs->barriers);
@@ -444,7 +524,7 @@ Index: xorg-server/xfixes/cursor.c
  	Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
  	Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
  	Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
-@@ -1455,8 +1776,10 @@
+@@ -1455,8 +1838,10 @@
  					     "XFixesCursorWindow");
      PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
  					      "XFixesPointerBarrier");
@@ -458,8 +538,8 @@ Index: xorg-server/xfixes/cursor.c
  
 Index: xorg-server/xfixes/xfixes.c
 ===================================================================
---- xorg-server.orig/xfixes/xfixes.c	2012-02-29 14:01:49.946067501 +1100
-+++ xorg-server/xfixes/xfixes.c	2012-02-29 14:02:32.870067406 +1100
+--- xorg-server.orig/xfixes/xfixes.c	2012-03-07 22:24:45.592697117 +1100
++++ xorg-server/xfixes/xfixes.c	2012-03-08 07:40:35.480111388 +1100
 @@ -100,6 +100,7 @@
      X_XFixesExpandRegion,	    /* Version 3 */
      X_XFixesShowCursor,		    /* Version 4 */
@@ -492,8 +572,8 @@ Index: xorg-server/xfixes/xfixes.c
  static int
 Index: xorg-server/xfixes/xfixes.h
 ===================================================================
---- xorg-server.orig/xfixes/xfixes.h	2012-02-29 14:01:49.958067501 +1100
-+++ xorg-server/xfixes/xfixes.h	2012-02-29 14:02:32.870067406 +1100
+--- xorg-server.orig/xfixes/xfixes.h	2012-03-07 22:24:45.608697118 +1100
++++ xorg-server/xfixes/xfixes.h	2012-03-08 07:40:35.480111388 +1100
 @@ -28,6 +28,7 @@
  #define _XFIXES_H_
  
@@ -502,7 +582,7 @@ Index: xorg-server/xfixes/xfixes.h
  
  extern _X_EXPORT RESTYPE RegionResType;
  extern _X_EXPORT RESTYPE PointerBarrierType;
-@@ -52,9 +53,27 @@
+@@ -52,9 +53,25 @@
  extern _X_EXPORT RegionPtr
  XFixesRegionCopy (RegionPtr pRegion);
  
@@ -517,8 +597,6 @@ Index: xorg-server/xfixes/xfixes.h
 +    struct list entry;
 +};
 +
-+  
-+
  struct PointerBarrier {
 +    XID    barrier;
      CARD16 x1, x2, y1, y2;
@@ -532,8 +610,8 @@ Index: xorg-server/xfixes/xfixes.h
  
 Index: xorg-server/xfixes/xfixesint.h
 ===================================================================
---- xorg-server.orig/xfixes/xfixesint.h	2012-02-29 14:01:49.966067502 +1100
-+++ xorg-server/xfixes/xfixesint.h	2012-02-29 14:02:32.870067406 +1100
+--- xorg-server.orig/xfixes/xfixesint.h	2012-03-07 22:24:45.616697118 +1100
++++ xorg-server/xfixes/xfixesint.h	2012-03-08 07:40:35.480111388 +1100
 @@ -59,6 +59,7 @@
  #include "windowstr.h"
  #include "selection.h"
@@ -571,8 +649,8 @@ Index: xorg-server/xfixes/xfixesint.h
  void PanoramiXFixesInit (void);
 Index: xorg-server/dix/getevents.c
 ===================================================================
---- xorg-server.orig/dix/getevents.c	2012-02-29 14:01:49.974067501 +1100
-+++ xorg-server/dix/getevents.c	2012-02-29 14:02:32.874067406 +1100
+--- xorg-server.orig/dix/getevents.c	2012-03-07 22:24:45.624697119 +1100
++++ xorg-server/dix/getevents.c	2012-03-08 11:02:31.739464474 +1100
 @@ -79,6 +79,12 @@
  InternalEvent* InputEventList = NULL;
  
@@ -590,7 +668,7 @@ Index: xorg-server/dix/getevents.c
      /* miPointerSetPosition takes care of crossing screens for us, as well as
       * clipping to the current screen. Coordinates returned are in desktop
       * coord system */
-+    /** 
++    /**
 +     * Hack to pass the unclipped values through to the pointer barrier code.
 +     * Required (for now) to calculate the velocity.
 +     */
@@ -605,8 +683,8 @@ Index: xorg-server/dix/getevents.c
 Index: xorg-server/test/gtest/xfixes_barriers.cpp
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ xorg-server/test/gtest/xfixes_barriers.cpp	2012-02-29 14:02:32.874067406 +1100
-@@ -0,0 +1,362 @@
++++ xorg-server/test/gtest/xfixes_barriers.cpp	2012-03-08 07:42:49.188104249 +1100
+@@ -0,0 +1,828 @@
 +/*
 +
 +Copyright (c) 2012, Canonical Ltd
@@ -632,6 +710,7 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +*/
 +
 +#include <iostream>
++#include <sys/time.h>
 +#include <unistd.h>
 +#include <gtest/gtest.h>
 +#include <xorg/gtest/test.h>
@@ -645,7 +724,7 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +{
 +    ::testing::InitGoogleTest (&argc, argv);
 +    xorg::testing::Environment* environment = new xorg::testing::Environment ();
-+    environment->set_conf_file ("dummy.conf");
++    environment->set_conf_file (XORG_DUMMY_CONF);
 +    environment->set_server (XORG_BINARY);
 +    testing::AddGlobalTestEnvironment (environment);
 +    return RUN_ALL_TESTS ();
@@ -655,6 +734,10 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +    public:
 +    ::Display *dpy;
 +    static XErrorEvent *lastError;
++    int xtest_eventbase;
++    int xtest_errorbase;
++    int fixes_eventbase;
++    int fixes_errorbase;
 +
 +    void AssertPointerPosition (int expected_x, int expected_y)
 +    {
@@ -665,9 +748,31 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +        XQueryPointer (Display (), DefaultRootWindow (Display ()),
 +                       &unused_win, &unused_win, &x, &y,
 +                       &unused_int, &unused_int, &unused_uint);
-+        
-+        ASSERT_EQ (expected_x, x);
-+        ASSERT_EQ (expected_y, y);
++
++        ASSERT_TRUE (x == expected_x && y == expected_y) <<
++            "Incorrect pointer position: Expected ("<<
++            expected_x<< ", "<<expected_y<<"), got "<<
++            "("<<x<<", "<<y<<")\n";
++    }
++
++    bool WaitForXEvent (int msTimeout = 1000)
++    {
++        fd_set fds;
++        int xfd = ConnectionNumber (Display ());
++        struct timeval tv;
++        int retval;
++
++        FD_ZERO (&fds);
++        FD_SET (xfd, &fds);
++
++        tv.tv_sec = msTimeout / 1000;
++        tv.tv_usec = (msTimeout % 1000) * 1000;
++
++        retval = select (xfd + 1, &fds, NULL, NULL, &tv);
++
++        EXPECT_NE (-1, retval)<<"Error waiting for X event";
++
++        return retval;
 +    }
 +
 +    protected:
@@ -701,12 +806,7 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +    {
 +        memcpy (lastError, error, sizeof (*lastError));
 +        return 0;
-+    } 
-+    
-+    int xtest_eventbase;
-+    int xtest_errorbase;
-+    int fixes_eventbase;
-+    int fixes_errorbase;
++    }
 +};
 +
 +XErrorEvent *BarrierTest::lastError = NULL;
@@ -735,244 +835,688 @@ Index: xorg-server/test/gtest/xfixes_barriers.cpp
 +
 +TEST_F (BarrierTest, CreateNonAxisAlignedBarrierFails)
 +{
-+    PointerBarrier barrier;
-+    
-+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
-+                                          0, 0,
-+                                          100, 100,
-+                                          0,
-+                                          0, NULL);
++    XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
++                                0, 0,
++                                100, 100,
++                                0,
++                                0, NULL);
 +    XSync (Display (), false);
 +    ASSERT_EQ(BadValue, lastError->error_code);
 +}
-+ 
++
 +TEST_F (BarrierTest, VerticalBidirectionalBarrierBlocksRelativeMotion)
 +{
-+    PointerBarrier barrier;
-+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                          100, 0,
-+                                          100, 300,
-+                                          0,
-+                                          0, NULL);
-+    // Absolute event will ignore barrier
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 100, 0);
++                          x, y, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
 +    // Relative motion should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), -200, 0, 0);
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (100, 100));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y));
 +}
 +
 +TEST_F (BarrierTest, VerticalPositiveXBarrierBlocksMotion)
 +{
-+    PointerBarrier positiveXBarrier;
-+    positiveXBarrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                                   100, 0,
-+                                                   100, 300,
-+                                                   BarrierPositiveX,
-+                                                   0, NULL);
-+    // Absolute event will ignore barrier
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierPositiveX, 0, NULL);
++    int x = 200, y = 100, dx = -200, dy = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 100, 0);
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
-+    
 +    // Relative motion in -ve X direction should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), -200, 0, 0);
-+    
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (100, 100));
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
 +
-+    // Absolute event will ignore barrier
++    x = 0, y = 100, dx = 200, dy = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          0, 100, 0);
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (0, 100));
-+                          
 +    // Relative motion in +ve X direction should ignore barrier
-+    XTestFakeRelativeMotionEvent (Display (), 200, 0, 0);
-+    
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
 +}
 +
 +TEST_F (BarrierTest, VerticalNegativeXBarrierBlocksMotion)
 +{
-+    PointerBarrier positiveXBarrier;
-+    positiveXBarrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                                   100, 0,
-+                                                   100, 300,
-+                                                   BarrierNegativeX,
-+                                                   0, NULL);
-+    // Absolute event will ignore barrier
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierNegativeX,
++                                0, NULL);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 100, 0);
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
-+    
 +    // Relative motion in -ve X direction should ignore barrier
-+    XTestFakeRelativeMotionEvent (Display (), -200, 0, 0);
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = 0, y = 100, dx = 200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (0, 100));
-+                          
 +    // Relative motion in +ve X direction should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), 200, 0, 0);
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (99, 100));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
 +}
 +
 +TEST_F (BarrierTest, HorizontalBidirectionalBarrierBlocksRelativeMotion)
 +{
-+    PointerBarrier barrier;
-+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                          0,   100,
-+                                          300, 100,
-+                                          0,
-+                                          0, NULL);
-+    // Absolute event will ignore barrier
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                0, 0, NULL);
++
++    int x = 200, y = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 200, 0);
++                          x, y, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 200));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    // Relative motion should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, -200, 0);
++    // Relative motion in +ve Y direction should block on barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
 +
-+    // Absolute event will ignore barrier
++    x = 100, y = 200;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 0, 0);
++                          x, y, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 0));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    // Relative motion should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, 200, 0);
++    // Relative motion in -ve Y direction should block on barrier
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 99));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
 +}
 +
 +TEST_F (BarrierTest, HorizontalPositiveYBarrierBlocksMotion)
 +{
-+    PointerBarrier positiveXBarrier;
-+    positiveXBarrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                                   0,   100,
-+                                                   300, 100,
-+                                                   BarrierPositiveY,
-+                                                   0, NULL);
-+    // Absolute event will ignore barrier
-+    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 200, 0);
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                BarrierPositiveY, 0, NULL);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 200));
-+    
-+    // Relative motion in -ve Y direction should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, -200, 0);
++    int x = 200, y = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    // Relative motion in +ve Y direction should ignore barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
 +
-+    // Absolute event will ignore barrier
++    x = 100, y = 200;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          100, 0, 0);
++                          x, y, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (100, 0));
-+                          
-+    // Relative motion in +ve X direction should ignore barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, 200, 0);
-+    
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (100, 200));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve Y direction should block on barrier
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
 +}
 +
 +TEST_F (BarrierTest, HorizontalNegativeYBarrierBlocksMotion)
 +{
-+    PointerBarrier positiveXBarrier;
-+    positiveXBarrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                                   0,   100,
-+                                                   300, 100,
-+                                                   BarrierNegativeY,
-+                                                   0, NULL);
-+    // Absolute event will ignore barrier
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                BarrierNegativeY, 0, NULL);
++
++    int x = 200, y = 0;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 200, 0);
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve Y direction should block on barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = 100, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 200));
-+    
 +    // Relative motion in -ve Y direction should ignore barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, -200, 0);
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 0));
-+                          
-+    // Relative motion in +ve Y direction should block on barrier
-+    XTestFakeRelativeMotionEvent (Display (), 0, 200, 0);
-+    
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 99));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
 +}
 +
 +TEST_F (BarrierTest, DestroyPointerBarrierSucceeds)
 +{
++    int barrier_x = 100;
 +    PointerBarrier barrier;
-+    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                          100, 0,
-+                                          100, 300,
-+                                          0,
-+                                          0, NULL);
++    barrier = XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                          barrier_x, 0,
++                                          barrier_x, 300,
++                                          0, 0, NULL);
 +
-+    XFixesDestroyPointerBarrier (Display (), barrier);
-+    // Absolute event will ignore barrier
++    int x = 0, y = 200;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 100, 0);
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    // Check that the barrier exists before we destroy it.
++    int dx = 200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
 +
-+    // There should be no barrier to block this.
-+    XTestFakeRelativeMotionEvent (Display (), -200, 0, 0);
++    // Destroy the barrier...
++    XFixesDestroyPointerBarrier (Display (), barrier);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (0, 100));
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // There should be no barrier to block this.
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
 +}
 +
 +TEST_F (BarrierTest, BarrierIgnoresNonsensicalDirections)
 +{
-+    PointerBarrier verticalBarrier;
-+    verticalBarrier = XFixesCreatePointerBarrier (Display (),
-+                                                  DefaultRootWindow (Display ()),
-+                                                  100, 0,
-+                                                  100, 300,
-+                                                  BarrierPositiveY | BarrierNegativeY,
-+                                                  0, NULL);
-+
-+    // Absolute event will ignore barrier
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierPositiveY | BarrierNegativeY,
++                                0, NULL);
++
++    int x = 200, y = 100;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 100, 0);
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    int dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
 +
-+    // Barrier should block relative motion
-+    XTestFakeRelativeMotionEvent (Display (), -200, 0, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (100, 100));
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                               0,   barrier_y,
++                               400, barrier_y,
++                               BarrierPositiveX | BarrierNegativeX,
++                               0, NULL);
 +
-+    PointerBarrier horizontalBarrier;
-+    horizontalBarrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow (dpy),
-+                                                    0,   100,
-+                                                    400, 100,
-+                                                    BarrierPositiveX | BarrierNegativeX,
-+                                                    0, NULL);    
-+    // Absolute event will ignore barrier
++    x = 100, y = 200;
 +    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
-+                          200, 200, 0);
++                          x, y, 0);
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 200));
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    // Barrier should block relative motion
-+    XTestFakeRelativeMotionEvent (Display (), 0, -200, 0);
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
++}
++
++TEST_F (BarrierTest, VerticalBarrierEdges)
++{
++    int barrier_x = 300, barrier_y1 = 300 , barrier_y2 = 500;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, barrier_y1,
++                                barrier_x, barrier_y2,
++                                0, 0, NULL);
++
++    int x = barrier_x + 100, y = barrier_y1 - 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the top of the barrier...
++    int dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = barrier_x + 100, y = barrier_y1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the top of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = barrier_x + 100, y = barrier_y2;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the bottom of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = barrier_x + 100, y = barrier_y2 + 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
 +
-+    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (200, 100));
++    // Motion should take us past the bottom of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, HorizontalBarrierEdges)
++{
++    int barrier_x1 = 200, barrier_x2 = 500, barrier_y = 300;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x1, barrier_y,
++                                barrier_x2, barrier_y,
++                                0, 0, NULL);
++
++    int x = barrier_x1 - 1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the left edge of the barrier...
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = barrier_x1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the top of the barrier...
++    dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, barrier_y - 1));
++
++    x = barrier_x2, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the bottom of the barrier...
++    dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = barrier_x2 + 1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),


Reply to: