summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-10-29 23:16:30 -0400
committerPeter Hutterer <peter.hutterer@who-t.net>2012-11-02 10:44:53 +1000
commita2b6c0cbb57fd25cde5a1334f347c3d258560858 (patch)
tree4e4579928cac2553fed3de5e84dca34d78057d49
parent10dd3b107ed3c0c896e1c19ef0f0240e03818917 (diff)
server: Add tests for pointer barriers
Signed-off-by: Jasper St. Pierre <jstpierre@mecheye.net>
-rw-r--r--configure.ac3
-rw-r--r--tests/common/Makefile.am1
-rw-r--r--tests/server/.gitignore1
-rw-r--r--tests/server/Makefile.am5
-rw-r--r--tests/server/barriers-common.h54
-rw-r--r--tests/server/barriers-directions.cpp421
-rw-r--r--tests/server/barriers-validity.cpp163
7 files changed, 646 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index e7a3628..f9459a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,7 +49,8 @@ PKG_CHECK_MODULES(EVEMU, [evemu >= 1.0.10])
PKG_CHECK_MODULES(XI22, [inputproto >= 2.2] [xi >= 1.6],
AC_DEFINE(HAVE_XI22, 1, [XI 2.2 available]),
[noop=noop])
-PKG_CHECK_MODULES(XTEST, [xtst]);
+PKG_CHECK_MODULES(XTEST, [xtst])
+PKG_CHECK_MODULES(XFIXES, [xfixes])
PKG_CHECK_MODULES(XORGGTEST, [xorg-gtest >= 0.6.0])
PKG_CHECK_MODULES(WACOM, xorg-wacom)
diff --git a/tests/common/Makefile.am b/tests/common/Makefile.am
index d0eda52..0164918 100644
--- a/tests/common/Makefile.am
+++ b/tests/common/Makefile.am
@@ -4,6 +4,7 @@ noinst_LIBRARIES = $(XORG_GTEST_BUILD_LIBS)
AM_CPPFLAGS = \
$(XI_CFLAGS) \
+ $(XFIXES_CFLAGS) \
$(XRANDR_CFLAGS) \
$(WACOM_CFLAGS) \
$(GTEST_CPPFLAGS) \
diff --git a/tests/server/.gitignore b/tests/server/.gitignore
index 4eb1c20..f7d8d2e 100644
--- a/tests/server/.gitignore
+++ b/tests/server/.gitignore
@@ -4,3 +4,4 @@ xigrabbutton
xtest
multihead
misc
+barriers
diff --git a/tests/server/Makefile.am b/tests/server/Makefile.am
index 23c8b17..e5060ba 100644
--- a/tests/server/Makefile.am
+++ b/tests/server/Makefile.am
@@ -1,6 +1,6 @@
include $(top_srcdir)/tests/common/Makefile.am
-noinst_PROGRAMS = grab touch xtest multihead misc
+noinst_PROGRAMS = grab touch xtest multihead misc barriers
TESTS=$(noinst_PROGRAMS)
grab_SOURCES = grab.cpp xigrabbutton.cpp $(common_sources)
@@ -17,3 +17,6 @@ multihead_LDADD = $(GTEST_LDADDS)
misc_SOURCES = misc.cpp $(common_sources)
misc_LDADD = $(GTEST_LDADDS)
+
+barriers_SOURCES = barrires-common.h barriers-validity.cpp barriers-directions.cpp $(common_sources)
+barriers_LDADD = $(GTEST_LDADDS) $(XFIXES_LIBS)
diff --git a/tests/server/barriers-common.h b/tests/server/barriers-common.h
new file mode 100644
index 0000000..1c9e590
--- /dev/null
+++ b/tests/server/barriers-common.h
@@ -0,0 +1,54 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef _BARRIERS_COMMON_H_
+#define _BARRIERS_COMMON_H_
+
+#include <xorg/gtest/xorg-gtest.h>
+
+#include "xit-server-input-test.h"
+#include "device-interface.h"
+
+class BarrierTest : public XITServerInputTest,
+ public DeviceInterface {
+public:
+ int xfixes_opcode;
+ int xfixes_event_base;
+ int xfixes_error_base;
+
+ /**
+ * Initializes a standard mouse device.
+ */
+ virtual void SetUp() {
+ SetDevice("mice/PIXART-USB-OPTICAL-MOUSE-HWHEEL.desc");
+ XITServerInputTest::SetUp();
+
+ if (!XQueryExtension (Display(), XFIXES_NAME,
+ &xfixes_opcode,
+ &xfixes_event_base,
+ &xfixes_error_base)) {
+ ADD_FAILURE () << "Need XFixes.\n";
+ }
+ }
+
+ /**
+ * Sets up an xorg.conf for a single evdev CoreKeyboard device based on
+ * the evemu device. The input from GetParam() is used as XkbLayout.
+ */
+ virtual void SetUpConfigAndLog() {
+ config.AddDefaultScreenWithDriver();
+ config.AddInputSection("evdev", "--device--",
+ "Option \"CorePointer\" \"on\"\n"
+ /* Disable pointer acceleration to allow for accurate
+ * pointer positions with EV_REL events... */
+ "Option \"AccelerationProfile\" \"-1\""
+ "Option \"Device\" \"" + dev->GetDeviceNode() + "\"");
+ /* add default keyboard device to avoid server adding our device again */
+ config.AddInputSection("kbd", "kbd-device",
+ "Option \"CoreKeyboard\" \"on\"\n");
+ config.WriteConfig();
+ }
+};
+
+#endif
diff --git a/tests/server/barriers-directions.cpp b/tests/server/barriers-directions.cpp
new file mode 100644
index 0000000..0db58a9
--- /dev/null
+++ b/tests/server/barriers-directions.cpp
@@ -0,0 +1,421 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <xorg/gtest/xorg-gtest.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/XInput2.h>
+
+#include "barriers-common.h"
+#include "helpers.h"
+
+class BarrierConstrained : public BarrierTest {};
+
+/* Helper because XIQueryPointer and friends
+ * are terrible... */
+static Bool
+QueryPointerPosition(Display *dpy, double *root_x, double *root_y)
+{
+ Window root, child;
+ double win_x, win_y;
+ XIButtonState buttons;
+ XIModifierState mods;
+ XIGroupState group;
+
+ return XIQueryPointer (dpy, VIRTUAL_CORE_POINTER_ID,
+ DefaultRootWindow (dpy),
+ &root, &child,
+ root_x, root_y,
+ &win_x, &win_y,
+ &buttons, &mods, &group);
+ }
+
+#define ASSERT_PTR_POS(x, y) \
+ QueryPointerPosition(dpy, &root_x, &root_y); \
+ ASSERT_EQ(x, root_x); \
+ ASSERT_EQ(y, root_y);
+
+/* Doing this parameterized would require a lot of fancy logic
+ * that would make it super fancy. For now, just do it manually.
+ */
+
+TEST_F(BarrierConstrained, VerticalBarrierNoDirectionBlocksMotion)
+{
+ XORG_TESTCASE("Set up a vertical pointer barrier.\n"
+ "Ensure that mouse movement is blocked in both directions,\n"
+ " horizontally, when crossing the barrer and that warping\n"
+ " across the barrier is not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in neither direction */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 40, 0, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 50, 30);
+ ASSERT_PTR_POS(50, 30);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_X, -100, True);
+ ASSERT_PTR_POS(20, 30);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_X, 100, True);
+ ASSERT_PTR_POS(19, 30);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, VerticalBarrierPositiveXBlocksMotion)
+{
+ XORG_TESTCASE("Set up a vertical pointer barrier. Ensure that mouse"
+ " movement is blocked in the positive X direction when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in positive X */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 40,
+ BarrierPositiveX, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 50, 30);
+ ASSERT_PTR_POS(50, 30);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_X, -100, True);
+ ASSERT_PTR_POS(20, 30);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_X, 100, True);
+ ASSERT_PTR_POS(110, 30);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, VerticalBarrierNegativeXBlocksMotion)
+{
+ XORG_TESTCASE("Set up a vertical pointer barrier. Ensure that mouse"
+ " movement is blocked in the negative X direction when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in negative X */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 40,
+ BarrierNegativeX, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 50, 30);
+ ASSERT_PTR_POS(50, 30);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_X, -100, True);
+ ASSERT_PTR_POS(0, 30);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_X, 100, True);
+ ASSERT_PTR_POS(19, 30);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, VerticalBarrierBothDirectionsXBlocksNoMotion)
+{
+ XORG_TESTCASE("Set up a vertical pointer barrier. Ensure that mouse"
+ " movement is not blocked in either direction, horizontally, when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in negative X */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 40,
+ BarrierPositiveX | BarrierNegativeX,
+ 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 50, 30);
+ ASSERT_PTR_POS(50, 30);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_X, -100, True);
+ ASSERT_PTR_POS(0, 30);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 10, 30);
+ ASSERT_PTR_POS(10, 30);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_X, 100, True);
+ ASSERT_PTR_POS(110, 30);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+
+
+TEST_F(BarrierConstrained, HorizontalBarrierNoDirectionBlocksMotion)
+{
+ XORG_TESTCASE("Set up a horizontal pointer barrier. Ensure that mouse"
+ " movement is blocked in both directions, vertically, when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in neither direction */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 40, 20, 0, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 50);
+ ASSERT_PTR_POS(30, 50);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, -100, True);
+ ASSERT_PTR_POS(30, 20);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, 100, True);
+ ASSERT_PTR_POS(30, 19);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, HoritzontalBarrierPositiveYBlocksMotion)
+{
+ XORG_TESTCASE("Set up a horizontal pointer barrier. Ensure that mouse"
+ " movement is blocked in the positive Y direction when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in positive Y */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 40, 20,
+ BarrierPositiveY, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 50);
+ ASSERT_PTR_POS(30, 50);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, -100, True);
+ ASSERT_PTR_POS(30, 20);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, 100, True);
+ ASSERT_PTR_POS(30, 110);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, HoritzontalBarrierNegativeYBlocksMotion)
+{
+ XORG_TESTCASE("Set up a horizontal pointer barrier. Ensure that mouse"
+ " movement is blocked in the negative Y direction when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in negative Y */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 40, 20,
+ BarrierNegativeY, 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 50);
+ ASSERT_PTR_POS(30, 50);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, -100, True);
+ ASSERT_PTR_POS(30, 0);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* This should be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, 100, True);
+ ASSERT_PTR_POS(30, 19);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
+
+TEST_F(BarrierConstrained, HorizontalBarrierBothDirectionsYBlocksNoMotion)
+{
+ XORG_TESTCASE("Set up a horizontal pointer barrier. Ensure that mouse"
+ " movement is not blocked in either direction, vertically, when"
+ " crossing the barrer and that warping across the barrier is"
+ " not blocked.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+ double root_x, root_y;
+
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 30);
+
+ ASSERT_PTR_POS(30, 30);
+
+ /* Barrier allows motion in negative X */
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 40, 20,
+ BarrierPositiveY | BarrierNegativeY,
+ 0, NULL);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* Ensure that absolute warping works fine. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 50);
+ ASSERT_PTR_POS(30, 50);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, -100, True);
+ ASSERT_PTR_POS(30, 0);
+
+ /* Warp the pointer to before the barrier. */
+ XIWarpPointer(dpy, VIRTUAL_CORE_POINTER_ID,
+ None, root, 0, 0, 0, 0, 30, 10);
+ ASSERT_PTR_POS(30, 10);
+
+ /* This shouldn't be blocked. */
+ dev->PlayOne(EV_REL, REL_Y, 100, True);
+ ASSERT_PTR_POS(30, 110);
+
+ XFixesDestroyPointerBarrier (dpy, barrier);
+}
diff --git a/tests/server/barriers-validity.cpp b/tests/server/barriers-validity.cpp
new file mode 100644
index 0000000..8aa9343
--- /dev/null
+++ b/tests/server/barriers-validity.cpp
@@ -0,0 +1,163 @@
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <xorg/gtest/xorg-gtest.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/XInput2.h>
+
+#include "barriers-common.h"
+#include "helpers.h"
+
+class BarrierSimpleTest : public BarrierTest {};
+
+TEST_F(BarrierSimpleTest, CreateAndDestroyBarrier)
+{
+ XORG_TESTCASE("Create a valid pointer barrier.\n"
+ "Ensure PointerBarrier XID is valid.\n"
+ "Delete pointer barrier\n"
+ "Ensure no error is generated\n");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ PointerBarrier barrier;
+
+ XSync(dpy, False);
+
+ barrier = XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 40,
+ BarrierPositiveX, 0, NULL);
+ ASSERT_NE((PointerBarrier)None, barrier) << "Failed to create barrier.";
+
+ SetErrorTrap(dpy);
+ XFixesDestroyPointerBarrier(dpy, barrier);
+ ASSERT_NO_ERROR(ReleaseErrorTrap(dpy));
+}
+
+TEST_F(BarrierSimpleTest, DestroyInvalidBarrier)
+{
+ XORG_TESTCASE("Delete invalid pointer barrier\n"
+ "Ensure error is generated\n");
+
+ SetErrorTrap(Display());
+ XFixesDestroyPointerBarrier(Display(), -1);
+ XErrorEvent *error = ReleaseErrorTrap(Display());
+ ASSERT_ERROR(error, xfixes_error_base + BadBarrier);
+}
+
+#define VALID_DIRECTIONS \
+ ::testing::Values(0L, \
+ BarrierPositiveX, \
+ BarrierPositiveY, \
+ BarrierNegativeX, \
+ BarrierNegativeY, \
+ BarrierPositiveX | BarrierNegativeX, \
+ BarrierPositiveY | BarrierNegativeX)
+
+#define INVALID_DIRECTIONS \
+ ::testing::Values(BarrierPositiveX | BarrierPositiveY, \
+ BarrierNegativeX | BarrierNegativeY, \
+ BarrierPositiveX | BarrierNegativeY, \
+ BarrierNegativeX | BarrierPositiveY, \
+ BarrierPositiveX | BarrierNegativeX | BarrierPositiveY, \
+ BarrierPositiveX | BarrierNegativeX | BarrierNegativeY, \
+ BarrierPositiveX | BarrierPositiveY | BarrierNegativeY, \
+ BarrierNegativeX | BarrierPositiveY | BarrierNegativeY, \
+ BarrierPositiveX | BarrierNegativeX | BarrierPositiveY | BarrierNegativeY)
+
+
+class BarrierZeroLength : public BarrierTest,
+ public ::testing::WithParamInterface<long int> {};
+TEST_P(BarrierZeroLength, InvalidZeroLengthBarrier)
+{
+ XORG_TESTCASE("Create a pointer barrier with zero length.\n"
+ "Ensure server returns BadValue.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ int directions = GetParam();
+
+ XSync(dpy, False);
+
+ SetErrorTrap(dpy);
+ XFixesCreatePointerBarrier(dpy, root, 20, 20, 20, 20, directions, 0, NULL);
+ XErrorEvent *error = ReleaseErrorTrap(dpy);
+ ASSERT_ERROR(error, BadValue);
+}
+
+INSTANTIATE_TEST_CASE_P(, BarrierZeroLength, VALID_DIRECTIONS);
+
+class BarrierNonZeroArea : public BarrierTest,
+ public ::testing::WithParamInterface<long int> {};
+TEST_P(BarrierNonZeroArea, InvalidNonZeroAreaBarrier)
+{
+ XORG_TESTCASE("Create pointer barrier with non-zero area.\n"
+ "Ensure server returns BadValue\n");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+ int directions = GetParam();
+
+ XSync(dpy, False);
+
+ SetErrorTrap(dpy);
+ XFixesCreatePointerBarrier(dpy, root, 20, 20, 40, 40, directions, 0, NULL);
+ XErrorEvent *error = ReleaseErrorTrap(dpy);
+ ASSERT_ERROR(error, BadValue);
+}
+INSTANTIATE_TEST_CASE_P(, BarrierNonZeroArea, VALID_DIRECTIONS);
+
+static void
+BarrierPosForDirections(int directions, int *x1, int *y1, int *x2, int *y2)
+{
+ *x1 = 20;
+ *y1 = 20;
+
+ if (directions & BarrierPositiveY) {
+ *x2 = 40;
+ *y2 = 20;
+ } else {
+ *x2 = 20;
+ *y2 = 40;
+ }
+}
+
+class BarrierConflictingDirections : public BarrierTest,
+ public ::testing::WithParamInterface<long int> {};
+TEST_P(BarrierConflictingDirections, InvalidConflictingDirectionsBarrier)
+{
+ XORG_TESTCASE("Create a barrier with conflicting directions, such\n"
+ "as (PositiveX | NegativeY), and ensure that these\n"
+ "cases are handled properly.");
+
+ ::Display *dpy = Display();
+ Window root = DefaultRootWindow(dpy);
+
+ int directions = GetParam();
+ int x1, y1, x2, y2;
+ BarrierPosForDirections(directions, &x1, &y1, &x2, &y2);
+
+ XSync(dpy, False);
+
+ SetErrorTrap(dpy);
+ XFixesCreatePointerBarrier(dpy, root, x1, y1, x2, y2, directions, 0, NULL);
+ XErrorEvent *error = ReleaseErrorTrap(dpy);
+
+ /* Nonsensical directions are ignored -- they don't
+ * raise a BadValue. Unfortunately, there's no way
+ * to query an existing pointer barrier, so we can't
+ * actually check that the masked directions are proper.
+ *
+ * Just ensure we have no error.
+ */
+
+ ASSERT_NO_ERROR(error);
+}
+INSTANTIATE_TEST_CASE_P(, BarrierConflictingDirections, INVALID_DIRECTIONS);
+
+int main(int argc, char **argv) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}