summaryrefslogtreecommitdiffstats
path: root/tests/auto/compositor
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2018-03-27 15:30:26 +0200
committerJohan Helsing <johan.helsing@qt.io>2018-04-27 10:17:10 +0000
commitbd5917025fe7491c9f24e99c20484c7ffce9f172 (patch)
tree006435d90eb25738b04a2c86aa45c0b3e8babdf1 /tests/auto/compositor
parent531a767040782007181bb13583fe69b4ba4b1ba3 (diff)
Add QWaylandSeat::sendKeyEvent(int qtKey, bool pressed)
Makes it possible to send keyboard events using the QML API: Button { onPressedChanged: seat.sendKeyEvent(Qt.Key_Left, pressed) } The wl_keyboard.key event requires a keyboard scan code, so in order to get this we iterate over all the keys in the current keymap checking which QtKey they map to, storing the results in a QMap which is reused by later calls to QWaylandKeymap::toScanCode. This also fixes a bug when sending QKeyEvents without a native scan code using QWaylandSeat::sendFullKeyEvent. (generated key events have no nativeScanCode). Now we try QWaylandKeyboard::toScanCode, and if unsuccessful we return with a warning instead of letting the assertion in QWaylandKeyboard fail. This also adds more thorough testing for the keyboard, including keymaps and checking that the events, including enter and leave, are actually received on the client side. Change-Id: I601b0c7d909071863abb146bd65a990215dcaff7 Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'tests/auto/compositor')
-rw-r--r--tests/auto/compositor/compositor/compositor.pro2
-rw-r--r--tests/auto/compositor/compositor/mockkeyboard.cpp101
-rw-r--r--tests/auto/compositor/compositor/mockkeyboard.h50
-rw-r--r--tests/auto/compositor/compositor/mockseat.cpp5
-rw-r--r--tests/auto/compositor/compositor/mockseat.h4
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp139
6 files changed, 293 insertions, 8 deletions
diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro
index 2919fa4bb..68b18c974 100644
--- a/tests/auto/compositor/compositor/compositor.pro
+++ b/tests/auto/compositor/compositor/compositor.pro
@@ -21,6 +21,7 @@ SOURCES += \
mockclient.cpp \
mockseat.cpp \
testseat.cpp \
+ mockkeyboard.cpp \
mockpointer.cpp
HEADERS += \
@@ -29,4 +30,5 @@ HEADERS += \
mockclient.h \
mockseat.h \
testseat.h \
+ mockkeyboard.h \
mockpointer.h
diff --git a/tests/auto/compositor/compositor/mockkeyboard.cpp b/tests/auto/compositor/compositor/mockkeyboard.cpp
new file mode 100644
index 000000000..e5f5f8d36
--- /dev/null
+++ b/tests/auto/compositor/compositor/mockkeyboard.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mockkeyboard.h"
+
+void keyboardKeymap(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size)
+{
+ Q_UNUSED(keyboard);
+ Q_UNUSED(wl_keyboard);
+ Q_UNUSED(format);
+ Q_UNUSED(fd);
+ Q_UNUSED(size);
+}
+
+void keyboardEnter(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
+{
+ Q_UNUSED(wl_keyboard);
+ Q_UNUSED(serial);
+ Q_UNUSED(surface);
+ Q_UNUSED(keys);
+
+ static_cast<MockKeyboard *>(keyboard)->m_enteredSurface = surface;
+}
+
+void keyboardLeave(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface)
+{
+ Q_UNUSED(wl_keyboard);
+ Q_UNUSED(serial);
+ Q_UNUSED(surface);
+
+ static_cast<MockKeyboard *>(keyboard)->m_enteredSurface = nullptr;
+}
+
+void keyboardKey(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
+{
+ Q_UNUSED(keyboard);
+ Q_UNUSED(wl_keyboard);
+ Q_UNUSED(serial);
+ Q_UNUSED(time);
+ Q_UNUSED(key);
+ Q_UNUSED(state);
+ auto kb = static_cast<MockKeyboard *>(keyboard);
+ kb->m_lastKeyCode = key;
+ kb->m_lastKeyState = state;
+}
+
+void keyboardModifiers(void *keyboard, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
+{
+ Q_UNUSED(keyboard);
+ Q_UNUSED(wl_keyboard);
+ Q_UNUSED(serial);
+ Q_UNUSED(mods_depressed);
+ Q_UNUSED(mods_latched);
+ Q_UNUSED(mods_locked);
+ auto kb = static_cast<MockKeyboard *>(keyboard);
+ kb->m_group = group;
+}
+
+static const struct wl_keyboard_listener keyboardListener = {
+ keyboardKeymap,
+ keyboardEnter,
+ keyboardLeave,
+ keyboardKey,
+ keyboardModifiers
+};
+
+MockKeyboard::MockKeyboard(wl_seat *seat)
+ : m_keyboard(wl_seat_get_keyboard(seat))
+{
+ wl_keyboard_add_listener(m_keyboard, &keyboardListener, this);
+}
+
+MockKeyboard::~MockKeyboard()
+{
+ wl_keyboard_destroy(m_keyboard);
+}
diff --git a/tests/auto/compositor/compositor/mockkeyboard.h b/tests/auto/compositor/compositor/mockkeyboard.h
new file mode 100644
index 000000000..1090db597
--- /dev/null
+++ b/tests/auto/compositor/compositor/mockkeyboard.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MOCKKEYBOARD_H
+#define MOCKKEYBOARD_H
+
+#include <QObject>
+#include <wayland-client.h>
+
+class MockKeyboard : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit MockKeyboard(wl_seat *seat);
+ ~MockKeyboard() override;
+
+ wl_keyboard *m_keyboard = nullptr;
+ wl_surface *m_enteredSurface = nullptr;
+ uint m_lastKeyCode = 0;
+ uint m_lastKeyState = 0;
+ uint m_group = 0;
+};
+
+#endif // MOCKKEYBOARD_H
diff --git a/tests/auto/compositor/compositor/mockseat.cpp b/tests/auto/compositor/compositor/mockseat.cpp
index 052c2f90b..ce873c129 100644
--- a/tests/auto/compositor/compositor/mockseat.cpp
+++ b/tests/auto/compositor/compositor/mockseat.cpp
@@ -31,14 +31,11 @@
MockSeat::MockSeat(wl_seat *seat)
: m_seat(seat)
, m_pointer(new MockPointer(seat))
+ , m_keyboard(new MockKeyboard(seat))
{
- // Bind to the keyboard interface so that the compositor has
- // the right resource associations
- m_keyboard = wl_seat_get_keyboard(seat);
}
MockSeat::~MockSeat()
{
- wl_keyboard_destroy(m_keyboard);
wl_seat_destroy(m_seat);
}
diff --git a/tests/auto/compositor/compositor/mockseat.h b/tests/auto/compositor/compositor/mockseat.h
index 73d289281..f8c103ed4 100644
--- a/tests/auto/compositor/compositor/mockseat.h
+++ b/tests/auto/compositor/compositor/mockseat.h
@@ -29,6 +29,7 @@
#define MOCKSEAT
#include "mockpointer.h"
+#include "mockkeyboard.h"
#include <QObject>
#include <wayland-client.h>
@@ -41,12 +42,13 @@ public:
MockSeat(wl_seat *seat);
~MockSeat() override;
MockPointer *pointer() const { return m_pointer.data(); }
+ MockKeyboard *keyboard() const { return m_keyboard.data(); }
wl_seat *m_seat = nullptr;
- wl_keyboard *m_keyboard = nullptr;
private:
QScopedPointer<MockPointer> m_pointer;
+ QScopedPointer<MockKeyboard> m_keyboard;
};
#endif
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index 575ea6466..2f00f2a83 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -40,10 +40,12 @@
#include <QtGui/QScreen>
#include <QtWaylandCompositor/QWaylandXdgShellV5>
#include <QtWaylandCompositor/private/qwaylandxdgshellv6_p.h>
+#include <QtWaylandCompositor/private/qwaylandkeyboard_p.h>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
#include <QtWaylandCompositor/QWaylandSurface>
#include <QtWaylandCompositor/QWaylandResource>
+#include <QtWaylandCompositor/QWaylandKeymap>
#include <qwayland-xdg-shell.h>
#include <qwayland-ivi-application.h>
@@ -56,6 +58,11 @@ class tst_WaylandCompositor : public QObject
private slots:
void init();
void seatCapabilities();
+#if QT_CONFIG(xkbcommon_evdev)
+ void simpleKeyboard();
+ void keyboardKeymaps();
+ void keyboardLayoutSwitching();
+#endif
void keyboardGrab();
void seatCreation();
void seatKeyboardFocus();
@@ -160,6 +167,121 @@ void tst_WaylandCompositor::multipleClients()
QTRY_COMPARE(compositor.surfaces.size(), 0);
}
+#if QT_CONFIG(xkbcommon_evdev)
+
+void tst_WaylandCompositor::simpleKeyboard()
+{
+ TestCompositor compositor;
+ compositor.create();
+
+ QWaylandSeat* seat = compositor.defaultSeat();
+ seat->keymap()->setLayout("us");
+
+ MockClient client;
+
+ QTRY_COMPARE(client.m_seats.size(), 1);
+ MockKeyboard *mockKeyboard = client.m_seats.at(0)->keyboard();
+
+ wl_surface *mockSurface = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+ seat->setKeyboardFocus(compositor.surfaces.at(0));
+
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_enteredSurface, mockSurface);
+
+ seat->sendKeyEvent(Qt::Key_A, true);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyState, 1u);
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 30u); // 30 is the scan code for A on us keyboard layouts
+
+ seat->sendKeyEvent(Qt::Key_A, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyState, 0u);
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 30u);
+
+ seat->sendKeyEvent(Qt::Key_Super_L, true);
+ seat->sendKeyEvent(Qt::Key_Super_L, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 125u);
+}
+
+void tst_WaylandCompositor::keyboardKeymaps()
+{
+ TestCompositor compositor;
+ compositor.create();
+ QWaylandSeat* seat = compositor.defaultSeat();
+ MockClient client;
+ QTRY_COMPARE(client.m_seats.size(), 1);
+ MockKeyboard *mockKeyboard = client.m_seats.at(0)->keyboard();
+ client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+ seat->setKeyboardFocus(compositor.surfaces.at(0));
+
+ seat->keymap()->setLayout("us");
+
+ seat->sendKeyEvent(Qt::Key_Y, true);
+ seat->sendKeyEvent(Qt::Key_Y, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 21u);
+
+ seat->sendKeyEvent(Qt::Key_Z, true);
+ seat->sendKeyEvent(Qt::Key_Z, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 44u);
+
+ seat->keymap()->setLayout("de"); // In the German layout y and z have changed places
+
+ seat->sendKeyEvent(Qt::Key_Y, true);
+ seat->sendKeyEvent(Qt::Key_Y, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 44u);
+
+ seat->sendKeyEvent(Qt::Key_Z, true);
+ seat->sendKeyEvent(Qt::Key_Z, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 21u);
+}
+
+void tst_WaylandCompositor::keyboardLayoutSwitching()
+{
+ TestCompositor compositor;
+ compositor.create();
+ QWaylandSeat* seat = compositor.defaultSeat();
+ MockClient client;
+ QTRY_COMPARE(client.m_seats.size(), 1);
+ MockKeyboard *mockKeyboard = client.m_seats.at(0)->keyboard();
+ client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+ seat->setKeyboardFocus(compositor.surfaces.at(0));
+
+ seat->keymap()->setLayout("us,de");
+ seat->keymap()->setOptions("grp:lalt_toggle"); //toggle keyboard layout with left alt
+
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_group, 0u);
+
+ seat->sendKeyEvent(Qt::Key_Y, true);
+ seat->sendKeyEvent(Qt::Key_Y, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 21u);
+
+ // It's not currently possible to switch layouts programmatically with the public APIs
+ // We will just fake it with the private APIs here.
+ auto keyboardPrivate = QWaylandKeyboardPrivate::get(seat->keyboard());
+ const uint leftAltCode = 64;
+ keyboardPrivate->updateModifierState(leftAltCode, WL_KEYBOARD_KEY_STATE_PRESSED);
+ keyboardPrivate->updateModifierState(leftAltCode, WL_KEYBOARD_KEY_STATE_RELEASED);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_group, 1u);
+
+ seat->sendKeyEvent(Qt::Key_Y, true);
+ seat->sendKeyEvent(Qt::Key_Y, false);
+ compositor.flushClients();
+ QTRY_COMPARE(mockKeyboard->m_lastKeyCode, 44u);
+}
+
+#endif // QT_CONFIG(xkbcommon_evdev)
+
void tst_WaylandCompositor::keyboardGrab()
{
TestCompositor compositor;
@@ -448,13 +570,24 @@ void tst_WaylandCompositor::seatKeyboardFocus()
// Create client after all the input devices have been set up as the mock client
// does not dynamically listen to new seats
MockClient client;
+
+ QTRY_COMPARE(client.m_seats.size(), 1);
+ MockKeyboard *mockKeyboard = client.m_seats.first()->keyboard();
+ QVERIFY(mockKeyboard);
+ QCOMPARE(mockKeyboard->m_enteredSurface, nullptr);
+
wl_surface *surface = client.createSurface();
QTRY_COMPARE(compositor.surfaces.size(), 1);
QWaylandSurface *waylandSurface = compositor.surfaces.at(0);
- QWaylandSeat* dev = compositor.defaultSeat();
- dev->setKeyboardFocus(waylandSurface);
- QTRY_COMPARE(compositor.defaultSeat()->keyboardFocus(), waylandSurface);
+ QWaylandSeat* seat = compositor.defaultSeat();
+ QVERIFY(seat->setKeyboardFocus(waylandSurface));
+ QCOMPARE(compositor.defaultSeat()->keyboardFocus(), waylandSurface);
+
+ compositor.flushClients();
+
+ qDebug() << mockKeyboard->m_enteredSurface;
+ QTRY_COMPARE(mockKeyboard->m_enteredSurface, surface);
wl_surface_destroy(surface);
QTRY_VERIFY(compositor.surfaces.size() == 0);