From 276b15fa355ce3a2e92b307d340f2367ccac1843 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 13 Dec 2018 09:39:05 +0100 Subject: Client tests: Add simple test for keyboard press Change-Id: Ib28be5277af9145834c7808f993c747e21845616 Reviewed-by: Paul Olav Tvete --- tests/auto/client/seatv4/tst_seatv4.cpp | 27 +++++++++++++- tests/auto/client/shared/coreprotocol.cpp | 58 ++++++++++++++++++++++++++++- tests/auto/client/shared/coreprotocol.h | 18 ++++++++- tests/auto/client/shared/mockcompositor.cpp | 2 +- tests/auto/client/shared/mockcompositor.h | 1 + 5 files changed, 101 insertions(+), 5 deletions(-) diff --git a/tests/auto/client/seatv4/tst_seatv4.cpp b/tests/auto/client/seatv4/tst_seatv4.cpp index b6357a25b..f1e948ee2 100644 --- a/tests/auto/client/seatv4/tst_seatv4.cpp +++ b/tests/auto/client/seatv4/tst_seatv4.cpp @@ -46,7 +46,7 @@ public: removeAll(); - uint capabilities = MockCompositor::Seat::capability_pointer; + uint capabilities = Seat::capability_pointer | Seat::capability_keyboard; int version = 4; add(capabilities, version); }); @@ -67,6 +67,8 @@ private slots: void simpleAxis(); void invalidPointerEvents(); void scaledCursor(); + + void keyboardKeyPress(); }; void tst_seatv4::cleanup() @@ -287,5 +289,28 @@ void tst_seatv4::scaledCursor() exec([&] { remove(output(1)); }); } +void tst_seatv4::keyboardKeyPress() +{ + class Window : public QRasterWindow { + public: + void keyPressEvent(QKeyEvent *) override { m_pressed = true; } + bool m_pressed = false; + }; + + Window window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + uint keyCode = 80; // arbitrarily chosen + exec([&] { + auto *surface = xdgSurface()->m_surface; + keyboard()->sendEnter(surface); + keyboard()->sendKey(client(), keyCode, Keyboard::key_state_pressed); + keyboard()->sendKey(client(), keyCode, Keyboard::key_state_released); + }); + QTRY_VERIFY(window.m_pressed); +} + QCOMPOSITOR_TEST_MAIN(tst_seatv4) #include "tst_seatv4.moc" diff --git a/tests/auto/client/shared/coreprotocol.cpp b/tests/auto/client/shared/coreprotocol.cpp index fdd5f627c..16494d789 100644 --- a/tests/auto/client/shared/coreprotocol.cpp +++ b/tests/auto/client/shared/coreprotocol.cpp @@ -193,8 +193,8 @@ Seat::~Seat() } void Seat::setCapabilities(uint capabilities) { - // TODO: Add support for touch and keyboard - Q_ASSERT(capabilities == 0 || capabilities == capability_pointer); + // TODO: Add support for touch + Q_ASSERT(~capabilities & capability_touch); m_capabilities = capabilities; @@ -206,6 +206,14 @@ void Seat::setCapabilities(uint capabilities) { m_pointer = nullptr; } + if (m_capabilities & capability_keyboard) { + if (!m_keyboard) + m_keyboard = (new Keyboard(this)); + } else if (m_keyboard) { + m_oldKeyboards << m_keyboard; + m_keyboard = nullptr; + } + for (auto *resource : resourceMap()) wl_seat::send_capabilities(resource->handle, capabilities); } @@ -225,6 +233,21 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id) m_pointer->add(resource->client(), id, resource->version()); } +void Seat::seat_get_keyboard(QtWaylandServer::wl_seat::Resource *resource, uint32_t id) +{ + if (~m_capabilities & capability_pointer) { + qWarning() << "Client requested a wl_keyboard without the capability being available." + << "This Could be a race condition when hotunplugging," + << "but is most likely a client error"; + Keyboard *keyboard = new Keyboard(this); + keyboard->add(resource->client(), id, resource->version()); + // TODO: mark as destroyed + m_oldKeyboards << keyboard; + return; + } + m_keyboard->add(resource->client(), id, resource->version()); +} + Surface *Pointer::cursorSurface() { return m_cursorRole ? m_cursorRole->m_surface : nullptr; @@ -296,6 +319,37 @@ void Pointer::pointer_set_cursor(Resource *resource, uint32_t serial, wl_resourc emit setCursor(serial); } +uint Keyboard::sendEnter(Surface *surface) +{ + auto serial = m_seat->m_compositor->nextSerial(); + wl_client *client = surface->resource()->client(); + const auto pointerResources = resourceMap().values(client); + for (auto *r : pointerResources) + send_enter(r->handle, serial, surface->resource()->handle, QByteArray()); + return serial; +} + +uint Keyboard::sendLeave(Surface *surface) +{ + auto serial = m_seat->m_compositor->nextSerial(); + wl_client *client = surface->resource()->client(); + const auto pointerResources = resourceMap().values(client); + for (auto *r : pointerResources) + send_leave(r->handle, serial, surface->resource()->handle); + return serial; +} + +uint Keyboard::sendKey(wl_client *client, uint key, uint state) +{ + Q_ASSERT(state == key_state_pressed || state == key_state_released); + auto time = m_seat->m_compositor->currentTimeMilliseconds(); + uint serial = m_seat->m_compositor->nextSerial(); + const auto pointerResources = resourceMap().values(client); + for (auto *r : pointerResources) + send_key(r->handle, serial, time, key, state); + return serial; +} + // Shm implementation Shm::Shm(CoreCompositor *compositor, QVector formats, int version) : QtWaylandServer::wl_shm(compositor->m_display, version) diff --git a/tests/auto/client/shared/coreprotocol.h b/tests/auto/client/shared/coreprotocol.h index 565ae66ae..da171c202 100644 --- a/tests/auto/client/shared/coreprotocol.h +++ b/tests/auto/client/shared/coreprotocol.h @@ -38,6 +38,7 @@ namespace MockCompositor { class WlCompositor; class Output; class Pointer; +class Keyboard; class CursorRole; class ShmPool; class ShmBuffer; @@ -245,6 +246,9 @@ public: Pointer* m_pointer = nullptr; QVector m_oldPointers; + Keyboard* m_keyboard = nullptr; + QVector m_oldKeyboards; + uint m_capabilities = 0; protected: @@ -254,7 +258,7 @@ protected: } void seat_get_pointer(Resource *resource, uint32_t id) override; -// void seat_get_keyboard(Resource *resource, uint32_t id) override; + void seat_get_keyboard(Resource *resource, uint32_t id) override; // void seat_get_touch(Resource *resource, uint32_t id) override; // void seat_release(Resource *resource) override; @@ -294,6 +298,18 @@ public: Surface *m_surface = nullptr; }; +class Keyboard : public QObject, public QtWaylandServer::wl_keyboard +{ + Q_OBJECT +public: + explicit Keyboard(Seat *seat) : m_seat(seat) {} + //TODO: Keymap event + uint sendEnter(Surface *surface); + uint sendLeave(Surface *surface); + uint sendKey(wl_client *client, uint key, uint state); + Seat *m_seat = nullptr; +}; + class Shm : public Global, public QtWaylandServer::wl_shm { Q_OBJECT diff --git a/tests/auto/client/shared/mockcompositor.cpp b/tests/auto/client/shared/mockcompositor.cpp index bb7cd6f46..6b9af4295 100644 --- a/tests/auto/client/shared/mockcompositor.cpp +++ b/tests/auto/client/shared/mockcompositor.cpp @@ -41,7 +41,7 @@ DefaultCompositor::DefaultCompositor() add(); auto *output = add(); output->m_data.physicalSize = output->m_data.mode.physicalSizeForDpi(96); - add(Seat::capability_pointer); + add(Seat::capability_pointer | Seat::capability_keyboard); add(); add(); // TODO: other shells, viewporter, xdgoutput etc diff --git a/tests/auto/client/shared/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h index c7ea4d009..a6515c04c 100644 --- a/tests/auto/client/shared/mockcompositor.h +++ b/tests/auto/client/shared/mockcompositor.h @@ -53,6 +53,7 @@ public: XdgToplevel *xdgToplevel(int i = 0) { return get()->toplevel(i); } XdgPopup *xdgPopup(int i = 0) { return get()->popup(i); } Pointer *pointer() { auto *seat = get(); Q_ASSERT(seat); return seat->m_pointer; } + Keyboard *keyboard() { auto *seat = get(); Q_ASSERT(seat); return seat->m_keyboard; } uint sendXdgShellPing(); void xdgPingAndWaitForPong(); // Things that can be changed run-time without confusing the client (i.e. don't require separate tests) -- cgit v1.2.3