diff options
author | Johan Klokkhammer Helsing <johan.helsing@qt.io> | 2018-03-27 15:30:26 +0200 |
---|---|---|
committer | Johan Helsing <johan.helsing@qt.io> | 2018-04-27 10:17:10 +0000 |
commit | bd5917025fe7491c9f24e99c20484c7ffce9f172 (patch) | |
tree | 006435d90eb25738b04a2c86aa45c0b3e8babdf1 /tests/auto/compositor/compositor/tst_compositor.cpp | |
parent | 531a767040782007181bb13583fe69b4ba4b1ba3 (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/compositor/tst_compositor.cpp')
-rw-r--r-- | tests/auto/compositor/compositor/tst_compositor.cpp | 139 |
1 files changed, 136 insertions, 3 deletions
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); |