diff --git a/autotests/integration/globalshortcuts_test.cpp b/autotests/integration/globalshortcuts_test.cpp --- a/autotests/integration/globalshortcuts_test.cpp +++ b/autotests/integration/globalshortcuts_test.cpp @@ -57,6 +57,7 @@ void testMetaShiftW(); void testX11ClientShortcut(); void testWaylandClientShortcut(); + void testSetupWindowShortcut(); }; void GlobalShortcutsTest::initTestCase() @@ -314,6 +315,47 @@ QVERIFY(workspace()->shortcutAvailable(seq)); } +void GlobalShortcutsTest::testSetupWindowShortcut() +{ + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createShellSurface(surface.data())); + auto client = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); + + QCOMPARE(workspace()->activeClient(), client); + QVERIFY(client->isActive()); + QCOMPARE(client->shortcut(), QKeySequence()); + + QSignalSpy shortcutDialogAddedSpy(waylandServer(), &WaylandServer::shellClientAdded); + QVERIFY(shortcutDialogAddedSpy.isValid()); + workspace()->slotSetupWindowShortcut(); + QTRY_COMPARE(shortcutDialogAddedSpy.count(), 1); + auto dialog = shortcutDialogAddedSpy.first().first().value(); + QVERIFY(dialog); + QVERIFY(dialog->isInternal()); + auto sequenceEdit = workspace()->shortcutDialog()->findChild(); + QVERIFY(sequenceEdit); + + // the QKeySequenceEdit field does not get focus, we need to pass it focus manually + QEXPECT_FAIL("", "Edit does not have focus", Continue); + QVERIFY(sequenceEdit->hasFocus()); + sequenceEdit->setFocus(); + QTRY_VERIFY(sequenceEdit->hasFocus()); + + quint32 timestamp = 0; + kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTMETA, timestamp++); + kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++); + kwinApp()->platform()->keyboardKeyPressed(KEY_Y, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_Y, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTMETA, timestamp++); + + // the sequence gets accepted after one second, so wait a bit longer + QTest::qWait(2000); + // now send in enter + kwinApp()->platform()->keyboardKeyPressed(KEY_ENTER, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_ENTER, timestamp++); + QTRY_COMPARE(client->shortcut(), QKeySequence(Qt::META + Qt::SHIFT + Qt::Key_Y)); +} WAYLANDTEST_MAIN(GlobalShortcutsTest) #include "globalshortcuts_test.moc" diff --git a/input.cpp b/input.cpp --- a/input.cpp +++ b/input.cpp @@ -826,8 +826,17 @@ if (!found) { return false; } - event->setAccepted(false); - if (QCoreApplication::sendEvent(found, event)) { + auto xkb = input()->keyboard()->xkb(); + Qt::Key key = xkb->toQtKey(xkb->toKeysym(event->nativeScanCode())); + if (key == Qt::Key_Super_L || key == Qt::Key_Super_R) { + // workaround for QTBUG-62102 + key = Qt::Key_Meta; + } + QKeyEvent internalEvent(event->type(), key, + event->modifiers(), event->nativeScanCode(), event->nativeVirtualKey(), + event->nativeModifiers(), event->text()); + internalEvent.setAccepted(false); + if (QCoreApplication::sendEvent(found, &internalEvent)) { waylandServer()->seat()->setFocusedKeyboardSurface(nullptr); passToWaylandServer(event); return true; diff --git a/workspace.h b/workspace.h --- a/workspace.h +++ b/workspace.h @@ -379,6 +379,10 @@ }; void switchWindow(Direction direction); + ShortcutDialog *shortcutDialog() const { + return client_keys_dialog; + } + public Q_SLOTS: void performWindowOperation(KWin::AbstractClient* c, Options::WindowOperation op); // Keybindings