summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp41
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.h2
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard_p.h3
-rw-r--r--src/compositor/compositor_api/qwaylandseat.cpp44
-rw-r--r--src/compositor/compositor_api/qwaylandseat.h1
-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
11 files changed, 382 insertions, 10 deletions
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index 7ab8bff9e..c172bca85 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -54,6 +54,7 @@
#if QT_CONFIG(xkbcommon_evdev)
#include <sys/mman.h>
#include <sys/types.h>
+#include <qwaylandxkb_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -196,6 +197,32 @@ void QWaylandKeyboardPrivate::modifiers(uint32_t serial, uint32_t mods_depressed
}
}
+#if QT_CONFIG(xkbcommon_evdev)
+void QWaylandKeyboardPrivate::maybeUpdateXkbScanCodeTable()
+{
+ if (!scanCodesByQtKey.isEmpty() || !xkbState())
+ return;
+
+ if (xkb_keymap *keymap = xkb_state_get_keymap(xkb_state)) {
+ xkb_keymap_key_for_each(keymap, [](xkb_keymap *keymap, xkb_keycode_t keycode, void *d){
+ auto *scanCodesByQtKey = static_cast<QMap<ScanCodeKey, uint>*>(d);
+ uint numLayouts = xkb_keymap_num_layouts_for_key(keymap, keycode);
+ for (uint layout = 0; layout < numLayouts; ++layout) {
+ const xkb_keysym_t *syms = nullptr;
+ xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, 0, &syms);
+ if (!syms)
+ continue;
+
+ Qt::KeyboardModifiers mods = {};
+ int qtKey = QWaylandXkb::keysymToQtKey(syms[0], mods).first;
+ if (qtKey != 0)
+ scanCodesByQtKey->insert({layout, qtKey}, keycode);
+ }
+ }, &scanCodesByQtKey);
+ }
+}
+#endif
+
void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state)
{
#if QT_CONFIG(xkbcommon_evdev)
@@ -355,6 +382,7 @@ void QWaylandKeyboardPrivate::createXKBKeymap()
struct xkb_keymap *xkbKeymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast<xkb_keymap_compile_flags>(0));
if (xkbKeymap) {
+ scanCodesByQtKey.clear();
createXKBState(xkbKeymap);
xkb_keymap_unref(xkbKeymap);
} else {
@@ -561,4 +589,17 @@ void QWaylandKeyboard::addClient(QWaylandClient *client, uint32_t id, uint32_t v
d->add(client->client(), id, qMin<uint32_t>(QtWaylandServer::wl_keyboard::interfaceVersion(), version));
}
+uint QWaylandKeyboard::toScanCode(int qtKey) const
+{
+ uint scanCode = 0;
+#if QT_CONFIG(xkbcommon_evdev)
+ Q_D(const QWaylandKeyboard);
+ const_cast<QWaylandKeyboardPrivate *>(d)->maybeUpdateXkbScanCodeTable();
+ scanCode = d->scanCodesByQtKey.value({d->group, qtKey}, 0);
+#else
+ Q_UNUSED(qtKey);
+#endif
+ return scanCode;
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.h b/src/compositor/compositor_api/qwaylandkeyboard.h
index 580f0c4ed..e5d5e086e 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.h
+++ b/src/compositor/compositor_api/qwaylandkeyboard.h
@@ -82,6 +82,8 @@ public:
virtual void addClient(QWaylandClient *client, uint32_t id, uint32_t version);
+ uint toScanCode(int qtKey) const;
+
Q_SIGNALS:
void focusChanged(QWaylandSurface *surface);
void repeatRateChanged(quint32 repeatRate);
diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h
index 6db312cfb..cd1f27956 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard_p.h
+++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h
@@ -89,6 +89,7 @@ public:
#if QT_CONFIG(xkbcommon_evdev)
struct xkb_state *xkbState() const { return xkb_state; }
uint32_t xkbModsMask() const { return modsDepressed | modsLatched | modsLocked; }
+ void maybeUpdateXkbScanCodeTable();
#endif
void keyEvent(uint code, uint32_t state);
@@ -131,6 +132,8 @@ private:
size_t keymap_size;
int keymap_fd = -1;
char *keymap_area = nullptr;
+ using ScanCodeKey = std::pair<uint,int>; // group/layout and QtKey
+ QMap<ScanCodeKey, uint> scanCodesByQtKey;
struct xkb_context *xkb_context = nullptr;
struct xkb_state *xkb_state = nullptr;
#endif
diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp
index c67e6020d..957f5ea83 100644
--- a/src/compositor/compositor_api/qwaylandseat.cpp
+++ b/src/compositor/compositor_api/qwaylandseat.cpp
@@ -440,10 +440,50 @@ void QWaylandSeat::sendFullKeyEvent(QKeyEvent *event)
return;
if (!d->keyboard.isNull() && !event->isAutoRepeat()) {
+
+ uint scanCode = event->nativeScanCode();
+ if (scanCode == 0)
+ scanCode = d->keyboard->toScanCode(event->key());
+
+ if (scanCode == 0) {
+ qWarning() << "Can't send Wayland key event: Unable to get a valid scan code";
+ return;
+ }
+
if (event->type() == QEvent::KeyPress)
- d->keyboard->sendKeyPressEvent(event->nativeScanCode());
+ d->keyboard->sendKeyPressEvent(scanCode);
else if (event->type() == QEvent::KeyRelease)
- d->keyboard->sendKeyReleaseEvent(event->nativeScanCode());
+ d->keyboard->sendKeyReleaseEvent(scanCode);
+ }
+}
+
+/*!
+ * \qmlmethod void QtWaylandCompositor::WaylandSeat::sendKeyEvent(int qtKey, bool pressed)
+ * \since 5.12
+ *
+ * Sends a key press or release to the keyboard device.
+ */
+
+/*!
+ * Sends a key press or release to the keyboard device.
+ *
+ * \since 5.12
+ */
+void QWaylandSeat::sendKeyEvent(int qtKey, bool pressed)
+{
+ Q_D(QWaylandSeat);
+ if (!keyboardFocus()) {
+ qWarning("Cannot send Wayland key event, no keyboard focus, fix the compositor");
+ return;
+ }
+
+ if (auto scanCode = d->keyboard->toScanCode(qtKey)) {
+ if (pressed)
+ d->keyboard->sendKeyPressEvent(scanCode);
+ else
+ d->keyboard->sendKeyReleaseEvent(scanCode);
+ } else {
+ qWarning() << "Can't send Wayland key event: Unable to get scan code for" << Qt::Key(qtKey);
}
}
diff --git a/src/compositor/compositor_api/qwaylandseat.h b/src/compositor/compositor_api/qwaylandseat.h
index f438b6639..6a4d6e176 100644
--- a/src/compositor/compositor_api/qwaylandseat.h
+++ b/src/compositor/compositor_api/qwaylandseat.h
@@ -97,6 +97,7 @@ public:
void sendKeyReleaseEvent(uint code);
void sendFullKeyEvent(QKeyEvent *event);
+ Q_INVOKABLE void sendKeyEvent(int qtKey, bool pressed);
uint sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state);
Q_INVOKABLE uint sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position);
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);