f71ee59a37
Use input device specific apis to change the position of the cursor. The main reason to do so is to break the assumption that Cursor position is the same as pointer position, which I would like to rely on later to merge tablet and pointer cursors.
267 lines
9.6 KiB
C++
267 lines
9.6 KiB
C++
/*
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
SPDX-FileCopyrightText: 2018 Martin Flöser <mgraesslin@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include "kwin_wayland_test.h"
|
|
|
|
#include "core/outputbackend.h"
|
|
#include "input.h"
|
|
#include "keyboard_input.h"
|
|
#include "pointer_input.h"
|
|
#include "screenedge.h"
|
|
#include "wayland_server.h"
|
|
#include "workspace.h"
|
|
|
|
#include <KConfigGroup>
|
|
#include <KGlobalAccel>
|
|
|
|
#include <QAction>
|
|
#include <QDBusConnection>
|
|
|
|
#include <linux/input.h>
|
|
|
|
using namespace KWin;
|
|
|
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_no_global_shortcuts-0");
|
|
static const QString s_serviceName = QStringLiteral("org.kde.KWin.Test.ModifierOnlyShortcut");
|
|
static const QString s_path = QStringLiteral("/Test");
|
|
|
|
Q_DECLARE_METATYPE(KWin::ElectricBorder)
|
|
|
|
/**
|
|
* This test verifies the NoGlobalShortcuts initialization flag
|
|
*/
|
|
class NoGlobalShortcutsTest : public QObject
|
|
{
|
|
Q_OBJECT
|
|
private Q_SLOTS:
|
|
void initTestCase();
|
|
void init();
|
|
void cleanup();
|
|
|
|
void testTrigger_data();
|
|
void testTrigger();
|
|
void testKGlobalAccel();
|
|
void testPointerShortcut();
|
|
void testAxisShortcut_data();
|
|
void testAxisShortcut();
|
|
void testScreenEdge();
|
|
};
|
|
|
|
class Target : public QObject
|
|
{
|
|
Q_OBJECT
|
|
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.Test.ModifierOnlyShortcut")
|
|
|
|
public:
|
|
Target();
|
|
~Target() override;
|
|
|
|
public Q_SLOTS:
|
|
Q_SCRIPTABLE void shortcut();
|
|
|
|
Q_SIGNALS:
|
|
void shortcutTriggered();
|
|
};
|
|
|
|
Target::Target()
|
|
: QObject()
|
|
{
|
|
QDBusConnection::sessionBus().registerService(s_serviceName);
|
|
QDBusConnection::sessionBus().registerObject(s_path, s_serviceName, this, QDBusConnection::ExportScriptableSlots);
|
|
}
|
|
|
|
Target::~Target()
|
|
{
|
|
QDBusConnection::sessionBus().unregisterObject(s_path);
|
|
QDBusConnection::sessionBus().unregisterService(s_serviceName);
|
|
}
|
|
|
|
void Target::shortcut()
|
|
{
|
|
Q_EMIT shortcutTriggered();
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::initTestCase()
|
|
{
|
|
qRegisterMetaType<KWin::ElectricBorder>("ElectricBorder");
|
|
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
|
QVERIFY(waylandServer()->init(s_socketName, KWin::WaylandServer::InitializationFlag::NoGlobalShortcuts));
|
|
QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
|
|
|
|
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
|
qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1");
|
|
qputenv("XKB_DEFAULT_RULES", "evdev");
|
|
|
|
kwinApp()->start();
|
|
QVERIFY(applicationStartedSpy.wait());
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::init()
|
|
{
|
|
workspace()->setActiveOutput(QPoint(640, 512));
|
|
KWin::input()->pointer()->warp(QPoint(640, 512));
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::cleanup()
|
|
{
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testTrigger_data()
|
|
{
|
|
QTest::addColumn<QStringList>("metaConfig");
|
|
QTest::addColumn<QStringList>("altConfig");
|
|
QTest::addColumn<QStringList>("controlConfig");
|
|
QTest::addColumn<QStringList>("shiftConfig");
|
|
QTest::addColumn<int>("modifier");
|
|
QTest::addColumn<QList<int>>("nonTriggeringMods");
|
|
|
|
const QStringList trigger = QStringList{s_serviceName, s_path, s_serviceName, QStringLiteral("shortcut")};
|
|
const QStringList e = QStringList();
|
|
|
|
QTest::newRow("leftMeta") << trigger << e << e << e << KEY_LEFTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("rightMeta") << trigger << e << e << e << KEY_RIGHTMETA << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("leftAlt") << e << trigger << e << e << KEY_LEFTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("rightAlt") << e << trigger << e << e << KEY_RIGHTALT << QList<int>{KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("leftControl") << e << e << trigger << e << KEY_LEFTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("rightControl") << e << e << trigger << e << KEY_RIGHTCTRL << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTMETA, KEY_RIGHTMETA, KEY_LEFTSHIFT, KEY_RIGHTSHIFT};
|
|
QTest::newRow("leftShift") << e << e << e << trigger << KEY_LEFTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
|
QTest::newRow("rightShift") << e << e << e << trigger << KEY_RIGHTSHIFT << QList<int>{KEY_LEFTALT, KEY_RIGHTALT, KEY_LEFTCTRL, KEY_RIGHTCTRL, KEY_LEFTMETA, KEY_RIGHTMETA};
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testTrigger()
|
|
{
|
|
// test based on ModifierOnlyShortcutTest::testTrigger
|
|
Target target;
|
|
QSignalSpy triggeredSpy(&target, &Target::shortcutTriggered);
|
|
|
|
KConfigGroup group = kwinApp()->config()->group("ModifierOnlyShortcuts");
|
|
QFETCH(QStringList, metaConfig);
|
|
QFETCH(QStringList, altConfig);
|
|
QFETCH(QStringList, shiftConfig);
|
|
QFETCH(QStringList, controlConfig);
|
|
group.writeEntry("Meta", metaConfig);
|
|
group.writeEntry("Alt", altConfig);
|
|
group.writeEntry("Shift", shiftConfig);
|
|
group.writeEntry("Control", controlConfig);
|
|
group.sync();
|
|
workspace()->slotReconfigure();
|
|
|
|
// configured shortcut should trigger
|
|
quint32 timestamp = 1;
|
|
QFETCH(int, modifier);
|
|
Test::keyboardKeyPressed(modifier, timestamp++);
|
|
Test::keyboardKeyReleased(modifier, timestamp++);
|
|
QCOMPARE(triggeredSpy.count(), 0);
|
|
|
|
// the other shortcuts should not trigger
|
|
QFETCH(QList<int>, nonTriggeringMods);
|
|
for (auto it = nonTriggeringMods.constBegin(), end = nonTriggeringMods.constEnd(); it != end; it++) {
|
|
Test::keyboardKeyPressed(*it, timestamp++);
|
|
Test::keyboardKeyReleased(*it, timestamp++);
|
|
QCOMPARE(triggeredSpy.count(), 0);
|
|
}
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testKGlobalAccel()
|
|
{
|
|
std::unique_ptr<QAction> action(new QAction(nullptr));
|
|
action->setProperty("componentName", QStringLiteral("kwin"));
|
|
action->setObjectName(QStringLiteral("globalshortcuts-test-meta-shift-w"));
|
|
QSignalSpy triggeredSpy(action.get(), &QAction::triggered);
|
|
KGlobalAccel::self()->setShortcut(action.get(), QList<QKeySequence>{Qt::META | Qt::SHIFT | Qt::Key_W}, KGlobalAccel::NoAutoloading);
|
|
|
|
// press meta+shift+w
|
|
quint32 timestamp = 0;
|
|
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
|
QCOMPARE(input()->keyboardModifiers(), Qt::MetaModifier);
|
|
Test::keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++);
|
|
QCOMPARE(input()->keyboardModifiers(), Qt::ShiftModifier | Qt::MetaModifier);
|
|
Test::keyboardKeyPressed(KEY_W, timestamp++);
|
|
Test::keyboardKeyReleased(KEY_W, timestamp++);
|
|
|
|
// release meta+shift
|
|
Test::keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++);
|
|
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
|
|
|
QVERIFY(!triggeredSpy.wait(100));
|
|
QCOMPARE(triggeredSpy.count(), 0);
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testPointerShortcut()
|
|
{
|
|
// based on LockScreenTest::testPointerShortcut
|
|
std::unique_ptr<QAction> action(new QAction(nullptr));
|
|
QSignalSpy actionSpy(action.get(), &QAction::triggered);
|
|
input()->registerPointerShortcut(Qt::MetaModifier, Qt::LeftButton, action.get());
|
|
|
|
// try to trigger the shortcut
|
|
quint32 timestamp = 1;
|
|
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
|
Test::pointerButtonPressed(BTN_LEFT, timestamp++);
|
|
QCoreApplication::instance()->processEvents();
|
|
QCOMPARE(actionSpy.count(), 0);
|
|
Test::pointerButtonReleased(BTN_LEFT, timestamp++);
|
|
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
|
QCoreApplication::instance()->processEvents();
|
|
QCOMPARE(actionSpy.count(), 0);
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testAxisShortcut_data()
|
|
{
|
|
QTest::addColumn<Qt::Orientation>("direction");
|
|
QTest::addColumn<int>("sign");
|
|
|
|
QTest::newRow("up") << Qt::Vertical << 1;
|
|
QTest::newRow("down") << Qt::Vertical << -1;
|
|
QTest::newRow("left") << Qt::Horizontal << 1;
|
|
QTest::newRow("right") << Qt::Horizontal << -1;
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testAxisShortcut()
|
|
{
|
|
// based on LockScreenTest::testAxisShortcut
|
|
std::unique_ptr<QAction> action(new QAction(nullptr));
|
|
QSignalSpy actionSpy(action.get(), &QAction::triggered);
|
|
QFETCH(Qt::Orientation, direction);
|
|
QFETCH(int, sign);
|
|
PointerAxisDirection axisDirection = PointerAxisUp;
|
|
if (direction == Qt::Vertical) {
|
|
axisDirection = sign > 0 ? PointerAxisUp : PointerAxisDown;
|
|
} else {
|
|
axisDirection = sign > 0 ? PointerAxisLeft : PointerAxisRight;
|
|
}
|
|
input()->registerAxisShortcut(Qt::MetaModifier, axisDirection, action.get());
|
|
|
|
// try to trigger the shortcut
|
|
quint32 timestamp = 1;
|
|
Test::keyboardKeyPressed(KEY_LEFTMETA, timestamp++);
|
|
if (direction == Qt::Vertical) {
|
|
Test::pointerAxisVertical(sign * 5.0, timestamp++);
|
|
} else {
|
|
Test::pointerAxisHorizontal(sign * 5.0, timestamp++);
|
|
}
|
|
QCoreApplication::instance()->processEvents();
|
|
QCOMPARE(actionSpy.count(), 0);
|
|
Test::keyboardKeyReleased(KEY_LEFTMETA, timestamp++);
|
|
QCoreApplication::instance()->processEvents();
|
|
QCOMPARE(actionSpy.count(), 0);
|
|
}
|
|
|
|
void NoGlobalShortcutsTest::testScreenEdge()
|
|
{
|
|
// based on LockScreenTest::testScreenEdge
|
|
QSignalSpy screenEdgeSpy(workspace()->screenEdges(), &ScreenEdges::approaching);
|
|
QCOMPARE(screenEdgeSpy.count(), 0);
|
|
|
|
quint32 timestamp = 1;
|
|
Test::pointerMotion({5, 5}, timestamp++);
|
|
QCOMPARE(screenEdgeSpy.count(), 0);
|
|
}
|
|
|
|
WAYLANDTEST_MAIN(NoGlobalShortcutsTest)
|
|
#include "no_global_shortcuts_test.moc"
|