[PATCH 3/3 wayland-fits] core: Add a test for multiple pointer and keyboard resources

Neil Roberts neil at linux.intel.com
Wed Sep 25 11:06:52 PDT 2013


This adds a test which creates multiple pointer and keyboard resources
for the same client and verifies that they all receive events. It also
tests various combiniations of pointer and keyboard focus and ensures
that for example a keyboard created while the surface already has
focus will correctly get updated about the state.
---
 src/test/core/Makefile.am             |   1 +
 src/test/core/test_multi_resource.cpp | 259 ++++++++++++++++++++++++++++++++++
 2 files changed, 260 insertions(+)
 create mode 100644 src/test/core/test_multi_resource.cpp

diff --git a/src/test/core/Makefile.am b/src/test/core/Makefile.am
index 3a93a67..ec7901b 100644
--- a/src/test/core/Makefile.am
+++ b/src/test/core/Makefile.am
@@ -19,6 +19,7 @@ libwfits_core_la_SOURCES =		\
 	test_bind_interface.cpp		\
 	test_cursor.cpp			\
 	test_data.cpp			\
+	test_multi_resource.cpp		\
 	test_surface.cpp		\
 	test_dnd.cpp
 
diff --git a/src/test/core/test_multi_resource.cpp b/src/test/core/test_multi_resource.cpp
new file mode 100644
index 0000000..d3fb003
--- /dev/null
+++ b/src/test/core/test_multi_resource.cpp
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "harness.h"
+#include "compositor.h"
+#include "pointer.h"
+#include "keyboard.h"
+#include "seat.h"
+#include "surface.h"
+#include "shell.h"
+#include "shell_surface.h"
+#include "shm.h"
+
+namespace wfits {
+namespace test {
+namespace core {
+namespace input {
+
+class DummyClient
+{
+public:
+	DummyClient()
+		: display_()
+		, compositor_(display_)
+		, shell_(display_)
+		, seat_(display_)
+		, surface_(compositor_)
+		, shellSurface_(shell_, surface_)
+		, shm_(display_)
+		, buffer_(shm_, 128, 128)
+	{
+		wl_surface_attach(surface_, buffer_, 0, 0);
+		wl_surface_damage(surface_, 0, 0,
+				  buffer_.width(), buffer_.height());
+		surface_.commit();
+	}
+
+private:
+	Display display_;
+	Compositor compositor_;
+	Shell shell_;
+	Seat seat_;
+	Surface surface_;
+	ShellSurface shellSurface_;
+	SharedMemory shm_;
+	SharedMemoryBuffer buffer_;
+};
+
+class MultiResourceTest : public Harness
+{
+public:
+	MultiResourceTest()
+		: Harness::Harness()
+		, compositor_(display())
+		, shell_(display())
+		, seat_(display())
+		, surface_(compositor_)
+		, shellSurface_(shell_, surface_)
+		, shm_(display())
+		, buffer_(shm_, 128, 128)
+	{
+	}
+
+	void setup();
+	void testPointer();
+	void testKeyboard();
+
+	void movePointer(const int32_t x, const int32_t y)
+	{
+		Geometry geometry(getSurfaceGeometry(surface_));
+		setGlobalPointerPosition(geometry.x + x, geometry.y + y);
+	}
+
+	void checkPointer(Pointer *pointer, const int32_t x, const int32_t y)
+	{
+		YIELD_UNTIL(pointer->x() == x and pointer->y() == y);
+	}
+
+private:
+	Compositor compositor_;
+	Shell shell_;
+	Seat seat_;
+	Surface surface_;
+	ShellSurface shellSurface_;
+	SharedMemory shm_;
+	SharedMemoryBuffer buffer_;
+};
+
+void MultiResourceTest::setup()
+{
+	wl_surface_attach(surface_, buffer_, 0, 0);
+	wl_surface_damage(surface_, 0, 0, buffer_.width(), buffer_.height());
+	surface_.commit();
+
+	queueStep(boost::bind(&MultiResourceTest::testPointer, boost::ref(*this)));
+	queueStep(boost::bind(&MultiResourceTest::testKeyboard, boost::ref(*this)));
+}
+
+void MultiResourceTest::testPointer()
+{
+	Pointer *pointer_a = new Pointer(seat_);
+	Pointer *pointer_b = new Pointer(seat_);
+
+	movePointer(42, 120);
+
+	/* Verify that both pointers received the new position */
+	YIELD_UNTIL(pointer_a->hasFocus(surface_));
+	YIELD_UNTIL(pointer_b->hasFocus(surface_));
+	checkPointer(pointer_a, 42, 120);
+	checkPointer(pointer_b, 42, 120);
+
+	/* Move the pointer outside of the surface */
+	movePointer(130, 130);
+	YIELD_UNTIL(!pointer_a->hasFocus(surface_));
+	YIELD_UNTIL(!pointer_b->hasFocus(surface_));
+
+	/* Move the pointer back inside the surface while we only have
+	 * one pointer */
+	delete pointer_b;
+	yield();
+	movePointer(42, 120);
+	YIELD_UNTIL(pointer_a->hasFocus(surface_));
+	checkPointer(pointer_a, 42, 120);
+
+	/* Verify that the second pointer gets the updated position
+	 * even if it is created later */
+	pointer_b = new Pointer(seat_);
+	YIELD_UNTIL(pointer_b->hasFocus(surface_));
+	checkPointer(pointer_b, 42, 120);
+
+	/* Both pointers should have the same focus serial or one of
+	 * them would fail to set the cursor */
+	ASSERT(pointer_a->focusSerial() == pointer_b->focusSerial());
+
+	delete pointer_a;
+	delete pointer_b;
+}
+
+void MultiResourceTest::testKeyboard()
+{
+	Keyboard *keyboard_a = new Keyboard(seat_);
+	Keyboard *keyboard_b = new Keyboard(seat_);
+
+	/* Both keyboards should initially have focus */
+	YIELD_UNTIL(keyboard_a->hasFocus(surface_));
+	YIELD_UNTIL(keyboard_b->hasFocus(surface_));
+
+	xkb_mod_index_t shiftMod =
+		xkb_keymap_mod_get_index(keyboard_a->keymap(),
+					 XKB_MOD_NAME_SHIFT);
+	ASSERT(shiftMod != XKB_MOD_INVALID);
+
+	inputKeySend(KEY_LEFTSHIFT, 1);
+	inputKeySend(KEY_A, 1);
+
+	/* Both keyboards should get key events */
+	YIELD_UNTIL(keyboard_a->keyPressed(KEY_LEFTSHIFT) and
+		    keyboard_b->keyPressed(KEY_LEFTSHIFT) and
+		    keyboard_a->keyPressed(KEY_A) and
+		    keyboard_b->keyPressed(KEY_A) and
+		    (keyboard_a->modsDepressed() & (1 << shiftMod)) != 0 and
+		    (keyboard_b->modsDepressed() & (1 << shiftMod)) != 0);
+
+	inputKeySend(KEY_LEFTSHIFT, 0);
+	inputKeySend(KEY_A, 0);
+
+	YIELD_UNTIL(!keyboard_a->keyPressed(KEY_LEFTSHIFT) and
+		    !keyboard_b->keyPressed(KEY_LEFTSHIFT) and
+		    !keyboard_a->keyPressed(KEY_A) and
+		    !keyboard_b->keyPressed(KEY_A) and
+		    (keyboard_a->modsDepressed() & (1 << shiftMod)) == 0 and
+		    (keyboard_b->modsDepressed() & (1 << shiftMod)) == 0);
+
+	/* Create another surface with a dummy display so that we can
+	 * be sure this client doesn't have focus */
+	DummyClient dummyClient;
+
+	/* Give the old surface pointer focus but not keyboard focus */
+	movePointer(5, 5);
+	{
+		Pointer pointer(seat_);
+		YIELD_UNTIL(!keyboard_a->hasFocus(surface_) and
+			    pointer.hasFocus(surface_));
+	}
+
+	/* We should still be able to see the modifiers even though we
+	 * don't have a pointer resource and the surface doesn't have
+	 * keyboard focus */
+	inputKeySend(KEY_LEFTSHIFT, 1);
+	YIELD_UNTIL((keyboard_a->modsDepressed() & (1 << shiftMod)) and
+		    (keyboard_b->modsDepressed() & (1 << shiftMod)));
+	inputKeySend(KEY_LEFTSHIFT, 0);
+	YIELD_UNTIL((keyboard_a->modsDepressed() & (1 << shiftMod)) == 0 and
+		    (keyboard_b->modsDepressed() & (1 << shiftMod)) == 0);
+
+	delete keyboard_b;
+
+	inputKeySend(KEY_A, 1);
+	yield();
+
+	/* This client doesn't have focus so we shouldn't be able to
+	 * see the key press */
+	YIELD_UNTIL(!keyboard_a->keyPressed(KEY_A));
+
+	/* Give the surface focus by clicking on it */
+	inputKeySend(BTN_LEFT, 1);
+	yield();
+	inputKeySend(BTN_LEFT, 0);
+	yield();
+
+	/* The surface should now be told about the keypresses in the
+	 * enter event */
+	YIELD_UNTIL(keyboard_a->hasFocus(surface_) and
+		    keyboard_a->keyPressed(KEY_A));
+
+	inputKeySend(KEY_LEFTSHIFT, 1);
+	YIELD_UNTIL(keyboard_a->keyPressed(KEY_LEFTSHIFT) and
+		    (keyboard_a->modsDepressed() & (1 << shiftMod)));
+
+	/* If we later create another keyboard resource it should be
+	 * told about the modifiers and key presses on creation */
+	keyboard_b = new Keyboard(seat_);
+	YIELD_UNTIL(keyboard_b->hasFocus(surface_) and
+		    keyboard_b->keyPressed(KEY_A) and
+		    keyboard_b->keyPressed(KEY_LEFTSHIFT) and
+		    (keyboard_b->modsDepressed() & (1 << shiftMod)));
+
+	inputKeySend(KEY_A, 0);
+	inputKeySend(KEY_LEFTSHIFT, 0);
+
+	delete keyboard_a;
+	delete keyboard_b;
+}
+
+WFITS_CORE_HARNESS_TEST_CASE(MultiResourceTest);
+
+} // namespace input
+} // namespace core
+} // namespace test
+} // namespace wfits
-- 
1.8.3.1



More information about the wayland-devel mailing list