This adds a wrapper for a wl_keyboard in a similar way to the pointer wrapper. It keeps track of the keys that are pressed so that they can be quickly verified. wayland-fits now depends on libxkbcommon so that the keyboard wrapper can pass the keymap to it and get the modifier indices. --- configure.ac | 2 + src/test/Makefile.am | 2 + src/test/core/Makefile.am | 3 + src/test/core/display.cpp | 13 +++ src/test/core/display.h | 3 + src/test/core/keyboard.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++++ src/test/core/keyboard.h | 107 +++++++++++++++++++++++ src/test/efl/Makefile.am | 2 + src/test/gtk+/Makefile.am | 2 + 9 files changed, 347 insertions(+) create mode 100644 src/test/core/keyboard.cpp create mode 100644 src/test/core/keyboard.h
diff --git a/configure.ac b/configure.ac index de84adf..5ad59ca 100644 --- a/configure.ac +++ b/configure.ac @@ -61,6 +61,8 @@ PKG_CHECK_MODULES([WAYLAND], ) PKG_CHECK_MODULES(WAYLAND_SERVER, [wayland-server >= wayland_req_version]) +PKG_CHECK_MODULES([XKBCOMMON], xkbcommon) + have_weston="no" want_weston_extensions="auto" AC_ARG_ENABLE([weston-extensions], diff --git a/src/test/Makefile.am b/src/test/Makefile.am index ba5e5ce..e50c0fc 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -14,6 +14,7 @@ wfits_SOURCES = \ wfits_LDADD = \ core/libwfits-core.la \ $(CHECK_LIBS) \ + $(XKBCOMMON_LIBS) \ $(WAYLAND_LIBS) \ $(BOOST_LIBS) @@ -23,6 +24,7 @@ wfits_LDFLAGS = \ wfits_CPPFLAGS = \ -I$(top_srcdir)/src \ $(CHECK_CFLAGS) \ + $(XKBCOMMON_CFLAGS) \ $(WAYLAND_CFLAGS) \ $(BOOST_CPPFLAGS) diff --git a/src/test/core/Makefile.am b/src/test/core/Makefile.am index bff1c5a..3a93a67 100644 --- a/src/test/core/Makefile.am +++ b/src/test/core/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libwfits-core.la libwfits_core_la_SOURCES = \ display.cpp \ compositor.cpp \ + keyboard.cpp \ shell.cpp \ seat.cpp \ pointer.cpp \ @@ -23,11 +24,13 @@ libwfits_core_la_SOURCES = \ libwfits_core_la_LIBADD = \ $(WAYLAND_LIBS) \ + $(XKBCOMMON_LIBS) \ $(CHECK_LIBS) libwfits_core_la_CPPFLAGS = \ -I$(top_srcdir)/src \ $(WAYLAND_CFLAGS) \ + $(XKBCOMMON_CFLAGS) \ $(CHECK_CFLAGS) AM_CXXFLAGS = \ diff --git a/src/test/core/display.cpp b/src/test/core/display.cpp index 1c29dbf..5c9a459 100644 --- a/src/test/core/display.cpp +++ b/src/test/core/display.cpp @@ -30,6 +30,7 @@ Display::Display() : wl_display_(wl_display_connect(0)) , wl_registry_(NULL) , globals_() + , xkbContext_(NULL) { ASSERT(wl_display_ != NULL); @@ -49,6 +50,8 @@ Display::Display() /*virtual*/ Display::~Display() { + if (xkbContext_) + xkb_context_unref(xkbContext_); wl_registry_destroy(wl_registry_); wl_display_disconnect(*this); } @@ -69,6 +72,16 @@ void Display::yield(const unsigned time) const usleep(time); } +struct xkb_context *Display::xkbContext() const +{ + if (xkbContext_ == NULL) { + xkbContext_ = xkb_context_new((enum xkb_context_flags) 0); + ASSERT(xkbContext_ != NULL); + } + + return xkbContext_; +} + /*static*/ void Display::global( void *data, struct wl_registry *wl_registry, uint32_t id, const char* interface, uint32_t version) diff --git a/src/test/core/display.h b/src/test/core/display.h index 0a4c10a..bf09057 100644 --- a/src/test/core/display.h +++ b/src/test/core/display.h @@ -25,6 +25,7 @@ #include <map> #include <wayland-client.h> +#include <xkbcommon/xkbcommon.h> #include "test/tools.h" namespace wfits { @@ -63,6 +64,7 @@ public: void roundtrip() const; void dispatch() const; void yield(const unsigned = 0.001 * 1e6) const; + struct xkb_context *xkbContext() const; operator wl_display*() const { return wl_display_; } operator wl_registry*() const { return wl_registry_; } @@ -74,6 +76,7 @@ private: wl_display *wl_display_; wl_registry *wl_registry_; Globals globals_; + mutable struct xkb_context *xkbContext_; }; } // namespace core diff --git a/src/test/core/keyboard.cpp b/src/test/core/keyboard.cpp new file mode 100644 index 0000000..aa49413 --- /dev/null +++ b/src/test/core/keyboard.cpp @@ -0,0 +1,213 @@ +/* + * 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 <sys/mman.h> + +#include "keyboard.h" + +namespace wfits { +namespace test { +namespace core { + +Keyboard::Keyboard(const Seat& seat) + : seat_(seat) + , focus_(NULL) + , focusSerial_(0) + , wl_keyboard_(NULL) + , modsDepressed_(0) + , modsLatched_(0) + , modsLocked_(0) + , group_(0) + , keymap_(NULL) +{ + ASSERT(seat.capabilities() & WL_SEAT_CAPABILITY_KEYBOARD); + + wl_keyboard_ = wl_seat_get_keyboard(seat); + + ASSERT(wl_keyboard_ != NULL); + + wl_keyboard_set_user_data(*this, this); + + static const wl_keyboard_listener listener = { + keymap, enter, leave, key, modifiers + }; + + wl_keyboard_add_listener(*this, &listener, this); +} + +/*virtual*/ Keyboard::~Keyboard() +{ + if (keymap_) + xkb_map_unref(keymap_); + + wl_keyboard_destroy(*this); +} + +bool Keyboard::hasFocus(wl_surface* surface) +{ + return focus() == surface; +} + +bool Keyboard::keyPressed(uint32_t key) const +{ + for (CKeyIterator it = keys_.begin(); it != keys_.end(); ++it) + if (*it == key) + return true; + + return false; +} + +void Keyboard::pressKey(uint32_t key) +{ + for (KeyIterator it = keys_.begin(); it != keys_.end(); ++it) + if (*it == key) + return; + + keys_.push_back(key); +} + +void Keyboard::releaseKey(uint32_t key) +{ + for (KeyIterator it = keys_.begin(); it != keys_.end(); ++it) { + if (*it == key) { + *it = keys_.end()[-1]; + keys_.pop_back(); + break; + } + } +} + +/* static */ void Keyboard::keymap(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t format, + int32_t fd, + uint32_t size) +{ + Keyboard* keyboard = static_cast<Keyboard*>(data); + struct xkb_keymap *keymap; + char *map_str; + + ASSERT(wl_keyboard == *keyboard); + ASSERT(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); + + map_str = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + ASSERT(map_str != MAP_FAILED); + + keymap = xkb_map_new_from_string(keyboard->seat_.display().xkbContext(), + map_str, + XKB_KEYMAP_FORMAT_TEXT_V1, + (enum xkb_keymap_compile_flags) 0); + munmap(map_str, size); + close(fd); + + ASSERT(keymap != NULL); + + if (keyboard->keymap_ != NULL) + xkb_map_unref(keyboard->keymap_); + + keyboard->keymap_ = keymap; +} + +/* static */ void Keyboard::enter(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys) +{ + Keyboard* keyboard = static_cast<Keyboard*>(data); + ASSERT(wl_keyboard == *keyboard); + + keyboard->focus_ = surface; + keyboard->focusSerial_ = serial; + + keyboard->keys_.resize(keys->size / sizeof(uint32_t)); + memcpy(&keyboard->keys_[0], keys->data, keys->size); +} + +/* static */ void Keyboard::leave(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + struct wl_surface *surface) +{ + Keyboard* keyboard = static_cast<Keyboard*>(data); + ASSERT(wl_keyboard == *keyboard); + + keyboard->focus_ = NULL; + keyboard->keys_.resize(0); + + /* We don't want to reset the modifiers here because the + * compositor may still send updated modifier state if the + * surface has pointer focus */ +} + +/* static */ void Keyboard::key(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state) +{ + Keyboard* keyboard = static_cast<Keyboard*>(data); + ASSERT(wl_keyboard == *keyboard); + + if (state == 0) + keyboard->releaseKey(key); + else + keyboard->pressKey(key); +} + +/* static */ void Keyboard::modifiers(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + uint32_t modsDepressed, + uint32_t modsLatched, + uint32_t modsLocked, + uint32_t group) +{ + Keyboard* keyboard = static_cast<Keyboard*>(data); + ASSERT(wl_keyboard == *keyboard); + + keyboard->modsDepressed_ = modsDepressed; + keyboard->modsLatched_ = modsLatched; + keyboard->modsLocked_ = modsLocked; + keyboard->group_ = group; +} + +namespace wrapper { + + TEST(Keyboard) + { + Display display; + Seat seat(display); + Keyboard keyboard(seat); + + FAIL_UNLESS_EQUAL(&keyboard.seat(), &seat); + FAIL_IF((wl_keyboard*)keyboard == NULL); + FAIL_UNLESS_EQUAL(wl_keyboard_get_user_data(keyboard), &keyboard); + FAIL_UNLESS(keyboard.hasFocus(NULL)); + } + +} // namespace wrapper + +} // namespace core +} // namespace test +} // namespace wfits diff --git a/src/test/core/keyboard.h b/src/test/core/keyboard.h new file mode 100644 index 0000000..9bc5d33 --- /dev/null +++ b/src/test/core/keyboard.h @@ -0,0 +1,107 @@ +/* + * 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. + */ + +#ifndef __WFITS_CORE_KEYBOARD_H__ +#define __WFITS_CORE_KEYBOARD_H__ + +#include <xkbcommon/xkbcommon.h> +#include <vector> +#include "seat.h" + +namespace wfits { +namespace test { +namespace core { + +class Keyboard +{ +public: + Keyboard(const Seat&); + + virtual ~Keyboard(); + + operator wl_keyboard*() const { return wl_keyboard_; } + const Seat& seat() const { return seat_; } + wl_surface* focus() const { return focus_; } + xkb_keymap* keymap() const { return keymap_; } + const uint32_t focusSerial() const { return focusSerial_; } + + bool hasFocus(wl_surface*); + + const uint32_t modsDepressed() const { return modsDepressed_; } + const uint32_t modsLatched() const { return modsLatched_; } + const uint32_t modsLocked() const { return modsLocked_; } + const uint32_t group() const { return group_; } + bool keyPressed(uint32_t key) const; + +private: + static void keymap(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t format, + int32_t fd, + uint32_t size); + static void enter(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + struct wl_surface *surface, + struct wl_array *keys); + static void leave(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + struct wl_surface *surface); + static void key(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + uint32_t time, + uint32_t key, + uint32_t state); + static void modifiers(void *data, + struct wl_keyboard *wl_keyboard, + uint32_t serial, + uint32_t modsDepressed, + uint32_t modsLatched, + uint32_t modsLocked, + uint32_t group); + + void pressKey(uint32_t key); + void releaseKey(uint32_t key); + void setKeys(const uint32_t *keys, int n_keys); + + const Seat& seat_; + wl_surface* focus_; + uint32_t focusSerial_; + wl_keyboard* wl_keyboard_; + + typedef std::vector<uint32_t>::iterator KeyIterator; + typedef std::vector<uint32_t>::const_iterator CKeyIterator; + std::vector<uint32_t> keys_; + uint32_t modsDepressed_; + uint32_t modsLatched_; + uint32_t modsLocked_; + uint32_t group_; + struct xkb_keymap *keymap_; +}; + +} // namespace core +} // namespace test +} // namespace wfits + +#endif diff --git a/src/test/efl/Makefile.am b/src/test/efl/Makefile.am index 104213d..85084be 100644 --- a/src/test/efl/Makefile.am +++ b/src/test/efl/Makefile.am @@ -46,6 +46,7 @@ libwfits_efl_la_SOURCES = \ test_window_fullscreen.cpp libwfits_efl_la_LIBADD = \ + $(XKBCOMMON_LIBS) \ $(WAYLAND_LIBS) \ $(EFL_LIBS) \ $(CHECK_LIBS) @@ -53,6 +54,7 @@ libwfits_efl_la_LIBADD = \ libwfits_efl_la_CPPFLAGS = \ -I$(top_srcdir)/src \ -DMEDIA_PATH=$(MEDIA) \ + $(XKBCOMMON_CFLAGS) \ $(WAYLAND_CFLAGS) \ $(EFL_CFLAGS) \ $(CHECK_CFLAGS) diff --git a/src/test/gtk+/Makefile.am b/src/test/gtk+/Makefile.am index b19aa9c..aa12963 100644 --- a/src/test/gtk+/Makefile.am +++ b/src/test/gtk+/Makefile.am @@ -10,12 +10,14 @@ libwfits_gtk_la_SOURCES = \ libwfits_gtk_la_LIBADD = \ $(WAYLAND_LIBS) \ + $(XKBCOMMON_LIBS) \ $(GTK_LIBS) \ $(CHECK_LIBS) libwfits_gtk_la_CPPFLAGS = \ -I$(top_srcdir)/src \ $(WAYLAND_CFLAGS) \ + $(XKBCOMMON_CFLAGS) \ $(GTK_CFLAGS) \ $(CHECK_CFLAGS) -- 1.8.3.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel