Warning, file /frameworks/kwindowsystem/autotests/netwininfotestclient.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "nettesthelper.h" 0008 #include <netwm.h> 0009 0010 #include <QProcess> 0011 #include <QStandardPaths> 0012 #include <qtest_widgets.h> 0013 0014 // system 0015 #include <unistd.h> 0016 0017 using Property = UniqueCPointer<xcb_get_property_reply_t>; 0018 0019 // clang-format off 0020 #define INFO NETWinInfo info(m_connection, m_testWindow, m_rootWindow, NET::WMAllProperties, NET::WM2AllProperties, NET::Client); 0021 0022 #define ATOM(name) \ 0023 KXUtils::Atom atom(connection(), QByteArrayLiteral(#name)); 0024 0025 #define UTF8 KXUtils::Atom utf8String(connection(), QByteArrayLiteral("UTF8_STRING")); 0026 0027 #define GETPROP(type, length, formatSize) \ 0028 xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(connection(), false, m_testWindow, \ 0029 atom, type, 0, length); \ 0030 Property reply(xcb_get_property_reply(connection(), cookie, nullptr)); \ 0031 QVERIFY(reply); \ 0032 QCOMPARE(reply->format, uint8_t(formatSize)); \ 0033 QCOMPARE(reply->value_len, uint32_t(length)); 0034 0035 #define VERIFYDELETED(t) \ 0036 xcb_get_property_cookie_t cookieDeleted = xcb_get_property_unchecked(connection(), false, m_testWindow, \ 0037 atom, t, 0, 1); \ 0038 Property replyDeleted(xcb_get_property_reply(connection(), cookieDeleted, nullptr)); \ 0039 QVERIFY(replyDeleted); \ 0040 QVERIFY(replyDeleted->type == XCB_ATOM_NONE); 0041 0042 class NetWinInfoTestClient : public QObject 0043 { 0044 Q_OBJECT 0045 private Q_SLOTS: 0046 void initTestCase(); 0047 void cleanupTestCase(); 0048 void init(); 0049 void cleanup(); 0050 0051 void testBlockCompositing(); 0052 void testUserTime(); 0053 void testStartupId(); 0054 void testDesktopFileName(); 0055 void testAppMenuObjectPath(); 0056 void testAppMenuServiceName(); 0057 void testHandledIcons_data(); 0058 void testHandledIcons(); 0059 void testPid(); 0060 void testName(); 0061 void testIconName(); 0062 #if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 0) 0063 void testStrut(); 0064 #endif 0065 void testExtendedStrut(); 0066 void testIconGeometry(); 0067 void testWindowType_data(); 0068 void testWindowType(); 0069 0070 void testActivities_data(); 0071 void testActivities(); 0072 void testWindowRole(); 0073 void testWindowClass(); 0074 void testClientMachine(); 0075 void testGroupLeader(); 0076 void testUrgency_data(); 0077 void testUrgency(); 0078 void testInput_data(); 0079 void testInput(); 0080 void testInitialMappingState_data(); 0081 void testInitialMappingState(); 0082 void testIconPixmap_data(); 0083 void testIconPixmap(); 0084 void testTransientFor(); 0085 void testProtocols_data(); 0086 void testProtocols(); 0087 void testOpaqueRegion_data(); 0088 void testOpaqueRegion(); 0089 0090 private: 0091 void performNameTest(xcb_atom_t atom, const char *(NETWinInfo:: *getter)(void)const, void (NETWinInfo:: *setter)(const char *), NET::Property property); 0092 void waitForPropertyChange(NETWinInfo *info, xcb_atom_t atom, NET::Property prop, NET::Property2 prop2 = NET::Property2(0)); 0093 xcb_connection_t *connection() 0094 { 0095 return m_connection; 0096 } 0097 xcb_connection_t *m_connection; 0098 QVector<xcb_connection_t*> m_connections; 0099 std::unique_ptr<QProcess> m_xvfb; 0100 xcb_window_t m_rootWindow; 0101 xcb_window_t m_testWindow; 0102 }; 0103 0104 void NetWinInfoTestClient::initTestCase() 0105 { 0106 } 0107 0108 void NetWinInfoTestClient::cleanupTestCase() 0109 { 0110 // close connection 0111 while (!m_connections.isEmpty()) { 0112 xcb_disconnect(m_connections.takeFirst()); 0113 } 0114 } 0115 0116 void NetWinInfoTestClient::init() 0117 { 0118 // first reset just to be sure 0119 m_connection = nullptr; 0120 m_rootWindow = XCB_WINDOW_NONE; 0121 m_testWindow = XCB_WINDOW_NONE; 0122 0123 const QString xfvbExec = QStandardPaths::findExecutable(QStringLiteral("Xvfb")); 0124 QVERIFY(!xfvbExec.isEmpty()); 0125 0126 // start Xvfb 0127 m_xvfb.reset(new QProcess); 0128 // use pipe to pass fd to Xvfb to get back the display id 0129 int pipeFds[2]; 0130 QVERIFY(pipe(pipeFds) == 0); 0131 m_xvfb->start(QStringLiteral("Xvfb"), QStringList{ QStringLiteral("-displayfd"), QString::number(pipeFds[1]) }); 0132 QVERIFY(m_xvfb->waitForStarted()); 0133 QCOMPARE(m_xvfb->state(), QProcess::Running); 0134 0135 // reads from pipe, closes write side 0136 close(pipeFds[1]); 0137 0138 QFile readPipe; 0139 QVERIFY(readPipe.open(pipeFds[0], QIODevice::ReadOnly, QFileDevice::AutoCloseHandle)); 0140 QByteArray displayNumber = readPipe.readLine(); 0141 readPipe.close(); 0142 0143 displayNumber.prepend(QByteArray(":")); 0144 displayNumber.remove(displayNumber.size() -1, 1); 0145 0146 // create X connection 0147 int screen = 0; 0148 m_connection = xcb_connect(displayNumber.constData(), &screen); 0149 QVERIFY(m_connection); 0150 QVERIFY(!xcb_connection_has_error(m_connection)); 0151 m_rootWindow = KXUtils::rootWindow(m_connection, screen); 0152 0153 // create test window 0154 m_testWindow = xcb_generate_id(m_connection); 0155 uint32_t values[] = {XCB_EVENT_MASK_PROPERTY_CHANGE}; 0156 xcb_create_window(m_connection, XCB_COPY_FROM_PARENT, m_testWindow, 0157 m_rootWindow, 0158 0, 0, 100, 100, 0, XCB_COPY_FROM_PARENT, 0159 XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values); 0160 // and map it 0161 xcb_map_window(m_connection, m_testWindow); 0162 } 0163 0164 void NetWinInfoTestClient::cleanup() 0165 { 0166 // destroy test window 0167 xcb_unmap_window(m_connection, m_testWindow); 0168 xcb_destroy_window(m_connection, m_testWindow); 0169 m_testWindow = XCB_WINDOW_NONE; 0170 0171 // delay till clenupTestCase as otherwise xcb reuses the same memory address 0172 m_connections << connection(); 0173 // kill Xvfb 0174 m_xvfb->terminate(); 0175 m_xvfb->waitForFinished(); 0176 } 0177 0178 void NetWinInfoTestClient::waitForPropertyChange(NETWinInfo *info, xcb_atom_t atom, NET::Property prop, NET::Property2 prop2) 0179 { 0180 while (true) { 0181 UniqueCPointer<xcb_generic_event_t> event(xcb_wait_for_event(connection())); 0182 if (!event) { 0183 break; 0184 } 0185 if ((event->response_type & ~0x80) != XCB_PROPERTY_NOTIFY) { 0186 continue; 0187 } 0188 xcb_property_notify_event_t *pe = reinterpret_cast<xcb_property_notify_event_t *>(event.get()); 0189 if (pe->window != m_testWindow) { 0190 continue; 0191 } 0192 if (pe->atom != atom) { 0193 continue; 0194 } 0195 NET::Properties dirty; 0196 NET::Properties2 dirty2; 0197 info->event(event.get(), &dirty, &dirty2); 0198 if (prop != 0) { 0199 QVERIFY(dirty & prop); 0200 } 0201 if (prop2 != 0) { 0202 QVERIFY(dirty2 & prop2); 0203 } 0204 if (!prop) { 0205 QCOMPARE(dirty, NET::Properties()); 0206 } 0207 if (!prop2) { 0208 QCOMPARE(dirty2, NET::Properties2()); 0209 } 0210 break; 0211 } 0212 } 0213 0214 void NetWinInfoTestClient::testBlockCompositing() 0215 { 0216 QVERIFY(connection()); 0217 ATOM(_KDE_NET_WM_BLOCK_COMPOSITING) 0218 INFO 0219 0220 QVERIFY(!info.isBlockingCompositing()); 0221 info.setBlockingCompositing(true); 0222 QVERIFY(info.isBlockingCompositing()); 0223 0224 // compare with the X property 0225 QVERIFY(atom != XCB_ATOM_NONE); 0226 GETPROP(XCB_ATOM_CARDINAL, 1, 32) 0227 QCOMPARE(reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get()))[0], uint32_t(1)); 0228 0229 // and wait for our event 0230 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2BlockCompositing); 0231 QVERIFY(info.isBlockingCompositing()); 0232 0233 // setting false should delete the property again 0234 info.setBlockingCompositing(false); 0235 QVERIFY(!info.isBlockingCompositing()); 0236 VERIFYDELETED(XCB_ATOM_CARDINAL) 0237 0238 // and wait for our event 0239 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2BlockCompositing); 0240 QVERIFY(!info.isBlockingCompositing()); 0241 } 0242 0243 void NetWinInfoTestClient::testUserTime() 0244 { 0245 QVERIFY(connection()); 0246 ATOM(_NET_WM_USER_TIME) 0247 INFO 0248 0249 QCOMPARE(info.userTime(), uint32_t(-1)); 0250 info.setUserTime(500); 0251 QCOMPARE(info.userTime(), uint32_t(500)); 0252 0253 // compare with the X property 0254 QVERIFY(atom != XCB_ATOM_NONE); 0255 GETPROP(XCB_ATOM_CARDINAL, 1, 32) 0256 QCOMPARE(reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get()))[0], uint32_t(500)); 0257 0258 // and wait for our event 0259 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2UserTime); 0260 QCOMPARE(info.userTime(), uint32_t(500)); 0261 } 0262 0263 void NetWinInfoTestClient::testStartupId() 0264 { 0265 QVERIFY(connection()); 0266 ATOM(_NET_STARTUP_ID) 0267 UTF8 0268 INFO 0269 0270 QVERIFY(!info.startupId()); 0271 info.setStartupId("foo"); 0272 QCOMPARE(info.startupId(), "foo"); 0273 0274 // compare with the X property 0275 QVERIFY(atom != XCB_ATOM_NONE); 0276 QVERIFY(utf8String != XCB_ATOM_NONE); 0277 GETPROP(utf8String, 3, 8) 0278 QCOMPARE(reinterpret_cast<const char *>(xcb_get_property_value(reply.get())), "foo"); 0279 0280 // and wait for our event 0281 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2StartupId); 0282 QCOMPARE(info.startupId(), "foo"); 0283 } 0284 0285 void NetWinInfoTestClient::testAppMenuObjectPath() 0286 { 0287 ATOM(_KDE_NET_WM_APPMENU_OBJECT_PATH) 0288 INFO 0289 0290 QVERIFY(!info.appMenuObjectPath()); 0291 0292 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0293 atom, XCB_ATOM_STRING, 8, 3, "foo"); 0294 xcb_flush(connection()); 0295 0296 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2AppMenuObjectPath); 0297 QCOMPARE(info.appMenuObjectPath(), "foo"); 0298 } 0299 0300 void NetWinInfoTestClient::testAppMenuServiceName() 0301 { 0302 ATOM(_KDE_NET_WM_APPMENU_SERVICE_NAME) 0303 INFO 0304 0305 QVERIFY(!info.appMenuServiceName()); 0306 0307 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0308 atom, XCB_ATOM_STRING, 8, 3, "foo"); 0309 xcb_flush(connection()); 0310 0311 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2AppMenuServiceName); 0312 QCOMPARE(info.appMenuServiceName(), "foo"); 0313 } 0314 0315 void NetWinInfoTestClient::testDesktopFileName() 0316 { 0317 QVERIFY(connection()); 0318 ATOM(_KDE_NET_WM_DESKTOP_FILE) 0319 UTF8 0320 INFO 0321 0322 QVERIFY(!info.desktopFileName()); 0323 info.setDesktopFileName("foo"); 0324 QCOMPARE(info.desktopFileName(), "foo"); 0325 0326 // compare with the X property 0327 QVERIFY(atom != XCB_ATOM_NONE); 0328 QVERIFY(utf8String != XCB_ATOM_NONE); 0329 GETPROP(utf8String, 3, 8) 0330 QCOMPARE(reinterpret_cast<const char *>(xcb_get_property_value(reply.get())), "foo"); 0331 0332 // and wait for our event 0333 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2DesktopFileName); 0334 QCOMPARE(info.desktopFileName(), "foo"); 0335 } 0336 0337 void NetWinInfoTestClient::testHandledIcons_data() 0338 { 0339 QTest::addColumn<bool>("handled"); 0340 QTest::addColumn<uint32_t>("value"); 0341 0342 QTest::newRow("enabled") << true << uint32_t(1); 0343 QTest::newRow("disabled") << false << uint32_t(0); 0344 } 0345 0346 void NetWinInfoTestClient::testHandledIcons() 0347 { 0348 QVERIFY(connection()); 0349 ATOM(_NET_WM_HANDLED_ICONS) 0350 INFO 0351 0352 QVERIFY(!info.handledIcons()); 0353 QFETCH(bool, handled); 0354 info.setHandledIcons(handled); 0355 QCOMPARE(info.handledIcons(), handled); 0356 0357 // compare with the X property 0358 QVERIFY(atom != XCB_ATOM_NONE); 0359 GETPROP(XCB_ATOM_CARDINAL, 1, 32) 0360 QTEST(reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get()))[0], "value"); 0361 0362 // and wait for our event 0363 waitForPropertyChange(&info, atom, NET::WMHandledIcons); 0364 QCOMPARE(info.handledIcons(), handled); 0365 } 0366 0367 void NetWinInfoTestClient::testPid() 0368 { 0369 QVERIFY(connection()); 0370 ATOM(_NET_WM_PID) 0371 INFO 0372 0373 QCOMPARE(info.pid(), 0); 0374 info.setPid(m_xvfb->processId()); 0375 QCOMPARE(info.pid(), m_xvfb->processId()); 0376 0377 // compare with the X property 0378 QVERIFY(atom != XCB_ATOM_NONE); 0379 GETPROP(XCB_ATOM_CARDINAL, 1, 32) 0380 QCOMPARE(reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get()))[0], uint32_t(m_xvfb->processId())); 0381 0382 // and wait for our event 0383 waitForPropertyChange(&info, atom, NET::WMPid); 0384 QCOMPARE(info.pid(), m_xvfb->processId()); 0385 } 0386 0387 void NetWinInfoTestClient::performNameTest(xcb_atom_t atom, const char *(NETWinInfo:: *getter)(void)const, void (NETWinInfo:: *setter)(const char *), NET::Property property) 0388 { 0389 UTF8 0390 INFO 0391 0392 QVERIFY(!(info.*getter)()); 0393 (info.*setter)("foo"); 0394 QCOMPARE((info.*getter)(), "foo"); 0395 0396 // compare with the X property 0397 QVERIFY(atom != XCB_ATOM_NONE); 0398 QVERIFY(utf8String != XCB_ATOM_NONE); 0399 GETPROP(utf8String, 3, 8) 0400 QCOMPARE(reinterpret_cast<const char *>(xcb_get_property_value(reply.get())), "foo"); 0401 0402 // and wait for our event 0403 waitForPropertyChange(&info, atom, property); 0404 QCOMPARE((info.*getter)(), "foo"); 0405 0406 // delete the string 0407 (info.*setter)(""); 0408 QCOMPARE((info.*getter)(), ""); 0409 VERIFYDELETED(utf8String) 0410 0411 // and wait for our event 0412 waitForPropertyChange(&info, atom, property); 0413 QVERIFY(!(info.*getter)()); 0414 0415 // set it again, to ensure that we don't leak on tear-down 0416 (info.*setter)("bar"); 0417 QCOMPARE((info.*getter)(), "bar"); 0418 xcb_flush(connection()); 0419 waitForPropertyChange(&info, atom, property); 0420 QCOMPARE((info.*getter)(), "bar"); 0421 } 0422 0423 void NetWinInfoTestClient::testIconName() 0424 { 0425 QVERIFY(connection()); 0426 ATOM(_NET_WM_ICON_NAME) 0427 performNameTest(atom, &NETWinInfo::iconName, &NETWinInfo::setIconName, NET::WMIconName); 0428 } 0429 0430 void NetWinInfoTestClient::testName() 0431 { 0432 QVERIFY(connection()); 0433 ATOM(_NET_WM_NAME) 0434 performNameTest(atom, &NETWinInfo::name, &NETWinInfo::setName, NET::WMName); 0435 } 0436 0437 #if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(5, 0) 0438 void NetWinInfoTestClient::testStrut() 0439 { 0440 QVERIFY(connection()); 0441 ATOM(_NET_WM_STRUT) 0442 INFO 0443 0444 NETStrut extents = info.strut(); 0445 QCOMPARE(extents.bottom, 0); 0446 QCOMPARE(extents.left, 0); 0447 QCOMPARE(extents.right, 0); 0448 QCOMPARE(extents.top, 0); 0449 0450 NETStrut newExtents; 0451 newExtents.bottom = 10; 0452 newExtents.left = 20; 0453 newExtents.right = 30; 0454 newExtents.top = 40; 0455 info.setStrut(newExtents); 0456 extents = info.strut(); 0457 QCOMPARE(extents.bottom, newExtents.bottom); 0458 QCOMPARE(extents.left, newExtents.left); 0459 QCOMPARE(extents.right, newExtents.right); 0460 QCOMPARE(extents.top, newExtents.top); 0461 0462 // compare with the X property 0463 QVERIFY(atom != XCB_ATOM_NONE); 0464 GETPROP(XCB_ATOM_CARDINAL, 4, 32) 0465 uint32_t *data = reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get())); 0466 QCOMPARE(data[0], uint32_t(newExtents.left)); 0467 QCOMPARE(data[1], uint32_t(newExtents.right)); 0468 QCOMPARE(data[2], uint32_t(newExtents.top)); 0469 QCOMPARE(data[3], uint32_t(newExtents.bottom)); 0470 0471 // and wait for our event 0472 waitForPropertyChange(&info, atom, NET::WMStrut); 0473 extents = info.strut(); 0474 QCOMPARE(extents.bottom, newExtents.bottom); 0475 QCOMPARE(extents.left, newExtents.left); 0476 QCOMPARE(extents.right, newExtents.right); 0477 QCOMPARE(extents.top, newExtents.top); 0478 } 0479 #endif 0480 0481 void NetWinInfoTestClient::testExtendedStrut() 0482 { 0483 QVERIFY(connection()); 0484 ATOM(_NET_WM_STRUT_PARTIAL) 0485 INFO 0486 0487 NETExtendedStrut extents = info.extendedStrut(); 0488 QCOMPARE(extents.left_width, 0); 0489 QCOMPARE(extents.right_width, 0); 0490 QCOMPARE(extents.top_width, 0); 0491 QCOMPARE(extents.bottom_width, 0); 0492 QCOMPARE(extents.left_start, 0); 0493 QCOMPARE(extents.left_end, 0); 0494 QCOMPARE(extents.right_start, 0); 0495 QCOMPARE(extents.right_end, 0); 0496 QCOMPARE(extents.top_start, 0); 0497 QCOMPARE(extents.top_end, 0); 0498 QCOMPARE(extents.bottom_start, 0); 0499 QCOMPARE(extents.bottom_end, 0); 0500 0501 NETExtendedStrut newExtents; 0502 newExtents.left_width = 10; 0503 newExtents.right_width = 20; 0504 newExtents.top_width = 30; 0505 newExtents.bottom_width = 40; 0506 newExtents.left_start = 50; 0507 newExtents.left_end = 60; 0508 newExtents.right_start = 70; 0509 newExtents.right_end = 80; 0510 newExtents.top_start = 90; 0511 newExtents.top_end = 91; 0512 newExtents.bottom_start = 92; 0513 newExtents.bottom_end = 93; 0514 info.setExtendedStrut(newExtents); 0515 extents = info.extendedStrut(); 0516 QCOMPARE(extents.left_width, newExtents.left_width); 0517 QCOMPARE(extents.right_width, newExtents.right_width); 0518 QCOMPARE(extents.top_width, newExtents.top_width); 0519 QCOMPARE(extents.bottom_width, newExtents.bottom_width); 0520 QCOMPARE(extents.left_start, newExtents.left_start); 0521 QCOMPARE(extents.left_end, newExtents.left_end); 0522 QCOMPARE(extents.right_start, newExtents.right_start); 0523 QCOMPARE(extents.right_end, newExtents.right_end); 0524 QCOMPARE(extents.top_start, newExtents.top_start); 0525 QCOMPARE(extents.top_end, newExtents.top_end); 0526 QCOMPARE(extents.bottom_start, newExtents.bottom_start); 0527 QCOMPARE(extents.bottom_end, newExtents.bottom_end); 0528 0529 // compare with the X property 0530 QVERIFY(atom != XCB_ATOM_NONE); 0531 GETPROP(XCB_ATOM_CARDINAL, 12, 32) 0532 uint32_t *data = reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get())); 0533 QCOMPARE(data[ 0], uint32_t(newExtents.left_width)); 0534 QCOMPARE(data[ 1], uint32_t(newExtents.right_width)); 0535 QCOMPARE(data[ 2], uint32_t(newExtents.top_width)); 0536 QCOMPARE(data[ 3], uint32_t(newExtents.bottom_width)); 0537 QCOMPARE(data[ 4], uint32_t(newExtents.left_start)); 0538 QCOMPARE(data[ 5], uint32_t(newExtents.left_end)); 0539 QCOMPARE(data[ 6], uint32_t(newExtents.right_start)); 0540 QCOMPARE(data[ 7], uint32_t(newExtents.right_end)); 0541 QCOMPARE(data[ 8], uint32_t(newExtents.top_start)); 0542 QCOMPARE(data[ 9], uint32_t(newExtents.top_end)); 0543 QCOMPARE(data[10], uint32_t(newExtents.bottom_start)); 0544 QCOMPARE(data[11], uint32_t(newExtents.bottom_end)); 0545 0546 // and wait for our event 0547 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2ExtendedStrut); 0548 extents = info.extendedStrut(); 0549 QCOMPARE(extents.left_width, newExtents.left_width); 0550 QCOMPARE(extents.right_width, newExtents.right_width); 0551 QCOMPARE(extents.top_width, newExtents.top_width); 0552 QCOMPARE(extents.bottom_width, newExtents.bottom_width); 0553 QCOMPARE(extents.left_start, newExtents.left_start); 0554 QCOMPARE(extents.left_end, newExtents.left_end); 0555 QCOMPARE(extents.right_start, newExtents.right_start); 0556 QCOMPARE(extents.right_end, newExtents.right_end); 0557 QCOMPARE(extents.top_start, newExtents.top_start); 0558 QCOMPARE(extents.top_end, newExtents.top_end); 0559 QCOMPARE(extents.bottom_start, newExtents.bottom_start); 0560 QCOMPARE(extents.bottom_end, newExtents.bottom_end); 0561 } 0562 0563 void NetWinInfoTestClient::testIconGeometry() 0564 { 0565 QVERIFY(connection()); 0566 ATOM(_NET_WM_ICON_GEOMETRY) 0567 INFO 0568 0569 NETRect geo = info.iconGeometry(); 0570 QCOMPARE(geo.pos.x, 0); 0571 QCOMPARE(geo.pos.y, 0); 0572 QCOMPARE(geo.size.width, 0); 0573 QCOMPARE(geo.size.height, 0); 0574 0575 NETRect newGeo; 0576 newGeo.pos.x = 10; 0577 newGeo.pos.y = 20; 0578 newGeo.size.width = 30; 0579 newGeo.size.height = 40; 0580 info.setIconGeometry(newGeo); 0581 geo = info.iconGeometry(); 0582 QCOMPARE(geo.pos.x, newGeo.pos.x); 0583 QCOMPARE(geo.pos.y, newGeo.pos.y); 0584 QCOMPARE(geo.size.width, newGeo.size.width); 0585 QCOMPARE(geo.size.height, newGeo.size.height); 0586 0587 // compare with the X property 0588 QVERIFY(atom != XCB_ATOM_NONE); 0589 GETPROP(XCB_ATOM_CARDINAL, 4, 32) 0590 uint32_t *data = reinterpret_cast<uint32_t *>(xcb_get_property_value(reply.get())); 0591 QCOMPARE(data[0], uint32_t(newGeo.pos.x)); 0592 QCOMPARE(data[1], uint32_t(newGeo.pos.y)); 0593 QCOMPARE(data[2], uint32_t(newGeo.size.width)); 0594 QCOMPARE(data[3], uint32_t(newGeo.size.height)); 0595 0596 // and wait for our event 0597 waitForPropertyChange(&info, atom, NET::WMIconGeometry); 0598 geo = info.iconGeometry(); 0599 QCOMPARE(geo.pos.x, newGeo.pos.x); 0600 QCOMPARE(geo.pos.y, newGeo.pos.y); 0601 QCOMPARE(geo.size.width, newGeo.size.width); 0602 QCOMPARE(geo.size.height, newGeo.size.height); 0603 } 0604 0605 Q_DECLARE_METATYPE(NET::WindowType) 0606 void NetWinInfoTestClient::testWindowType_data() 0607 { 0608 QTest::addColumn<NET::WindowType>("type"); 0609 QTest::addColumn<int>("length"); 0610 QTest::addColumn<QByteArray>("typeAtom"); 0611 QTest::addColumn<QByteArray>("secondaryTypeAtom"); 0612 0613 QTest::newRow("override") << NET::Override << 2 << QByteArrayLiteral("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NORMAL"); 0614 QTest::newRow("TopMenu") << NET::TopMenu << 2 << QByteArrayLiteral("_KDE_NET_WM_WINDOW_TYPE_TOPMENU") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DOCK"); 0615 QTest::newRow("Utility") << NET::Utility << 2 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_UTILITY") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DIALOG"); 0616 QTest::newRow("Splash") << NET::Splash << 2 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_SPLASH") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DOCK"); 0617 // TODO: this should be 2 0618 QTest::newRow("DropdownMenu") << NET::DropdownMenu << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_MENU"); 0619 // TODO: this should be 2 0620 QTest::newRow("PopupMenu") << NET::PopupMenu << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_POPUP_MENU") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_MENU"); 0621 // TODO: this should be 2 0622 QTest::newRow("Notification") << NET::Notification << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NOTIFICATION") << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_UTILITY"); 0623 QTest::newRow("Dialog") << NET::Dialog << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DIALOG") << QByteArray(); 0624 QTest::newRow("Menu") << NET::Menu << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_MENU") << QByteArray(); 0625 QTest::newRow("Toolbar") << NET::Toolbar << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_TOOLBAR") << QByteArray(); 0626 QTest::newRow("Dock") << NET::Dock << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DOCK") << QByteArray(); 0627 QTest::newRow("Desktop") << NET::Desktop << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DESKTOP") << QByteArray(); 0628 QTest::newRow("Tooltip") << NET::Tooltip << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_TOOLTIP") << QByteArray(); 0629 QTest::newRow("ComboBox") << NET::ComboBox << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_COMBO") << QByteArray(); 0630 QTest::newRow("DNDIcon") << NET::DNDIcon << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_DND") << QByteArray(); 0631 QTest::newRow("Normal") << NET::Normal << 1 << QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NORMAL") << QByteArray(); 0632 QTest::newRow("OnScreenDisplay") << NET::OnScreenDisplay << 1 << QByteArrayLiteral("_KDE_NET_WM_WINDOW_TYPE_ON_SCREEN_DISPLAY") << QByteArray(); 0633 QTest::newRow("CriticalNotification") << NET::CriticalNotification << 1 << QByteArrayLiteral("_KDE_NET_WM_WINDOW_TYPE_CRITICAL_NOTIFICATION") << QByteArray(); 0634 QTest::newRow("AppletPopup") << NET::AppletPopup << 1 << QByteArrayLiteral("_KDE_NET_WM_WINDOW_TYPE_APPLET_POPUP") << QByteArray(); 0635 } 0636 0637 void NetWinInfoTestClient::testWindowType() 0638 { 0639 QVERIFY(connection()); 0640 ATOM(_NET_WM_WINDOW_TYPE) 0641 INFO 0642 0643 QVERIFY(info.hasWindowType()); 0644 QVERIFY(!info.hasNETSupport()); 0645 QCOMPARE(info.windowType(NET::AllTypesMask), NET::Unknown); 0646 QFETCH(NET::WindowType, type); 0647 info.setWindowType(type); 0648 // it does not update the internal type! 0649 QCOMPARE(info.windowType(NET::AllTypesMask), NET::Unknown); 0650 QFETCH(int, length); 0651 QFETCH(QByteArray, typeAtom); 0652 0653 // compare the X property 0654 KXUtils::Atom type1(connection(), typeAtom); 0655 QVERIFY(atom != XCB_ATOM_NONE); 0656 GETPROP(XCB_ATOM_ATOM, length, 32) 0657 xcb_atom_t *atoms = reinterpret_cast<xcb_atom_t *>(xcb_get_property_value(reply.get())); 0658 QCOMPARE(atoms[0], xcb_atom_t(type1)); 0659 if (reply->value_len > 1) { 0660 QFETCH(QByteArray, secondaryTypeAtom); 0661 KXUtils::Atom type2(connection(), secondaryTypeAtom); 0662 QVERIFY(type2 != XCB_ATOM_NONE); 0663 QCOMPARE(atoms[1], xcb_atom_t(type2)); 0664 } 0665 0666 waitForPropertyChange(&info, atom, NET::WMWindowType); 0667 QCOMPARE(info.windowType(NET::AllTypesMask), type); 0668 QVERIFY(info.hasNETSupport()); 0669 } 0670 0671 void NetWinInfoTestClient::testClientMachine() 0672 { 0673 QVERIFY(connection()); 0674 INFO 0675 0676 QVERIFY(!info.clientMachine()); 0677 0678 // client machine needs to be changed using xcb 0679 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0680 XCB_ATOM_WM_CLIENT_MACHINE, XCB_ATOM_STRING, 8, 9, "localhost"); 0681 xcb_flush(connection()); 0682 0683 // only updated after event 0684 waitForPropertyChange(&info, XCB_ATOM_WM_CLIENT_MACHINE, NET::Property(0), NET::WM2ClientMachine); 0685 QCOMPARE(info.clientMachine(), "localhost"); 0686 } 0687 0688 void NetWinInfoTestClient::testGroupLeader() 0689 { 0690 QVERIFY(connection()); 0691 INFO 0692 0693 QVERIFY(info.groupLeader() == XCB_WINDOW_NONE); 0694 0695 // group leader needs to be changed through wm hints 0696 uint32_t values[] = { 0697 1 << 6, /* WindowGroupHint*/ 0698 1, /* Input */ 0699 1, /* Normal State */ 0700 XCB_NONE, /* icon pixmap */ 0701 XCB_NONE, /* icon window */ 0702 XCB_NONE, /* icon x */ 0703 XCB_NONE, /* icon y */ 0704 XCB_NONE, /* icon mask */ 0705 m_rootWindow /* group leader */ 0706 }; 0707 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0708 XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, 9, values); 0709 xcb_flush(connection()); 0710 0711 // only updated after event 0712 waitForPropertyChange(&info, XCB_ATOM_WM_HINTS, NET::Property(0), NET::WM2GroupLeader); 0713 QCOMPARE(info.groupLeader(), m_rootWindow); 0714 } 0715 0716 void NetWinInfoTestClient::testUrgency_data() 0717 { 0718 QTest::addColumn<quint32>("flags"); 0719 QTest::addColumn<bool>("expected"); 0720 0721 QTest::newRow("urgency") << quint32(1 << 8) << true; 0722 QTest::newRow("none") << quint32(0) << false; 0723 QTest::newRow("group_urgency") << quint32((1 << 6) | (1 << 8)) << true; 0724 QTest::newRow("input") << quint32(1) << false; 0725 } 0726 0727 void NetWinInfoTestClient::testUrgency() 0728 { 0729 QVERIFY(connection()); 0730 INFO 0731 0732 QVERIFY(!info.urgency()); 0733 QFETCH(quint32, flags); 0734 0735 // group leader needs to be changed through wm hints 0736 uint32_t values[] = { 0737 flags, 0738 1, /* Input */ 0739 1, /* Normal State */ 0740 XCB_NONE, /* icon pixmap */ 0741 XCB_NONE, /* icon window */ 0742 XCB_NONE, /* icon x */ 0743 XCB_NONE, /* icon y */ 0744 XCB_NONE, /* icon mask */ 0745 XCB_NONE /* group leader */ 0746 }; 0747 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0748 XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, 9, values); 0749 xcb_flush(connection()); 0750 0751 // only updated after event 0752 waitForPropertyChange(&info, XCB_ATOM_WM_HINTS, NET::Property(0), NET::WM2Urgency); 0753 QTEST(info.urgency(), "expected"); 0754 } 0755 0756 void NetWinInfoTestClient::testInput_data() 0757 { 0758 QTest::addColumn<quint32>("flags"); 0759 QTest::addColumn<quint32>("input"); 0760 QTest::addColumn<bool>("expected"); 0761 0762 QTest::newRow("flag_input") << quint32(1) << quint32(1) << true; 0763 QTest::newRow("flag_noinput") << quint32(1) << quint32(0) << false; 0764 QTest::newRow("noflag_input") << quint32(0) << quint32(1) << true; 0765 QTest::newRow("noflag_noinput") << quint32(0) << quint32(0) << true; 0766 QTest::newRow("flag_with_other_input") << quint32(1 | 1 << 8) << quint32(1) << true; 0767 QTest::newRow("flag_with_other_noinput") << quint32(1 | 1 << 8) << quint32(0) << false; 0768 } 0769 0770 void NetWinInfoTestClient::testInput() 0771 { 0772 QVERIFY(connection()); 0773 INFO 0774 0775 QVERIFY(info.input()); 0776 QFETCH(quint32, flags); 0777 QFETCH(quint32, input); 0778 0779 // group leader needs to be changed through wm hints 0780 uint32_t values[] = { 0781 flags, 0782 input, /* Input */ 0783 1, /* Normal State */ 0784 XCB_NONE, /* icon pixmap */ 0785 XCB_NONE, /* icon window */ 0786 XCB_NONE, /* icon x */ 0787 XCB_NONE, /* icon y */ 0788 XCB_NONE, /* icon mask */ 0789 XCB_NONE /* group leader */ 0790 }; 0791 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0792 XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, 9, values); 0793 xcb_flush(connection()); 0794 0795 // only updated after event 0796 waitForPropertyChange(&info, XCB_ATOM_WM_HINTS, NET::Property(0), NET::WM2Urgency); 0797 QTEST(info.input(), "expected"); 0798 } 0799 0800 Q_DECLARE_METATYPE(NET::MappingState) 0801 0802 void NetWinInfoTestClient::testInitialMappingState_data() 0803 { 0804 QTest::addColumn<quint32>("flags"); 0805 QTest::addColumn<quint32>("state"); 0806 QTest::addColumn<NET::MappingState>("expected"); 0807 0808 QTest::newRow("flag-iconic") << quint32(2) << quint32(3) << NET::Iconic; 0809 QTest::newRow("flag-normal") << quint32(2) << quint32(1) << NET::Visible; 0810 QTest::newRow("flag-invalid") << quint32(2) << quint32(8) << NET::Withdrawn; 0811 QTest::newRow("noflag-iconic") << quint32(256) << quint32(3) << NET::Withdrawn; 0812 QTest::newRow("noflag-normal") << quint32(256) << quint32(1) << NET::Withdrawn; 0813 } 0814 0815 void NetWinInfoTestClient::testInitialMappingState() 0816 { 0817 QVERIFY(connection()); 0818 INFO 0819 0820 QCOMPARE(info.initialMappingState(), NET::Withdrawn); 0821 QFETCH(quint32, flags); 0822 QFETCH(quint32, state); 0823 0824 // group leader needs to be changed through wm hints 0825 uint32_t values[] = { 0826 flags, 0827 1, /* Input */ 0828 state, /* Normal State */ 0829 XCB_NONE, /* icon pixmap */ 0830 XCB_NONE, /* icon window */ 0831 XCB_NONE, /* icon x */ 0832 XCB_NONE, /* icon y */ 0833 XCB_NONE, /* icon mask */ 0834 XCB_NONE /* group leader */ 0835 }; 0836 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0837 XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, 9, values); 0838 xcb_flush(connection()); 0839 0840 // only updated after event 0841 waitForPropertyChange(&info, XCB_ATOM_WM_HINTS, NET::Property(0), NET::WM2InitialMappingState); 0842 QTEST(info.initialMappingState(), "expected"); 0843 } 0844 0845 void NetWinInfoTestClient::testIconPixmap_data() 0846 { 0847 QTest::addColumn<quint32>("flags"); 0848 QTest::addColumn<quint32>("icon"); 0849 QTest::addColumn<quint32>("mask"); 0850 QTest::addColumn<quint32>("expectedPixmap"); 0851 QTest::addColumn<quint32>("expectedMask"); 0852 0853 QTest::newRow("invalid-flags") << 1u << 2u << 3u << 0u << 0u; 0854 QTest::newRow("pixmap-flags") << 4u << 2u << 3u << 2u << 0u; 0855 QTest::newRow("mask-flags") << 32u << 2u << 3u << 0u << 3u; 0856 QTest::newRow("pixmap-mask-flags") << 36u << 2u << 3u << 2u << 3u; 0857 } 0858 0859 void NetWinInfoTestClient::testIconPixmap() 0860 { 0861 QVERIFY(connection()); 0862 INFO 0863 0864 QCOMPARE(info.icccmIconPixmap(), 0u); 0865 QCOMPARE(info.icccmIconPixmapMask(), 0u); 0866 QFETCH(quint32, flags); 0867 QFETCH(quint32, icon); 0868 QFETCH(quint32, mask); 0869 0870 // icon pixmap needs to be changed through wm hints 0871 uint32_t values[] = { 0872 flags, 0873 1, /* Input */ 0874 XCB_NONE, /* Normal State */ 0875 icon, /* icon pixmap */ 0876 XCB_NONE, /* icon window */ 0877 XCB_NONE, /* icon x */ 0878 XCB_NONE, /* icon y */ 0879 mask, /* icon mask */ 0880 XCB_NONE /* group leader */ 0881 }; 0882 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0883 XCB_ATOM_WM_HINTS, XCB_ATOM_WM_HINTS, 32, 9, values); 0884 xcb_flush(connection()); 0885 // only updated after event 0886 waitForPropertyChange(&info, XCB_ATOM_WM_HINTS, NET::Property(0), NET::WM2IconPixmap); 0887 QTEST(info.icccmIconPixmap(), "expectedPixmap"); 0888 QTEST(info.icccmIconPixmapMask(), "expectedMask"); 0889 } 0890 0891 void NetWinInfoTestClient::testTransientFor() 0892 { 0893 QVERIFY(connection()); 0894 INFO 0895 0896 QVERIFY(info.transientFor() == XCB_WINDOW_NONE); 0897 // transient for needs to be changed using xcb 0898 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0899 XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, 1, &m_rootWindow); 0900 xcb_flush(connection()); 0901 0902 // only updated after event 0903 waitForPropertyChange(&info, XCB_ATOM_WM_TRANSIENT_FOR, NET::Property(0), NET::WM2TransientFor); 0904 QCOMPARE(info.transientFor(), m_rootWindow); 0905 } 0906 0907 void NetWinInfoTestClient::testWindowClass() 0908 { 0909 QVERIFY(connection()); 0910 INFO 0911 0912 QVERIFY(!info.windowClassClass()); 0913 QVERIFY(!info.windowClassName()); 0914 0915 // window class needs to be changed using xcb 0916 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0917 XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, 7, "foo\0bar"); 0918 xcb_flush(connection()); 0919 0920 // only updated after event 0921 waitForPropertyChange(&info, XCB_ATOM_WM_CLASS, NET::Property(0), NET::WM2WindowClass); 0922 QCOMPARE(info.windowClassName(), "foo"); 0923 QCOMPARE(info.windowClassClass(), "bar"); 0924 } 0925 0926 void NetWinInfoTestClient::testWindowRole() 0927 { 0928 QVERIFY(connection()); 0929 ATOM(WM_WINDOW_ROLE) 0930 INFO 0931 0932 QVERIFY(!info.windowRole()); 0933 0934 // window role needs to be changed using xcb 0935 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, 0936 atom, XCB_ATOM_STRING, 8, 3, "bar"); 0937 xcb_flush(connection()); 0938 0939 // only updated after event 0940 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2WindowRole); 0941 QCOMPARE(info.windowRole(), "bar"); 0942 } 0943 0944 void NetWinInfoTestClient::testActivities_data() 0945 { 0946 QTest::addColumn<QByteArray>("activities"); 0947 QTest::addColumn<QByteArray>("expectedActivities"); 0948 0949 const QByteArray testActivities = QByteArrayLiteral("foo,bar"); 0950 const QByteArray allActivities = QByteArrayLiteral(KDE_ALL_ACTIVITIES_UUID); 0951 0952 QTest::newRow("activities") << testActivities << testActivities; 0953 QTest::newRow("empty") << QByteArray() << allActivities; 0954 QTest::newRow("\\0") << QByteArrayLiteral("\0") << allActivities; 0955 } 0956 0957 void NetWinInfoTestClient::testActivities() 0958 { 0959 QVERIFY(connection()); 0960 ATOM(_KDE_NET_WM_ACTIVITIES) 0961 INFO 0962 0963 QVERIFY(!info.activities()); 0964 QFETCH(QByteArray, activities); 0965 0966 // activities needs to be changed using xcb 0967 info.setActivities(activities.isNull() ? nullptr : activities.constData()); 0968 xcb_flush(connection()); 0969 0970 // only updated after event 0971 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2Activities); 0972 QTEST(QByteArray(info.activities()), "expectedActivities"); 0973 } 0974 0975 Q_DECLARE_METATYPE(NET::Protocols) 0976 void NetWinInfoTestClient::testProtocols_data() 0977 { 0978 QTest::addColumn<NET::Protocols>("protocols"); 0979 QTest::addColumn<bool>("takeFocus"); 0980 QTest::addColumn<bool>("deleteWindow"); 0981 QTest::addColumn<bool>("ping"); 0982 QTest::addColumn<bool>("sync"); 0983 QTest::addColumn<bool>("context"); 0984 0985 const NET::Protocol t = NET::TakeFocusProtocol; 0986 const NET::Protocol d = NET::DeleteWindowProtocol; 0987 const NET::Protocol p = NET::PingProtocol; 0988 const NET::Protocol s = NET::SyncRequestProtocol; 0989 const NET::Protocol c = NET::ContextHelpProtocol; 0990 0991 QTest::newRow("none") << NET::Protocols(NET::NoProtocol) << false << false << false << false << false; 0992 0993 QTest::newRow("t") << NET::Protocols(t) << true << false << false << false << false; 0994 QTest::newRow("d") << NET::Protocols(d) << false << true << false << false << false; 0995 QTest::newRow("p") << NET::Protocols(p) << false << false << true << false << false; 0996 QTest::newRow("s") << NET::Protocols(s) << false << false << false << true << false; 0997 QTest::newRow("c") << NET::Protocols(c) << false << false << false << false << true; 0998 0999 // all two combinations with t 1000 QTest::newRow("t/d") << NET::Protocols(t | d) << true << true << false << false << false; 1001 QTest::newRow("t/p") << NET::Protocols(t | p) << true << false << true << false << false; 1002 QTest::newRow("t/s") << NET::Protocols(t | s) << true << false << false << true << false; 1003 QTest::newRow("t/c") << NET::Protocols(t | c) << true << false << false << false << true; 1004 // all two combinations with d 1005 QTest::newRow("d/p") << NET::Protocols(d | p) << false << true << true << false << false; 1006 QTest::newRow("d/s") << NET::Protocols(d | s) << false << true << false << true << false; 1007 QTest::newRow("d/c") << NET::Protocols(d | c) << false << true << false << false << true; 1008 // all two combinations with p 1009 QTest::newRow("p/s") << NET::Protocols(p | s) << false << false << true << true << false; 1010 QTest::newRow("p/c") << NET::Protocols(p | c) << false << false << true << false << true; 1011 // and remaining two combination 1012 QTest::newRow("s/c") << NET::Protocols(s | c) << false << false << false << true << true; 1013 1014 // all three combinations with t 1015 QTest::newRow("t/d/p") << NET::Protocols(t | d | p) << true << true << true << false << false; 1016 QTest::newRow("t/d/s") << NET::Protocols(t | d | s) << true << true << false << true << false; 1017 QTest::newRow("t/d/c") << NET::Protocols(t | d | c) << true << true << false << false << true; 1018 QTest::newRow("t/p/s") << NET::Protocols(t | p | s) << true << false << true << true << false; 1019 QTest::newRow("t/p/c") << NET::Protocols(t | p | c) << true << false << true << false << true; 1020 QTest::newRow("t/s/c") << NET::Protocols(t | s | c) << true << false << false << true << true; 1021 // all three combinations with d 1022 QTest::newRow("d/p/s") << NET::Protocols(d | p | s) << false << true << true << true << false; 1023 QTest::newRow("d/p/c") << NET::Protocols(d | p | c) << false << true << true << false << true; 1024 QTest::newRow("d/s/c") << NET::Protocols(d | s | c) << false << true << false << true << true; 1025 // and remaining 1026 QTest::newRow("p/s/c") << NET::Protocols(p | s | c) << false << false << true << true << true; 1027 1028 QTest::newRow("t/d/p/s") << NET::Protocols(t | d | p | s) << true << true << true << true << false; 1029 QTest::newRow("t/d/p/c") << NET::Protocols(t | d | p | c) << true << true << true << false << true; 1030 QTest::newRow("t/d/s/c") << NET::Protocols(t | d | s | c) << true << true << false << true << true; 1031 QTest::newRow("t/p/s/c") << NET::Protocols(t | p | s | c) << true << false << true << true << true; 1032 QTest::newRow("d/p/s/c") << NET::Protocols(d | p | s | c) << false << true << true << true << true; 1033 1034 QTest::newRow("all") << NET::Protocols(t | d | p | s | c) << true << true << true << true << true; 1035 } 1036 1037 void NetWinInfoTestClient::testProtocols() 1038 { 1039 QVERIFY(connection()); 1040 ATOM(WM_PROTOCOLS) 1041 KXUtils::Atom takeFocus(connection(), QByteArrayLiteral("WM_TAKE_FOCUS")); 1042 KXUtils::Atom deleteWindow(connection(), QByteArrayLiteral("WM_DELETE_WINDOW")); 1043 KXUtils::Atom ping(connection(), QByteArrayLiteral("_NET_WM_PING")); 1044 KXUtils::Atom syncRequest(connection(), QByteArrayLiteral("_NET_WM_SYNC_REQUEST")); 1045 KXUtils::Atom contextHelp(connection(), QByteArrayLiteral("_NET_WM_CONTEXT_HELP")); 1046 INFO 1047 1048 QVERIFY(!info.supportsProtocol(NET::TakeFocusProtocol)); 1049 QVERIFY(!info.supportsProtocol(NET::DeleteWindowProtocol)); 1050 QVERIFY(!info.supportsProtocol(NET::PingProtocol)); 1051 QVERIFY(!info.supportsProtocol(NET::SyncRequestProtocol)); 1052 QVERIFY(!info.supportsProtocol(NET::ContextHelpProtocol)); 1053 QCOMPARE(info.protocols(), NET::Protocols(NET::NoProtocol)); 1054 1055 QVector<xcb_atom_t> props; 1056 QFETCH(NET::Protocols, protocols); 1057 if (protocols.testFlag(NET::TakeFocusProtocol)) { 1058 props << takeFocus; 1059 } 1060 if (protocols.testFlag(NET::DeleteWindowProtocol)) { 1061 props << deleteWindow; 1062 } 1063 if (protocols.testFlag(NET::PingProtocol)) { 1064 props << ping; 1065 } 1066 if (protocols.testFlag(NET::SyncRequestProtocol)) { 1067 props << syncRequest; 1068 } 1069 if (protocols.testFlag(NET::ContextHelpProtocol)) { 1070 props << contextHelp; 1071 } 1072 1073 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, atom, XCB_ATOM_ATOM, 32, props.size(), props.constData()); 1074 xcb_flush(connection()); 1075 1076 // only updated after event 1077 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2Protocols); 1078 QCOMPARE(info.protocols(), protocols); 1079 QTEST(info.supportsProtocol(NET::TakeFocusProtocol), "takeFocus"); 1080 QTEST(info.supportsProtocol(NET::DeleteWindowProtocol), "deleteWindow"); 1081 QTEST(info.supportsProtocol(NET::PingProtocol), "ping"); 1082 QTEST(info.supportsProtocol(NET::SyncRequestProtocol), "sync"); 1083 QTEST(info.supportsProtocol(NET::ContextHelpProtocol), "context"); 1084 1085 xcb_delete_property(connection(), m_testWindow, atom); 1086 xcb_flush(connection()); 1087 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2Protocols); 1088 QVERIFY(!info.supportsProtocol(NET::TakeFocusProtocol)); 1089 QVERIFY(!info.supportsProtocol(NET::DeleteWindowProtocol)); 1090 QVERIFY(!info.supportsProtocol(NET::PingProtocol)); 1091 QVERIFY(!info.supportsProtocol(NET::SyncRequestProtocol)); 1092 QVERIFY(!info.supportsProtocol(NET::ContextHelpProtocol)); 1093 QCOMPARE(info.protocols(), NET::Protocols(NET::NoProtocol)); 1094 } 1095 1096 void NetWinInfoTestClient::testOpaqueRegion_data() 1097 { 1098 QTest::addColumn<QVector<QRect> >("geometries"); 1099 1100 QTest::newRow("none") << QVector<QRect>(); 1101 QTest::newRow("empty") << QVector<QRect>({QRect(0, 0, 0, 0)}); 1102 QTest::newRow("one rect") << QVector<QRect>({QRect(10, 20, 30, 40)}); 1103 QTest::newRow("two rect") << QVector<QRect>({QRect(10, 20, 30, 40), QRect(1, 2, 4, 5)}); 1104 QTest::newRow("multiple") << QVector<QRect>({QRect(10, 20, 30, 40), 1105 QRect(1, 2, 4, 5), 1106 QRect(100, 0, 200, 400), 1107 QRect(1, 2, 4, 5)}); 1108 } 1109 1110 void NetWinInfoTestClient::testOpaqueRegion() 1111 { 1112 QVERIFY(connection()); 1113 ATOM(_NET_WM_OPAQUE_REGION) 1114 INFO 1115 1116 QCOMPARE(info.opaqueRegion().size(), std::size_t(0)); 1117 1118 QFETCH(QVector<QRect>, geometries); 1119 QVector<qint32> data; 1120 for (auto it = geometries.constBegin(); it != geometries.constEnd(); ++it) { 1121 const QRect &r = *it; 1122 data << r.x(); 1123 data << r.y(); 1124 data << r.width(); 1125 data << r.height(); 1126 } 1127 1128 xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, m_testWindow, atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData()); 1129 xcb_flush(connection()); 1130 1131 // only updated after event 1132 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2OpaqueRegion); 1133 const auto opaqueRegion = info.opaqueRegion(); 1134 QCOMPARE(opaqueRegion.size(), std::size_t(geometries.size())); 1135 1136 for (std::size_t i = 0; i < opaqueRegion.size(); ++i) { 1137 auto r1 = opaqueRegion.at(i); 1138 auto r2 = geometries.at(i); 1139 QCOMPARE(r1.pos.x, r2.x()); 1140 QCOMPARE(r1.pos.y, r2.y()); 1141 QCOMPARE(r1.size.width, r2.width()); 1142 QCOMPARE(r1.size.height, r2.height()); 1143 } 1144 1145 xcb_delete_property(connection(), m_testWindow, atom); 1146 xcb_flush(connection()); 1147 waitForPropertyChange(&info, atom, NET::Property(0), NET::WM2OpaqueRegion); 1148 QCOMPARE(info.opaqueRegion().size(), std::size_t(0)); 1149 } 1150 1151 QTEST_GUILESS_MAIN(NetWinInfoTestClient) 1152 1153 #include "netwininfotestclient.moc"