Warning, file /plasma/kwin/autotests/integration/screenedge_client_show_test.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "kwin_wayland_test.h" 0010 0011 #include "core/output.h" 0012 #include "core/outputbackend.h" 0013 #include "cursor.h" 0014 #include "deleted.h" 0015 #include "screenedge.h" 0016 #include "wayland_server.h" 0017 #include "workspace.h" 0018 #include "x11window.h" 0019 #include <kwineffects.h> 0020 0021 #include <netwm.h> 0022 #include <xcb/xcb_icccm.h> 0023 0024 namespace KWin 0025 { 0026 0027 static const QString s_socketName = QStringLiteral("wayland_test_kwin_screenedge_client_show-0"); 0028 0029 class ScreenEdgeClientShowTest : public QObject 0030 { 0031 Q_OBJECT 0032 private Q_SLOTS: 0033 void initTestCase(); 0034 void init(); 0035 void testScreenEdgeShowHideX11_data(); 0036 void testScreenEdgeShowHideX11(); 0037 void testScreenEdgeShowX11Touch_data(); 0038 void testScreenEdgeShowX11Touch(); 0039 }; 0040 0041 void ScreenEdgeClientShowTest::initTestCase() 0042 { 0043 qRegisterMetaType<KWin::Window *>(); 0044 qRegisterMetaType<KWin::Deleted *>(); 0045 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0046 QVERIFY(waylandServer()->init(s_socketName)); 0047 QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024))); 0048 0049 // set custom config which disable touch edge 0050 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); 0051 KConfigGroup group = config->group("TabBox"); 0052 group.writeEntry(QStringLiteral("TouchBorderActivate"), "9"); 0053 group.sync(); 0054 0055 kwinApp()->setConfig(config); 0056 0057 kwinApp()->start(); 0058 QVERIFY(applicationStartedSpy.wait()); 0059 const auto outputs = workspace()->outputs(); 0060 QCOMPARE(outputs.count(), 2); 0061 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0062 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0063 setenv("QT_QPA_PLATFORM", "wayland", true); 0064 } 0065 0066 void ScreenEdgeClientShowTest::init() 0067 { 0068 workspace()->setActiveOutput(QPoint(640, 512)); 0069 Cursors::self()->mouse()->setPos(QPoint(640, 512)); 0070 QVERIFY(waylandServer()->windows().isEmpty()); 0071 } 0072 0073 struct XcbConnectionDeleter 0074 { 0075 void operator()(xcb_connection_t *pointer) 0076 { 0077 xcb_disconnect(pointer); 0078 } 0079 }; 0080 0081 void ScreenEdgeClientShowTest::testScreenEdgeShowHideX11_data() 0082 { 0083 QTest::addColumn<QRect>("windowGeometry"); 0084 QTest::addColumn<QRect>("resizedWindowGeometry"); 0085 QTest::addColumn<quint32>("location"); 0086 QTest::addColumn<QPoint>("triggerPos"); 0087 0088 QTest::newRow("bottom/left") << QRect(50, 1004, 1180, 20) << QRect(150, 1004, 1000, 20) << 2u << QPoint(100, 1023); 0089 QTest::newRow("bottom/right") << QRect(1330, 1004, 1180, 20) << QRect(1410, 1004, 1000, 20) << 2u << QPoint(1400, 1023); 0090 QTest::newRow("top/left") << QRect(50, 0, 1180, 20) << QRect(150, 0, 1000, 20) << 0u << QPoint(100, 0); 0091 QTest::newRow("top/right") << QRect(1330, 0, 1180, 20) << QRect(1410, 0, 1000, 20) << 0u << QPoint(1400, 0); 0092 QTest::newRow("left") << QRect(0, 10, 20, 1000) << QRect(0, 70, 20, 800) << 3u << QPoint(0, 50); 0093 QTest::newRow("right") << QRect(2540, 10, 20, 1000) << QRect(2540, 70, 20, 800) << 1u << QPoint(2559, 60); 0094 } 0095 0096 void ScreenEdgeClientShowTest::testScreenEdgeShowHideX11() 0097 { 0098 // this test creates a window which borders the screen and sets the screenedge show hint 0099 // that should trigger a show of the window whenever the cursor is pushed against the screen edge 0100 0101 // create the test window 0102 std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr)); 0103 QVERIFY(!xcb_connection_has_error(c.get())); 0104 // atom for the screenedge show hide functionality 0105 Xcb::Atom atom(QByteArrayLiteral("_KDE_NET_WM_SCREEN_EDGE_SHOW"), false, c.get()); 0106 0107 xcb_window_t windowId = xcb_generate_id(c.get()); 0108 QFETCH(QRect, windowGeometry); 0109 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(), 0110 windowGeometry.x(), 0111 windowGeometry.y(), 0112 windowGeometry.width(), 0113 windowGeometry.height(), 0114 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); 0115 xcb_size_hints_t hints; 0116 memset(&hints, 0, sizeof(hints)); 0117 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); 0118 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); 0119 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints); 0120 NETWinInfo info(c.get(), windowId, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties); 0121 info.setWindowType(NET::Dock); 0122 xcb_map_window(c.get(), windowId); 0123 xcb_flush(c.get()); 0124 0125 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded); 0126 QVERIFY(windowCreatedSpy.wait()); 0127 X11Window *window = windowCreatedSpy.last().first().value<X11Window *>(); 0128 QVERIFY(window); 0129 QVERIFY(!window->isDecorated()); 0130 QCOMPARE(window->frameGeometry(), windowGeometry); 0131 QVERIFY(!window->hasStrut()); 0132 QVERIFY(!window->isHiddenInternal()); 0133 0134 QSignalSpy effectsWindowAdded(effects, &EffectsHandler::windowAdded); 0135 QVERIFY(effectsWindowAdded.wait()); 0136 0137 // now try to hide 0138 QFETCH(quint32, location); 0139 xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId, atom, XCB_ATOM_CARDINAL, 32, 1, &location); 0140 xcb_flush(c.get()); 0141 0142 QSignalSpy effectsWindowHiddenSpy(effects, &EffectsHandler::windowHidden); 0143 QSignalSpy clientHiddenSpy(window, &X11Window::windowHidden); 0144 QVERIFY(clientHiddenSpy.wait()); 0145 QVERIFY(window->isHiddenInternal()); 0146 QCOMPARE(effectsWindowHiddenSpy.count(), 1); 0147 0148 // now trigger the edge 0149 QSignalSpy effectsWindowShownSpy(effects, &EffectsHandler::windowShown); 0150 QFETCH(QPoint, triggerPos); 0151 Cursors::self()->mouse()->setPos(triggerPos); 0152 QVERIFY(!window->isHiddenInternal()); 0153 QCOMPARE(effectsWindowShownSpy.count(), 1); 0154 0155 // go into event loop to trigger xcb_flush 0156 QTest::qWait(1); 0157 0158 // hide window again 0159 Cursors::self()->mouse()->setPos(QPoint(640, 512)); 0160 xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId, atom, XCB_ATOM_CARDINAL, 32, 1, &location); 0161 xcb_flush(c.get()); 0162 QVERIFY(clientHiddenSpy.wait()); 0163 QVERIFY(window->isHiddenInternal()); 0164 QFETCH(QRect, resizedWindowGeometry); 0165 // resizewhile hidden 0166 window->moveResize(resizedWindowGeometry); 0167 // triggerPos shouldn't be valid anymore 0168 Cursors::self()->mouse()->setPos(triggerPos); 0169 QVERIFY(window->isHiddenInternal()); 0170 0171 // destroy window again 0172 QSignalSpy windowClosedSpy(window, &X11Window::windowClosed); 0173 xcb_unmap_window(c.get(), windowId); 0174 xcb_destroy_window(c.get(), windowId); 0175 xcb_flush(c.get()); 0176 QVERIFY(windowClosedSpy.wait()); 0177 } 0178 0179 void ScreenEdgeClientShowTest::testScreenEdgeShowX11Touch_data() 0180 { 0181 QTest::addColumn<QRect>("windowGeometry"); 0182 QTest::addColumn<quint32>("location"); 0183 QTest::addColumn<QPoint>("touchDownPos"); 0184 QTest::addColumn<QPoint>("targetPos"); 0185 0186 QTest::newRow("bottom/left") << QRect(50, 1004, 1180, 20) << 2u << QPoint(100, 1023) << QPoint(100, 540); 0187 QTest::newRow("bottom/right") << QRect(1330, 1004, 1180, 20) << 2u << QPoint(1400, 1023) << QPoint(1400, 520); 0188 QTest::newRow("top/left") << QRect(50, 0, 1180, 20) << 0u << QPoint(100, 0) << QPoint(100, 350); 0189 QTest::newRow("top/right") << QRect(1330, 0, 1180, 20) << 0u << QPoint(1400, 0) << QPoint(1400, 400); 0190 QTest::newRow("left") << QRect(0, 10, 20, 1000) << 3u << QPoint(0, 50) << QPoint(400, 50); 0191 QTest::newRow("right") << QRect(2540, 10, 20, 1000) << 1u << QPoint(2559, 60) << QPoint(2200, 60); 0192 } 0193 0194 void ScreenEdgeClientShowTest::testScreenEdgeShowX11Touch() 0195 { 0196 // this test creates a window which borders the screen and sets the screenedge show hint 0197 // that should trigger a show of the window whenever the touch screen swipe gesture is triggered 0198 0199 // create the test window 0200 std::unique_ptr<xcb_connection_t, XcbConnectionDeleter> c(xcb_connect(nullptr, nullptr)); 0201 QVERIFY(!xcb_connection_has_error(c.get())); 0202 // atom for the screenedge show hide functionality 0203 Xcb::Atom atom(QByteArrayLiteral("_KDE_NET_WM_SCREEN_EDGE_SHOW"), false, c.get()); 0204 0205 xcb_window_t windowId = xcb_generate_id(c.get()); 0206 QFETCH(QRect, windowGeometry); 0207 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(), 0208 windowGeometry.x(), 0209 windowGeometry.y(), 0210 windowGeometry.width(), 0211 windowGeometry.height(), 0212 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr); 0213 xcb_size_hints_t hints; 0214 memset(&hints, 0, sizeof(hints)); 0215 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y()); 0216 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height()); 0217 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints); 0218 NETWinInfo info(c.get(), windowId, rootWindow(), NET::WMAllProperties, NET::WM2AllProperties); 0219 info.setWindowType(NET::Dock); 0220 xcb_map_window(c.get(), windowId); 0221 xcb_flush(c.get()); 0222 0223 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded); 0224 QVERIFY(windowCreatedSpy.wait()); 0225 X11Window *window = windowCreatedSpy.last().first().value<X11Window *>(); 0226 QVERIFY(window); 0227 QVERIFY(!window->isDecorated()); 0228 QCOMPARE(window->frameGeometry(), windowGeometry); 0229 QVERIFY(!window->hasStrut()); 0230 QVERIFY(!window->isHiddenInternal()); 0231 0232 QSignalSpy effectsWindowAdded(effects, &EffectsHandler::windowAdded); 0233 QVERIFY(effectsWindowAdded.wait()); 0234 0235 // now try to hide 0236 QFETCH(quint32, location); 0237 xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId, atom, XCB_ATOM_CARDINAL, 32, 1, &location); 0238 xcb_flush(c.get()); 0239 0240 QSignalSpy effectsWindowHiddenSpy(effects, &EffectsHandler::windowHidden); 0241 QSignalSpy clientHiddenSpy(window, &X11Window::windowHidden); 0242 QVERIFY(clientHiddenSpy.wait()); 0243 QVERIFY(window->isHiddenInternal()); 0244 QCOMPARE(effectsWindowHiddenSpy.count(), 1); 0245 0246 // now trigger the edge 0247 QSignalSpy effectsWindowShownSpy(effects, &EffectsHandler::windowShown); 0248 quint32 timestamp = 0; 0249 QFETCH(QPoint, touchDownPos); 0250 QFETCH(QPoint, targetPos); 0251 Test::touchDown(0, touchDownPos, timestamp++); 0252 Test::touchMotion(0, targetPos, timestamp++); 0253 Test::touchUp(0, timestamp++); 0254 QVERIFY(effectsWindowShownSpy.wait()); 0255 QVERIFY(!window->isHiddenInternal()); 0256 QCOMPARE(effectsWindowShownSpy.count(), 1); 0257 0258 // destroy window again 0259 QSignalSpy windowClosedSpy(window, &X11Window::windowClosed); 0260 xcb_unmap_window(c.get(), windowId); 0261 xcb_destroy_window(c.get(), windowId); 0262 xcb_flush(c.get()); 0263 QVERIFY(windowClosedSpy.wait()); 0264 } 0265 0266 } 0267 0268 WAYLANDTEST_MAIN(KWin::ScreenEdgeClientShowTest) 0269 #include "screenedge_client_show_test.moc"