d1b35f306d
The new signal is emitted when the Application has fully been initialized. It allows us to change the startup sequence, for example create workspace before starting the Xwayland server, without making any adjustments in our test suit.
509 lines
20 KiB
C++
509 lines
20 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2017 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
#include "kwin_wayland_test.h"
|
|
#include "abstract_client.h"
|
|
#include "keyboard_input.h"
|
|
#include "keyboard_layout.h"
|
|
#include "platform.h"
|
|
#include "virtualdesktops.h"
|
|
#include "wayland_server.h"
|
|
#include "workspace.h"
|
|
|
|
#include <KConfigGroup>
|
|
#include <KGlobalAccel>
|
|
|
|
#include <KWayland/Client/surface.h>
|
|
|
|
#include <QAction>
|
|
#include <QDBusConnection>
|
|
#include <QDBusConnectionInterface>
|
|
#include <QDBusMessage>
|
|
#include <QDBusPendingCall>
|
|
|
|
#include <linux/input.h>
|
|
|
|
using namespace KWin;
|
|
using namespace KWayland::Client;
|
|
|
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_keyboard_laout-0");
|
|
|
|
class KeyboardLayoutTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
private Q_SLOTS:
|
|
void initTestCase();
|
|
void init();
|
|
void cleanup();
|
|
|
|
void testReconfigure();
|
|
void testChangeLayoutThroughDBus();
|
|
void testPerLayoutShortcut();
|
|
void testDBusServiceExport();
|
|
void testVirtualDesktopPolicy();
|
|
void testWindowPolicy();
|
|
void testApplicationPolicy();
|
|
void testNumLock();
|
|
|
|
private:
|
|
void reconfigureLayouts();
|
|
};
|
|
|
|
void KeyboardLayoutTest::reconfigureLayouts()
|
|
{
|
|
// create DBus signal to reload
|
|
QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/Layouts"), QStringLiteral("org.kde.keyboard"), QStringLiteral("reloadConfig"));
|
|
QDBusConnection::sessionBus().send(message);
|
|
}
|
|
|
|
void KeyboardLayoutTest::initTestCase()
|
|
{
|
|
qRegisterMetaType<KWin::AbstractClient*>();
|
|
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
|
QVERIFY(applicationStartedSpy.isValid());
|
|
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
|
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
|
|
|
|
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
|
kwinApp()->setKxkbConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
|
|
|
kwinApp()->start();
|
|
QVERIFY(applicationStartedSpy.wait());
|
|
waylandServer()->initWorkspace();
|
|
}
|
|
|
|
void KeyboardLayoutTest::init()
|
|
{
|
|
QVERIFY(Test::setupWaylandConnection());
|
|
}
|
|
|
|
void KeyboardLayoutTest::cleanup()
|
|
{
|
|
Test::destroyWaylandConnection();
|
|
}
|
|
|
|
class LayoutChangedSignalWrapper : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
LayoutChangedSignalWrapper()
|
|
: QObject()
|
|
{
|
|
QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("currentLayoutChanged"), this, SIGNAL(layoutChanged(QString)));
|
|
}
|
|
|
|
Q_SIGNALS:
|
|
void layoutChanged(const QString &name);
|
|
};
|
|
|
|
void KeyboardLayoutTest::testReconfigure()
|
|
{
|
|
// verifies that we can change the keymap
|
|
|
|
// default should be a keymap with only us layout
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QCOMPARE(xkb->numberOfLayouts(), 1u);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
auto layouts = xkb->layoutNames();
|
|
QCOMPARE(layouts.size(), 1);
|
|
QVERIFY(layouts.contains(0));
|
|
QCOMPARE(layouts[0], QStringLiteral("English (US)"));
|
|
|
|
// create a new keymap
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("de,us"));
|
|
layoutGroup.sync();
|
|
|
|
reconfigureLayouts();
|
|
// now we should have two layouts
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 2u);
|
|
// default layout is German
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
layouts = xkb->layoutNames();
|
|
QCOMPARE(layouts.size(), 2);
|
|
QVERIFY(layouts.contains(0));
|
|
QVERIFY(layouts.contains(1));
|
|
QCOMPARE(layouts[0], QStringLiteral("German"));
|
|
QCOMPARE(layouts[1], QStringLiteral("English (US)"));
|
|
}
|
|
|
|
void KeyboardLayoutTest::testChangeLayoutThroughDBus()
|
|
{
|
|
// this test verifies that the layout can be changed through DBus
|
|
// first configure layouts
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("de,us,de(neo)"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
// now we should have two layouts
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 3u);
|
|
// default layout is German
|
|
xkb->switchToLayout(0);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
|
|
LayoutChangedSignalWrapper wrapper;
|
|
QSignalSpy layoutChangedSpy(&wrapper, &LayoutChangedSignalWrapper::layoutChanged);
|
|
QVERIFY(layoutChangedSpy.isValid());
|
|
|
|
// now change through DBus to english
|
|
auto changeLayout = [] (const QString &layoutName) {
|
|
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("setLayout"));
|
|
msg << layoutName;
|
|
return QDBusConnection::sessionBus().asyncCall(msg);
|
|
};
|
|
auto reply = changeLayout(QStringLiteral("English (US)"));
|
|
reply.waitForFinished();
|
|
QVERIFY(!reply.isError());
|
|
QCOMPARE(reply.reply().arguments().first().toBool(), true);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
QCOMPARE(layoutChangedSpy.count(), 1);
|
|
layoutChangedSpy.clear();
|
|
|
|
// switch to a layout which does not exist
|
|
reply = changeLayout(QStringLiteral("French"));
|
|
QVERIFY(!reply.isError());
|
|
QCOMPARE(reply.reply().arguments().first().toBool(), false);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QVERIFY(layoutChangedSpy.isEmpty());
|
|
|
|
// switch to another layout should work
|
|
reply = changeLayout(QStringLiteral("German"));
|
|
QVERIFY(!reply.isError());
|
|
QCOMPARE(reply.reply().arguments().first().toBool(), true);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
QCOMPARE(layoutChangedSpy.count(), 1);
|
|
layoutChangedSpy.clear();
|
|
|
|
// switching to same layout should also work
|
|
reply = changeLayout(QStringLiteral("German"));
|
|
QVERIFY(!reply.isError());
|
|
QCOMPARE(reply.reply().arguments().first().toBool(), true);
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QVERIFY(layoutChangedSpy.isEmpty());
|
|
}
|
|
|
|
void KeyboardLayoutTest::testPerLayoutShortcut()
|
|
{
|
|
// this test verifies that per-layout global shortcuts are working correctly.
|
|
// first configure layouts
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
|
|
layoutGroup.sync();
|
|
|
|
// and create the global shortcuts
|
|
const QString componentName = QStringLiteral("KDE Keyboard Layout Switcher");
|
|
QAction *a = new QAction(this);
|
|
a->setObjectName(QStringLiteral("Switch keyboard layout to English (US)"));
|
|
a->setProperty("componentName", componentName);
|
|
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>{Qt::CTRL+Qt::ALT+Qt::Key_1}, KGlobalAccel::NoAutoloading);
|
|
delete a;
|
|
a = new QAction(this);
|
|
a->setObjectName(QStringLiteral("Switch keyboard layout to German"));
|
|
a->setProperty("componentName", componentName);
|
|
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>{Qt::CTRL+Qt::ALT+Qt::Key_2}, KGlobalAccel::NoAutoloading);
|
|
delete a;
|
|
|
|
reconfigureLayouts();
|
|
// now we should have three layouts
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 3u);
|
|
// default layout is English
|
|
xkb->switchToLayout(0);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
LayoutChangedSignalWrapper wrapper;
|
|
QSignalSpy layoutChangedSpy(&wrapper, &LayoutChangedSignalWrapper::layoutChanged);
|
|
QVERIFY(layoutChangedSpy.isValid());
|
|
|
|
// now switch to English through the global shortcut
|
|
quint32 timestamp = 1;
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTCTRL, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTALT, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_2, timestamp++);
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
// now layout should be German
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
// release keys again
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_2, timestamp++);
|
|
// switch back to English
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_1, timestamp++);
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
QCOMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
// release keys again
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_1, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTALT, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTCTRL, timestamp++);
|
|
}
|
|
|
|
void KeyboardLayoutTest::testDBusServiceExport()
|
|
{
|
|
// verifies that the dbus service is only exported if there are at least two layouts
|
|
|
|
// first configure layouts, with just one layout
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 1u);
|
|
// default layout is English
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
// with one layout we should not have the dbus interface
|
|
QTRY_VERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
|
|
|
// reconfigure to two layouts
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 2u);
|
|
QTRY_VERIFY(QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
|
|
|
// and back to one layout
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 1u);
|
|
QTRY_VERIFY(!QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.keyboard")).value());
|
|
}
|
|
|
|
void KeyboardLayoutTest::testVirtualDesktopPolicy()
|
|
{
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
|
|
layoutGroup.writeEntry("SwitchMode", QStringLiteral("Desktop"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 3u);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
VirtualDesktopManager::self()->setCount(4);
|
|
QCOMPARE(VirtualDesktopManager::self()->count(), 4u);
|
|
|
|
auto changeLayout = [] (const QString &layoutName) {
|
|
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("setLayout"));
|
|
msg << layoutName;
|
|
return QDBusConnection::sessionBus().asyncCall(msg);
|
|
};
|
|
auto reply = changeLayout(QStringLiteral("German"));
|
|
reply.waitForFinished();
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
|
|
// switch to another virtual desktop
|
|
auto desktops = VirtualDesktopManager::self()->desktops();
|
|
QCOMPARE(desktops.count(), 4);
|
|
QCOMPARE(desktops.first(), VirtualDesktopManager::self()->currentDesktop());
|
|
VirtualDesktopManager::self()->setCurrent(desktops.at(1));
|
|
QCOMPARE(desktops.at(1), VirtualDesktopManager::self()->currentDesktop());
|
|
// should be reset to English
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));reply = changeLayout(QStringLiteral("German (Neo 2)"));
|
|
reply.waitForFinished();
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
|
|
// back to desktop 0 -> German
|
|
VirtualDesktopManager::self()->setCurrent(desktops.at(0));
|
|
QCOMPARE(desktops.first(), VirtualDesktopManager::self()->currentDesktop());
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
// desktop 2 -> English
|
|
VirtualDesktopManager::self()->setCurrent(desktops.at(2));
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
// desktop 1 -> Neo
|
|
VirtualDesktopManager::self()->setCurrent(desktops.at(1));
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
|
|
// remove virtual desktops
|
|
VirtualDesktopManager::self()->setCount(1);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
|
|
// add another desktop
|
|
VirtualDesktopManager::self()->setCount(2);
|
|
// switching to it should result in going to default
|
|
desktops = VirtualDesktopManager::self()->desktops();
|
|
QCOMPARE(desktops.count(), 2);
|
|
QCOMPARE(desktops.first(), VirtualDesktopManager::self()->currentDesktop());
|
|
VirtualDesktopManager::self()->setCurrent(desktops.last());
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
}
|
|
|
|
void KeyboardLayoutTest::testWindowPolicy()
|
|
{
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
|
|
layoutGroup.writeEntry("SwitchMode", QStringLiteral("Window"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 3u);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
// create a window
|
|
using namespace KWayland::Client;
|
|
QScopedPointer<Surface> surface(Test::createSurface());
|
|
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
|
auto c1 = Test::renderAndWaitForShown(surface.data(), QSize(100, 100), Qt::blue);
|
|
QVERIFY(c1);
|
|
|
|
// now switch layout
|
|
auto changeLayout = [] (const QString &layoutName) {
|
|
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("setLayout"));
|
|
msg << layoutName;
|
|
return QDBusConnection::sessionBus().asyncCall(msg);
|
|
};
|
|
auto reply = changeLayout(QStringLiteral("German"));
|
|
reply.waitForFinished();
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
|
|
// create a second window
|
|
QScopedPointer<Surface> surface2(Test::createSurface());
|
|
QScopedPointer<XdgShellSurface> shellSurface2(Test::createXdgShellStableSurface(surface2.data()));
|
|
auto c2 = Test::renderAndWaitForShown(surface2.data(), QSize(100, 100), Qt::red);
|
|
QVERIFY(c2);
|
|
// this should have switched back to English
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
// now change to another layout
|
|
reply = changeLayout(QStringLiteral("German (Neo 2)"));
|
|
reply.waitForFinished();
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
|
|
// activate other window
|
|
workspace()->activateClient(c1);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
workspace()->activateClient(c2);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
}
|
|
|
|
void KeyboardLayoutTest::testApplicationPolicy()
|
|
{
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us,de,de(neo)"));
|
|
layoutGroup.writeEntry("SwitchMode", QStringLiteral("WinClass"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 3u);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
// create a window
|
|
using namespace KWayland::Client;
|
|
QScopedPointer<Surface> surface(Test::createSurface());
|
|
QScopedPointer<XdgShellSurface> shellSurface(Test::createXdgShellStableSurface(surface.data()));
|
|
auto c1 = Test::renderAndWaitForShown(surface.data(), QSize(100, 100), Qt::blue);
|
|
QVERIFY(c1);
|
|
|
|
// now switch layout
|
|
auto changeLayout = [] (const QString &layoutName) {
|
|
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.keyboard"), QStringLiteral("/Layouts"), QStringLiteral("org.kde.KeyboardLayouts"), QStringLiteral("setLayout"));
|
|
msg << layoutName;
|
|
return QDBusConnection::sessionBus().asyncCall(msg);
|
|
};
|
|
LayoutChangedSignalWrapper wrapper;
|
|
QSignalSpy layoutChangedSpy(&wrapper, &LayoutChangedSignalWrapper::layoutChanged);
|
|
QVERIFY(layoutChangedSpy.isValid());
|
|
auto reply = changeLayout(QStringLiteral("German"));
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
QCOMPARE(layoutChangedSpy.count(), 1);
|
|
reply.waitForFinished();
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German"));
|
|
|
|
// create a second window
|
|
QScopedPointer<Surface> surface2(Test::createSurface());
|
|
QScopedPointer<XdgShellSurface> shellSurface2(Test::createXdgShellStableSurface(surface2.data()));
|
|
auto c2 = Test::renderAndWaitForShown(surface2.data(), QSize(100, 100), Qt::red);
|
|
QVERIFY(c2);
|
|
// it is the same application and should not switch the layout
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QCOMPARE(layoutChangedSpy.count(), 1);
|
|
// now change to another layout
|
|
reply = changeLayout(QStringLiteral("German (Neo 2)"));
|
|
QVERIFY(layoutChangedSpy.wait());
|
|
QCOMPARE(layoutChangedSpy.count(), 2);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
|
|
// activate other window
|
|
workspace()->activateClient(c1);
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
workspace()->activateClient(c2);
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
|
|
shellSurface2.reset();
|
|
surface2.reset();
|
|
QVERIFY(Test::waitForWindowDestroyed(c2));
|
|
QVERIFY(!layoutChangedSpy.wait());
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("German (Neo 2)"));
|
|
}
|
|
|
|
void KeyboardLayoutTest::testNumLock()
|
|
{
|
|
qputenv("KWIN_FORCE_NUM_LOCK_EVALUATION", "1");
|
|
KConfigGroup layoutGroup = kwinApp()->kxkbConfig()->group("Layout");
|
|
layoutGroup.writeEntry("LayoutList", QStringLiteral("us"));
|
|
layoutGroup.sync();
|
|
reconfigureLayouts();
|
|
|
|
auto xkb = input()->keyboard()->xkb();
|
|
QTRY_COMPARE(xkb->numberOfLayouts(), 1u);
|
|
QTRY_COMPARE(xkb->layoutName(), QStringLiteral("English (US)"));
|
|
|
|
// by default not set
|
|
QVERIFY(!xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
quint32 timestamp = 0;
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
|
// now it should be on
|
|
QVERIFY(xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
// and back to off
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
|
QVERIFY(!xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
|
|
// let's reconfigure to enable through config
|
|
auto group = InputConfig::self()->inputConfig()->group("Keyboard");
|
|
group.writeEntry("NumLock", 0);
|
|
group.sync();
|
|
xkb->reconfigure();
|
|
// now it should be on
|
|
QVERIFY(xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
// pressing should result in it being off
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
|
QVERIFY(!xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
|
|
// pressing again should enable it
|
|
kwinApp()->platform()->keyboardKeyPressed(KEY_NUMLOCK, timestamp++);
|
|
kwinApp()->platform()->keyboardKeyReleased(KEY_NUMLOCK, timestamp++);
|
|
QVERIFY(xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
|
|
// now reconfigure to disable on load
|
|
group.writeEntry("NumLock", 1);
|
|
group.sync();
|
|
xkb->reconfigure();
|
|
QVERIFY(!xkb->leds().testFlag(Xkb::LED::NumLock));
|
|
}
|
|
|
|
|
|
WAYLANDTEST_MAIN(KeyboardLayoutTest)
|
|
#include "keyboard_layout_test.moc"
|