KWin
Loading...
Searching...
No Matches
sticky_keys_test.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2023 Nicolas Fella <nicolas.fella@gmx.de>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10#include "kwin_wayland_test.h"
11
12#include "keyboard_input.h"
13#include "pluginmanager.h"
14#include "pointer_input.h"
15#include "wayland_server.h"
16#include "window.h"
17#include "workspace.h"
18
19#include <KWayland/Client/keyboard.h>
20#include <KWayland/Client/seat.h>
21
22#include <linux/input.h>
23
24namespace KWin
25{
26
27static const QString s_socketName = QStringLiteral("wayland_test_kwin_sticky_keys-0");
28
29class StickyKeysTest : public QObject
30{
31 Q_OBJECT
32private Q_SLOTS:
33 void initTestCase();
34 void init();
35 void cleanup();
36 void testStick();
37 void testLock();
38};
39
40void StickyKeysTest::initTestCase()
41{
42 KConfig kaccessConfig("kaccessrc");
43 kaccessConfig.group(QStringLiteral("Keyboard")).writeEntry("StickyKeys", true);
44 kaccessConfig.sync();
45
46 qRegisterMetaType<KWin::Window *>();
47 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
48 QVERIFY(waylandServer()->init(s_socketName));
50 QRect(0, 0, 1280, 1024),
51 QRect(1280, 0, 1280, 1024),
52 });
53
54 qputenv("XKB_DEFAULT_RULES", "evdev");
55
56 kwinApp()->start();
57 QVERIFY(applicationStartedSpy.wait());
58}
59
60void StickyKeysTest::init()
61{
64}
65
66void StickyKeysTest::cleanup()
67{
69}
70
71void StickyKeysTest::testStick()
72{
73 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
74
75 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
76 QVERIFY(surface != nullptr);
77 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
78 QVERIFY(shellSurface != nullptr);
79 Window *waylandWindow = Test::renderAndWaitForShown(surface.get(), QSize(10, 10), Qt::blue);
80 QVERIFY(waylandWindow);
81
82 QSignalSpy modifierSpy(keyboard.get(), &KWayland::Client::Keyboard::modifiersChanged);
83 QVERIFY(modifierSpy.wait());
84 modifierSpy.clear();
85
86 quint32 timestamp = 0;
87
88 // press Ctrl to latch it
89 Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp);
90 QVERIFY(modifierSpy.wait());
91 // arguments are: quint32 depressed, quint32 latched, quint32 locked, quint32 group
92 QCOMPARE(modifierSpy.first()[0], 4); // verify that Ctrl is depressed
93 QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is latched
94
95 modifierSpy.clear();
96 // release Ctrl, the modified should still be latched
97 Test::keyboardKeyReleased(KEY_LEFTCTRL, ++timestamp);
98 QVERIFY(modifierSpy.wait());
99 QCOMPARE(modifierSpy.first()[0], 0); // verify that Ctrl is not depressed
100 QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is still latched
101
102 // press and release a letter, this unlatches the modifier
103 modifierSpy.clear();
104 Test::keyboardKeyPressed(KEY_A, ++timestamp);
105 QVERIFY(modifierSpy.wait());
106 QCOMPARE(modifierSpy.first()[0], 0); // verify that Ctrl is not depressed
107 QCOMPARE(modifierSpy.first()[1], 0); // verify that Ctrl is not latched any more
108
109 Test::keyboardKeyReleased(KEY_A, ++timestamp);
110}
111
112void StickyKeysTest::testLock()
113{
114 KConfig kaccessConfig("kaccessrc");
115 kaccessConfig.group(QStringLiteral("Keyboard")).writeEntry("StickyKeysLatch", true);
116 kaccessConfig.sync();
117
118 // reload the plugin to pick up the new config
119 kwinApp()->pluginManager()->unloadPlugin("StickyKeysPlugin");
120 kwinApp()->pluginManager()->loadPlugin("StickyKeysPlugin");
121
122 QVERIFY(Test::waylandSeat()->hasKeyboard());
123 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard());
124
125 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
126 QVERIFY(surface != nullptr);
127 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
128 QVERIFY(shellSurface != nullptr);
129 Window *waylandWindow = Test::renderAndWaitForShown(surface.get(), QSize(10, 10), Qt::blue);
130 QVERIFY(waylandWindow);
131 waylandWindow->move(QPoint(0, 0));
132
133 QSignalSpy modifierSpy(keyboard.get(), &KWayland::Client::Keyboard::modifiersChanged);
134 QVERIFY(modifierSpy.wait());
135 modifierSpy.clear();
136
137 quint32 timestamp = 0;
138
139 // press Ctrl to latch it
140 Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp);
141 QVERIFY(modifierSpy.wait());
142 // arguments are: quint32 depressed, quint32 latched, quint32 locked, quint32 group
143 QCOMPARE(modifierSpy.first()[0], 4); // verify that Ctrl is depressed
144 QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is latched
145
146 modifierSpy.clear();
147 // release Ctrl, the modified should still be latched
148 Test::keyboardKeyReleased(KEY_LEFTCTRL, ++timestamp);
149 QVERIFY(modifierSpy.wait());
150 QCOMPARE(modifierSpy.first()[0], 0); // verify that Ctrl is not depressed
151 QCOMPARE(modifierSpy.first()[1], 4); // verify that Ctrl is still latched
152
153 // press Ctrl again to lock it
154 modifierSpy.clear();
155 Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp);
156 QVERIFY(modifierSpy.wait());
157 QCOMPARE(modifierSpy.first()[0], 4); // verify that Ctrl is depressed
158 // TODO should it be latched?
159 QCOMPARE(modifierSpy.first()[2], 4); // verify that Ctrl is locked
160
161 // press and release a letter, this does not unlock the modifier
162 modifierSpy.clear();
163 Test::keyboardKeyPressed(KEY_A, ++timestamp);
164 QVERIFY(!modifierSpy.wait(10));
165
166 Test::keyboardKeyReleased(KEY_A, ++timestamp);
167 QVERIFY(!modifierSpy.wait(10));
168
169 // press Ctrl again to unlock it
170 Test::keyboardKeyPressed(KEY_LEFTCTRL, ++timestamp);
171 QVERIFY(modifierSpy.wait());
172 QCOMPARE(modifierSpy.first()[0], 4); // verify that Ctrl is depressed
173 QCOMPARE(modifierSpy.first()[2], 0); // verify that Ctrl is locked
174
175 Test::keyboardKeyReleased(KEY_LEFTCTRL, ++timestamp);
176}
177}
178
180#include "sticky_keys_test.moc"
#define WAYLANDTEST_MAIN(TestObject)
Window * renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32, int timeout=5000)
void keyboardKeyReleased(quint32 key, quint32 time)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
void keyboardKeyPressed(quint32 key, quint32 time)
bool waitForWaylandKeyboard()
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
KWayland::Client::Seat * waylandSeat()
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
WaylandServer * waylandServer()