KWin
Loading...
Searching...
No Matches
keyboard_layout_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: 2017 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "keyboard_input.h"
12#include "keyboard_layout.h"
13#include "virtualdesktops.h"
14#include "wayland_server.h"
15#include "window.h"
16#include "workspace.h"
17#include "xkb.h"
18
19#include <KConfigGroup>
20#include <KGlobalAccel>
21
22#include <KWayland/Client/surface.h>
23
24#include <QAction>
25#include <QDBusConnection>
26#include <QDBusConnectionInterface>
27#include <QDBusMessage>
28#include <QDBusPendingCall>
29
30#include <linux/input.h>
31
32using namespace KWin;
33
34static const QString s_socketName = QStringLiteral("wayland_test_kwin_keyboard_laout-0");
35
36class KeyboardLayoutTest : public QObject
37{
38 Q_OBJECT
39public:
41 : layoutsReconfiguredSpy(this, &KeyboardLayoutTest::layoutListChanged)
42 , layoutChangedSpy(this, &KeyboardLayoutTest::layoutChanged)
43 {
44
45 QVERIFY(QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("layoutListChanged"), this, SIGNAL(layoutListChanged())));
46 QVERIFY(QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("layoutChanged"), this, SIGNAL(layoutChanged(uint))));
47 }
48
49Q_SIGNALS:
50 void layoutChanged(uint index);
52
53private Q_SLOTS:
54 void initTestCase();
55 void init();
56 void cleanup();
57
58 void testReconfigure();
59 void testChangeLayoutThroughDBus();
60 void testPerLayoutShortcut();
61 void testDBusServiceExport();
62 void testVirtualDesktopPolicy();
63 void testWindowPolicy();
64 void testApplicationPolicy();
65 void testNumLock();
66
67private:
68 void reconfigureLayouts();
69 void resetLayouts();
70 auto changeLayout(uint index);
71 void callSession(const QString &method);
72 QSignalSpy layoutsReconfiguredSpy;
73 QSignalSpy layoutChangedSpy;
74 KConfigGroup layoutGroup;
75};
76
77void KeyboardLayoutTest::reconfigureLayouts()
78{
79 // create DBus signal to reload
80 QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/Layouts"), QStringLiteral("org.kde.keyboard"), QStringLiteral("reloadConfig"));
81 QVERIFY(QDBusConnection::sessionBus().send(message));
82
83 QVERIFY(layoutsReconfiguredSpy.wait(1000));
84 QCOMPARE(layoutsReconfiguredSpy.count(), 1);
85 layoutsReconfiguredSpy.clear();
86}
87
88void KeyboardLayoutTest::resetLayouts()
89{
90 /* Switch Policy to destroy layouts from memory.
91 * On return to original Policy they should reload from disk.
92 */
93 callSession(QStringLiteral("aboutToSaveSession"));
94
95 const QString policy = layoutGroup.readEntry("SwitchMode", "Global");
96
97 if (policy == QLatin1String("Global")) {
98 layoutGroup.writeEntry("SwitchMode", "Desktop");
99 } else {
100 layoutGroup.deleteEntry("SwitchMode");
101 }
102 reconfigureLayouts();
103
104 layoutGroup.writeEntry("SwitchMode", policy);
105 reconfigureLayouts();
106
107 callSession(QStringLiteral("loadSession"));
108}
109
110auto KeyboardLayoutTest::changeLayout(uint index)
111{
112 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.keyboard"),
113 QStringLiteral("/Layouts"),
114 QStringLiteral("org.kde.KeyboardLayouts"),
115 QStringLiteral("setLayout"));
116 msg << index;
117 return QDBusConnection::sessionBus().asyncCall(msg);
118}
119
120void KeyboardLayoutTest::callSession(const QString &method)
121{
122 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
123 QStringLiteral("/Session"),
124 QStringLiteral("org.kde.KWin.Session"),
125 method);
126 msg << QLatin1String(); // session name
127 QVERIFY(QDBusConnection::sessionBus().call(msg).type() != QDBusMessage::ErrorMessage);
128}
129
130void KeyboardLayoutTest::initTestCase()
131{
132 qRegisterMetaType<KWin::Window *>();
133 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
134 QVERIFY(waylandServer()->init(s_socketName));
136 QRect(0, 0, 1280, 1024),
137 QRect(1280, 0, 1280, 1024),
138 });
139
140 kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
141 kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
142 kwinApp()->setInputConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
143
144 layoutGroup = kwinApp()->kxkbConfig()->group(QStringLiteral("Layout"));
145 layoutGroup.deleteGroup();
146
147 kwinApp()->start();
148 QVERIFY(applicationStartedSpy.wait());
149
150 // don't get DBus signal on one-layout configuration
151 // QVERIFY(layoutsReconfiguredSpy.wait());
152 // QCOMPARE(layoutsReconfiguredSpy.count(), 1);
153 // layoutsReconfiguredSpy.clear();
154}
155
156void KeyboardLayoutTest::init()
157{
159}
160
161void KeyboardLayoutTest::cleanup()
162{
164}
165
166void KeyboardLayoutTest::testReconfigure()
167{
168 // verifies that we can change the keymap
169
170 // default should be a keymap with only us layout
171 auto xkb = input()->keyboard()->xkb();
172 QCOMPARE(xkb->numberOfLayouts(), 1u);
173 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
174 QCOMPARE(xkb->numberOfLayouts(), 1);
175 QCOMPARE(xkb->layoutName(0), QStringLiteral("English (US)"));
176
177 // create a new keymap
178 KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group(QStringLiteral("Layout"));
179 layoutGroup.writeEntry("LayoutList", QStringLiteral("de,us"));
180 layoutGroup.sync();
181
182 reconfigureLayouts();
183 // now we should have two layouts
184 QCOMPARE(xkb->numberOfLayouts(), 2u);
185 // default layout is German
186 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
187 QCOMPARE(xkb->numberOfLayouts(), 2);
188 QCOMPARE(xkb->layoutName(0), QStringLiteral("German"));
189 QCOMPARE(xkb->layoutName(1), QStringLiteral("English (US)"));
190}
191
192void KeyboardLayoutTest::testChangeLayoutThroughDBus()
193{
194 // this test verifies that the layout can be changed through DBus
195 // first configure layouts
196 enum Layout {
197 de,
198 us,
199 de_neo,
200 bad,
201 };
202 layoutGroup.writeEntry("LayoutList", QStringLiteral("de,us,de(neo)"));
203 layoutGroup.sync();
204 reconfigureLayouts();
205 // now we should have three layouts
206 auto xkb = input()->keyboard()->xkb();
207 QCOMPARE(xkb->numberOfLayouts(), 3u);
208 // default layout is German
209 xkb->switchToLayout(0);
210 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
211
212 // place garbage to layout entry
213 layoutGroup.writeEntry("LayoutDefaultFoo", "garbage");
214 // make sure the garbage is wiped out on saving
215 resetLayouts();
216 QVERIFY(!layoutGroup.hasKey("LayoutDefaultFoo"));
217
218 // now change through DBus to English
219 auto reply = changeLayout(Layout::us);
220 reply.waitForFinished();
221 QVERIFY(!reply.isError());
222 QCOMPARE(reply.reply().arguments().first().toBool(), true);
223 QVERIFY(layoutChangedSpy.wait());
224 QCOMPARE(layoutChangedSpy.count(), 1);
225 layoutChangedSpy.clear();
226
227 // layout should persist after reset
228 resetLayouts();
229 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
230 QVERIFY(layoutChangedSpy.wait());
231 QCOMPARE(layoutChangedSpy.count(), 1);
232 layoutChangedSpy.clear();
233
234 // switch to a layout which does not exist
235 reply = changeLayout(Layout::bad);
236 QVERIFY(!reply.isError());
237 QCOMPARE(reply.reply().arguments().first().toBool(), false);
238 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
239 QVERIFY(!layoutChangedSpy.wait(1000));
240
241 // switch to another layout should work
242 reply = changeLayout(Layout::de);
243 QVERIFY(!reply.isError());
244 QCOMPARE(reply.reply().arguments().first().toBool(), true);
245 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
246 QVERIFY(layoutChangedSpy.wait(1000));
247 QCOMPARE(layoutChangedSpy.count(), 1);
248
249 // switching to same layout should also work
250 reply = changeLayout(Layout::de);
251 QVERIFY(!reply.isError());
252 QCOMPARE(reply.reply().arguments().first().toBool(), true);
253 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
254 QVERIFY(!layoutChangedSpy.wait(1000));
255}
256
257void KeyboardLayoutTest::testPerLayoutShortcut()
258{
259#if !KWIN_BUILD_GLOBALSHORTCUTS
260 QSKIP("Can't test shortcuts without shortcuts");
261 return;
262#endif
263
264 // this test verifies that per-layout global shortcuts are working correctly.
265 // first configure layouts
266 layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
267 layoutGroup.sync();
268
269 // and create the global shortcuts
270 const QString componentName = QStringLiteral("KDE Keyboard Layout Switcher");
271 QAction *a = new QAction(this);
272 a->setObjectName(QStringLiteral("Switch keyboard layout to English (US)"));
273 a->setProperty("componentName", componentName);
274 KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>{Qt::CTRL | Qt::ALT | Qt::Key_1}, KGlobalAccel::NoAutoloading);
275 delete a;
276 a = new QAction(this);
277 a->setObjectName(QStringLiteral("Switch keyboard layout to German"));
278 a->setProperty("componentName", componentName);
279 KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>{Qt::CTRL | Qt::ALT | Qt::Key_2}, KGlobalAccel::NoAutoloading);
280 delete a;
281
282 // now we should have three layouts
283 auto xkb = input()->keyboard()->xkb();
284 reconfigureLayouts();
285 QCOMPARE(xkb->numberOfLayouts(), 3u);
286 // default layout is English
287 xkb->switchToLayout(0);
288 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
289
290 // now switch to English through the global shortcut
291 quint32 timestamp = 1;
292 Test::keyboardKeyPressed(KEY_LEFTCTRL, timestamp++);
293 Test::keyboardKeyPressed(KEY_LEFTALT, timestamp++);
294 Test::keyboardKeyPressed(KEY_2, timestamp++);
295 QVERIFY(layoutChangedSpy.wait());
296 // now layout should be German
297 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
298 // release keys again
299 Test::keyboardKeyReleased(KEY_2, timestamp++);
300 // switch back to English
301 Test::keyboardKeyPressed(KEY_1, timestamp++);
302 QVERIFY(layoutChangedSpy.wait());
303 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
304 // release keys again
305 Test::keyboardKeyReleased(KEY_1, timestamp++);
306 Test::keyboardKeyReleased(KEY_LEFTALT, timestamp++);
307 Test::keyboardKeyReleased(KEY_LEFTCTRL, timestamp++);
308}
309
310void KeyboardLayoutTest::testDBusServiceExport()
311{
312 // verifies that the dbus service is only exported if there are at least two layouts
313
314 // first configure layouts, with just one layout
315 layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
316 layoutGroup.sync();
317 reconfigureLayouts();
318 auto xkb = input()->keyboard()->xkb();
319 QCOMPARE(xkb->numberOfLayouts(), 1u);
320 // default layout is English
321 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
322 // with one layout we should not have the dbus interface
323 QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
324
325 // reconfigure to two layouts
326 layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de"));
327 layoutGroup.sync();
328 reconfigureLayouts();
329 QCOMPARE(xkb->numberOfLayouts(), 2u);
330 QVERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
331
332 // and back to one layout
333 layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
334 layoutGroup.sync();
335 reconfigureLayouts();
336 QCOMPARE(xkb->numberOfLayouts(), 1u);
337 QVERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
338}
339
340void KeyboardLayoutTest::testVirtualDesktopPolicy()
341{
342 layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
343 layoutGroup.writeEntry("SwitchMode", QStringLiteral("Desktop"));
344 layoutGroup.sync();
345 reconfigureLayouts();
346 auto xkb = input()->keyboard()->xkb();
347 QCOMPARE(xkb->numberOfLayouts(), 3u);
348 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
349
350 VirtualDesktopManager::self()->setCount(4);
351 QCOMPARE(VirtualDesktopManager::self()->count(), 4u);
352 auto desktops = VirtualDesktopManager::self()->desktops();
353 QCOMPARE(desktops.count(), 4);
354
355 // give desktops different layouts
356 uint desktop, layout;
357 for (desktop = 0; desktop < VirtualDesktopManager::self()->count(); ++desktop) {
358 // switch to another virtual desktop
359 VirtualDesktopManager::self()->setCurrent(desktops.at(desktop));
360 QCOMPARE(desktops.at(desktop), VirtualDesktopManager::self()->currentDesktop());
361 // should be reset to English
362 QCOMPARE(xkb->currentLayout(), 0);
363 // change first desktop to German
364 layout = (desktop + 1) % xkb->numberOfLayouts();
365 changeLayout(layout).waitForFinished();
366 QCOMPARE(xkb->currentLayout(), layout);
367 }
368
369 // imitate app restart to test layouts saving feature
370 resetLayouts();
371
372 // check layout set on desktop switching as intended
373 for (--desktop;;) {
374 QCOMPARE(desktops.at(desktop), VirtualDesktopManager::self()->currentDesktop());
375 layout = (desktop + 1) % xkb->numberOfLayouts();
376 QCOMPARE(xkb->currentLayout(), layout);
377 if (--desktop >= VirtualDesktopManager::self()->count()) { // overflow
378 break;
379 }
380 VirtualDesktopManager::self()->setCurrent(desktops.at(desktop));
381 }
382
383 // remove virtual desktops
384 desktop = 0;
385 const KWin::VirtualDesktop *deletedDesktop = desktops.last();
386 VirtualDesktopManager::self()->setCount(1);
387 QCOMPARE(xkb->currentLayout(), layout = (desktop + 1) % xkb->numberOfLayouts());
388 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
389
390 // add another desktop
391 VirtualDesktopManager::self()->setCount(2);
392 // switching to it should result in going to default
393 desktops = VirtualDesktopManager::self()->desktops();
394 QCOMPARE(desktops.count(), 2);
395 QCOMPARE(desktops.first(), VirtualDesktopManager::self()->currentDesktop());
396 VirtualDesktopManager::self()->setCurrent(desktops.last());
397 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
398
399 // check there are no more layouts left in config than the last actual non-default layouts number
400 QSignalSpy deletedDesktopSpy(deletedDesktop, &VirtualDesktop::aboutToBeDestroyed);
401 QVERIFY(deletedDesktopSpy.wait());
402 resetLayouts();
403 QCOMPARE(layoutGroup.keyList().filter(QStringLiteral("LayoutDefault")).count(), 1);
404}
405
406void KeyboardLayoutTest::testWindowPolicy()
407{
408 enum Layout {
409 us,
410 de,
411 de_neo,
412 bad,
413 };
414 layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
415 layoutGroup.writeEntry("SwitchMode", QStringLiteral("Window"));
416 layoutGroup.sync();
417 reconfigureLayouts();
418 auto xkb = input()->keyboard()->xkb();
419 QCOMPARE(xkb->numberOfLayouts(), 3u);
420 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
421
422 // create a window
423 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
424 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
425 auto c1 = Test::renderAndWaitForShown(surface.get(), QSize(100, 100), Qt::blue);
426 QVERIFY(c1);
427
428 // now switch layout
429 auto reply = changeLayout(Layout::de);
430 reply.waitForFinished();
431 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
432
433 // create a second window
434 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
435 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
436 auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 100), Qt::red);
437 QVERIFY(c2);
438 // this should have switched back to English
439 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
440 // now change to another layout
441 reply = changeLayout(Layout::de_neo);
442 reply.waitForFinished();
443 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
444
445 // activate other window
447 QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
449 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
450}
451
452void KeyboardLayoutTest::testApplicationPolicy()
453{
454 enum Layout {
455 us,
456 de,
457 de_neo,
458 bad,
459 };
460 layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
461 layoutGroup.writeEntry("SwitchMode", QStringLiteral("WinClass"));
462 layoutGroup.sync();
463 reconfigureLayouts();
464 auto xkb = input()->keyboard()->xkb();
465 QCOMPARE(xkb->numberOfLayouts(), 3u);
466 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
467
468 // create a window
469 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
470 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
471 shellSurface->set_app_id(QStringLiteral("org.kde.foo"));
472 auto c1 = Test::renderAndWaitForShown(surface.get(), QSize(100, 100), Qt::blue);
473 QVERIFY(c1);
474
475 // create a second window
476 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface());
477 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
478 shellSurface2->set_app_id(QStringLiteral("org.kde.foo"));
479 auto c2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 100), Qt::red);
480 QVERIFY(c2);
481 // now switch layout
482 layoutChangedSpy.clear();
483 changeLayout(Layout::de_neo);
484 QVERIFY(layoutChangedSpy.wait());
485 QCOMPARE(layoutChangedSpy.count(), 1);
486 layoutChangedSpy.clear();
487 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
488
489 resetLayouts();
490 // to trigger layout application for current client
493 QVERIFY(layoutChangedSpy.wait());
494 QCOMPARE(layoutChangedSpy.count(), 1);
495 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
496
497 // activate other window
499 // it is the same application and should not switch the layout
500 QVERIFY(!layoutChangedSpy.wait(1000));
501 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
503 QVERIFY(!layoutChangedSpy.wait(1000));
504 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
505
506 shellSurface2.reset();
507 surface2.reset();
508 QVERIFY(Test::waitForWindowClosed(c2));
509 QVERIFY(!layoutChangedSpy.wait(1000));
510 QCOMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
511
512 resetLayouts();
513 QCOMPARE(layoutGroup.keyList().filter(QStringLiteral("LayoutDefault")).count(), 1);
514}
515
516void KeyboardLayoutTest::testNumLock()
517{
518 qputenv("KWIN_FORCE_NUM_LOCK_EVALUATION", "1");
519 layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
520 layoutGroup.sync();
521 reconfigureLayouts();
522
523 auto xkb = input()->keyboard()->xkb();
524 QCOMPARE(xkb->numberOfLayouts(), 1u);
525 QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
526
527 // by default not set
528 QVERIFY(!xkb->leds().testFlag(LED::NumLock));
529 quint32 timestamp = 0;
530 Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
531 Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
532 // now it should be on
533 QVERIFY(xkb->leds().testFlag(LED::NumLock));
534 // and back to off
535 Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
536 Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
537 QVERIFY(!xkb->leds().testFlag(LED::NumLock));
538
539 // let's reconfigure to enable through config
540 auto group = kwinApp()->inputConfig()->group(QStringLiteral("Keyboard"));
541 group.writeEntry("NumLock", 0);
542 group.sync();
543 xkb->reconfigure();
544 // now it should be on
545 QVERIFY(xkb->leds().testFlag(LED::NumLock));
546 // pressing should result in it being off
547 Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
548 Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
549 QVERIFY(!xkb->leds().testFlag(LED::NumLock));
550
551 // pressing again should enable it
552 Test::keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
553 Test::keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
554 QVERIFY(xkb->leds().testFlag(LED::NumLock));
555
556 // now reconfigure to disable on load
557 group.writeEntry("NumLock", 1);
558 group.sync();
559 xkb->reconfigure();
560 QVERIFY(!xkb->leds().testFlag(LED::NumLock));
561}
562
564#include "keyboard_layout_test.moc"
KeyboardInputRedirection * keyboard() const
Definition input.h:216
void activateWindow(Window *window, bool force=false)
void layoutChanged(uint index)
#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 setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
bool waitForWindowClosed(Window *window)
Session::Type type
Definition session.cpp:17
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549