From c9fa43e9db1329c04e5af2e6fde298c2a528d8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Thu, 20 Jul 2017 19:00:01 +0200 Subject: [PATCH] [autotests] Add test case for Client window shortcut Registers a shortcut on a window and triggers it. --- autotests/integration/CMakeLists.txt | 2 +- .../integration/globalshortcuts_test.cpp | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index d2946345c4..cd61ed6921 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -40,7 +40,6 @@ integrationTest(NAME testNoXdgRuntimeDir SRCS no_xdg_runtime_dir_test.cpp) integrationTest(NAME testScreenChanges SRCS screen_changes_test.cpp) integrationTest(NAME testModiferOnlyShortcut SRCS modifier_only_shortcut_test.cpp) integrationTest(NAME testTabBox SRCS tabbox_test.cpp) -integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp) integrationTest(NAME testWindowSelection SRCS window_selection_test.cpp) integrationTest(NAME testPointerConstraints SRCS pointer_constraints_test.cpp) integrationTest(NAME testKeyboardLayout SRCS keyboard_layout_test.cpp) @@ -60,6 +59,7 @@ if (XCB_ICCCM_FOUND) integrationTest(NAME testWindowRules SRCS window_rules_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testX11Client SRCS x11_client_test.cpp LIBS XCB::ICCCM) integrationTest(NAME testQuickTiling SRCS quick_tiling_test.cpp LIBS XCB::ICCCM) + integrationTest(NAME testGlobalShortcuts SRCS globalshortcuts_test.cpp LIBS XCB::ICCCM) if (KWIN_BUILD_ACTIVITIES) integrationTest(NAME testActivities SRCS activities_test.cpp LIBS XCB::ICCCM) diff --git a/autotests/integration/globalshortcuts_test.cpp b/autotests/integration/globalshortcuts_test.cpp index ada7316490..f3a7fd5ffd 100644 --- a/autotests/integration/globalshortcuts_test.cpp +++ b/autotests/integration/globalshortcuts_test.cpp @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "kwin_wayland_test.h" +#include "client.h" #include "cursor.h" #include "input.h" #include "platform.h" @@ -34,6 +35,9 @@ along with this program. If not, see . #include #include +#include +#include + using namespace KWin; using namespace KWayland::Client; @@ -51,6 +55,7 @@ private Q_SLOTS: void testRepeatedTrigger(); void testUserActionsMenu(); void testMetaShiftW(); + void testX11ClientShortcut(); }; void GlobalShortcutsTest::initTestCase() @@ -195,5 +200,82 @@ void GlobalShortcutsTest::testMetaShiftW() kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTMETA, timestamp++); } +struct XcbConnectionDeleter +{ + static inline void cleanup(xcb_connection_t *pointer) + { + xcb_disconnect(pointer); + } +}; + +void GlobalShortcutsTest::testX11ClientShortcut() +{ + // create an X11 window + QScopedPointer c(xcb_connect(nullptr, nullptr)); + QVERIFY(!xcb_connection_has_error(c.data())); + xcb_window_t w = xcb_generate_id(c.data()); + const QRect windowGeometry = QRect(0, 0, 10, 20); + const uint32_t values[] = { + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW + }; + xcb_create_window(c.data(), XCB_COPY_FROM_PARENT, w, rootWindow(), + windowGeometry.x(), + windowGeometry.y(), + windowGeometry.width(), + windowGeometry.height(), + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values); + xcb_size_hints_t hints; + memset(&hints, 0, sizeof(hints)); + xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); + xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); + xcb_icccm_set_wm_normal_hints(c.data(), w, &hints); + NETWinInfo info(c.data(), w, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties); + info.setWindowType(NET::Normal); + xcb_map_window(c.data(), w); + xcb_flush(c.data()); + + QSignalSpy windowCreatedSpy(workspace(), &Workspace::clientAdded); + QVERIFY(windowCreatedSpy.isValid()); + QVERIFY(windowCreatedSpy.wait()); + Client *client = windowCreatedSpy.last().first().value(); + QVERIFY(client); + + QCOMPARE(workspace()->activeClient(), client); + QVERIFY(client->isActive()); + QCOMPARE(client->shortcut(), QKeySequence()); + const QKeySequence seq(Qt::META + Qt::SHIFT + Qt::Key_Y); + QVERIFY(workspace()->shortcutAvailable(seq)); + client->setShortcut(seq.toString()); + QCOMPARE(client->shortcut(), seq); + QVERIFY(!workspace()->shortcutAvailable(seq)); + QCOMPARE(client->caption(), QStringLiteral(" {Meta+Shift+Y}")); + + // it's delayed + QCoreApplication::processEvents(); + + workspace()->activateClient(nullptr); + QVERIFY(!workspace()->activeClient()); + QVERIFY(!client->isActive()); + + // now let's trigger the shortcut + quint32 timestamp = 0; + kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTMETA, timestamp++); + kwinApp()->platform()->keyboardKeyPressed(KEY_LEFTSHIFT, timestamp++); + kwinApp()->platform()->keyboardKeyPressed(KEY_Y, timestamp++); + QTRY_COMPARE(workspace()->activeClient(), client); + kwinApp()->platform()->keyboardKeyReleased(KEY_Y, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTSHIFT, timestamp++); + kwinApp()->platform()->keyboardKeyReleased(KEY_LEFTMETA, timestamp++); + + // destroy window again + QSignalSpy windowClosedSpy(client, &Client::windowClosed); + QVERIFY(windowClosedSpy.isValid()); + xcb_unmap_window(c.data(), w); + xcb_destroy_window(c.data(), w); + xcb_flush(c.data()); + QVERIFY(windowClosedSpy.wait()); +} + WAYLANDTEST_MAIN(GlobalShortcutsTest) #include "globalshortcuts_test.moc"