Warning, file /plasma/plasma-workspace/libtaskmanager/autotests/xwindowtasksmodeltest.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: 2022 Fushan Wen <qydwhotmail@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include <array> 0008 0009 #include <QX11Info> 0010 0011 #include <KActivities/Consumer> 0012 0013 #include <xcb/xcb.h> 0014 #include <xcb/xproto.h> 0015 0016 #include "common.h" 0017 #include "xwindowtasksmodel.h" 0018 0019 using namespace TaskManager; 0020 using MimeDataMap = QMap<QString, QByteArray>; 0021 0022 class XWindowTasksModelTest : public QObject 0023 { 0024 Q_OBJECT 0025 0026 private Q_SLOTS: 0027 void initTestCase(); 0028 void cleanupTestCase(); 0029 0030 void test_winIdFromMimeData_data(); 0031 void test_winIdFromMimeData(); 0032 void test_winIdsFromMimeData_data(); 0033 void test_winIdsFromMimeData(); 0034 0035 void test_openCloseWindow(); 0036 void test_modelData(); 0037 void test_isMinimized(); 0038 void test_fullscreen(); 0039 void test_geometry(); 0040 void test_stackingOrder(); 0041 void test_lastActivated(); 0042 void test_modelDataFromDesktopFile(); 0043 void test_windowState(); 0044 0045 void test_request(); 0046 0047 private: 0048 WId m_WId = 12345; 0049 QByteArray m_singleWId; 0050 QByteArray m_threeWIds; 0051 QByteArray m_negativeCountWIds; 0052 QByteArray m_insufficientWIds; 0053 0054 XWindowTasksModel m_model; 0055 }; 0056 0057 void XWindowTasksModelTest::initTestCase() 0058 { 0059 if (!KWindowSystem::isPlatformX11()) { 0060 QSKIP("Test is not running on X11."); 0061 } 0062 0063 char *singleWIdData = new char[sizeof(WId)]; 0064 memcpy(singleWIdData, &m_WId, sizeof(WId)); 0065 m_singleWId = QByteArray(singleWIdData, sizeof(WId)); 0066 delete[] singleWIdData; 0067 0068 constexpr int count = 3; 0069 char *threeWIdsData = new char[sizeof(int) + sizeof(WId) * count]; 0070 memcpy(threeWIdsData, &count, sizeof(int)); 0071 for (int i = 0; i < count; ++i) { 0072 memcpy(threeWIdsData + sizeof(int) + sizeof(WId) * i, &m_WId, sizeof(WId)); 0073 } 0074 m_threeWIds = QByteArray(threeWIdsData, sizeof(int) + sizeof(WId) * count); 0075 delete[] threeWIdsData; 0076 0077 constexpr int negativeCount = -count; 0078 char *negativeWIdsData = new char[sizeof(int) + sizeof(WId) * count]; 0079 memcpy(negativeWIdsData, &negativeCount, sizeof(int)); 0080 for (int i = 0; i < count; ++i) { 0081 memcpy(negativeWIdsData + sizeof(int) + sizeof(WId) * i, &m_WId, sizeof(WId)); 0082 } 0083 m_negativeCountWIds = QByteArray(negativeWIdsData, sizeof(int) + sizeof(WId) * count); 0084 delete[] negativeWIdsData; 0085 0086 constexpr int insufficientCount = count - 1; 0087 char *insufficientWIdsData = new char[sizeof(int) + sizeof(WId) * insufficientCount]; 0088 memcpy(insufficientWIdsData, &count, sizeof(int)); 0089 for (int i = 0; i < insufficientCount; ++i) { 0090 memcpy(insufficientWIdsData + sizeof(int) + sizeof(WId) * i, &m_WId, sizeof(WId)); 0091 } 0092 m_insufficientWIds = QByteArray(insufficientWIdsData, sizeof(int) + sizeof(WId) * insufficientCount); 0093 delete[] insufficientWIdsData; 0094 0095 QGuiApplication::setQuitOnLastWindowClosed(false); 0096 0097 QStandardPaths::setTestModeEnabled(true); 0098 0099 const QString applicationDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QDir::separator() + QStringLiteral("applications"); 0100 QDir dir; 0101 if (!dir.exists(applicationDir)) { 0102 dir.mkpath(applicationDir); 0103 } 0104 } 0105 0106 void XWindowTasksModelTest::cleanupTestCase() 0107 { 0108 TestUtils::cleanupTestCase(); 0109 } 0110 0111 void XWindowTasksModelTest::test_winIdFromMimeData_data() 0112 { 0113 QTest::addColumn<QString>("mimeType"); 0114 QTest::addColumn<QByteArray>("data"); 0115 QTest::addColumn<bool>("isOK"); 0116 0117 QTest::newRow("Valid WId") << QStringLiteral("windowsystem/winid") // XWindowTasksModel::Private::mimeType() 0118 << m_singleWId << true; 0119 QTest::newRow("Invalid WId") << QStringLiteral("windowsystem/winid") << QByteArray("\x06") << false; 0120 QTest::newRow("Invalid mimeType") << QStringLiteral("text/plain") << m_singleWId << false; 0121 } 0122 0123 void XWindowTasksModelTest::test_winIdFromMimeData() 0124 { 0125 QFETCH(QString, mimeType); 0126 QFETCH(QByteArray, data); 0127 QFETCH(bool, isOK); 0128 0129 QMimeData mimeData; 0130 mimeData.setData(mimeType, data); 0131 qDebug() << data << "data size:" << data.size(); 0132 0133 bool ok = !isOK; 0134 WId result = XWindowTasksModel::winIdFromMimeData(&mimeData, &ok); 0135 QCOMPARE(ok, isOK); 0136 if (isOK) { 0137 QCOMPARE(result, m_WId); 0138 } 0139 } 0140 0141 void XWindowTasksModelTest::test_winIdsFromMimeData_data() 0142 { 0143 QTest::addColumn<MimeDataMap>("mimeDataMap"); 0144 QTest::addColumn<bool>("isOK"); 0145 QTest::addColumn<int>("count"); 0146 0147 // if (!mimeData->hasFormat(Private::groupMimeType())) 0148 MimeDataMap data1; 0149 data1.insert(QStringLiteral("windowsystem/winid"), m_singleWId); 0150 QTest::newRow("Single WId") << data1 << true << data1.size(); 0151 0152 MimeDataMap data2; 0153 data2.insert(QStringLiteral("windowsystem/winid"), QByteArray("\x06")); 0154 QTest::newRow("Invalid WId") << data2 << false << 0; 0155 0156 MimeDataMap data3; 0157 data3.insert(QStringLiteral("windowsystem/multiple-winids"), m_threeWIds); 0158 QTest::newRow("Three WIds") << data3 << true << 3; 0159 0160 // if ((unsigned int)data.size() < sizeof(int) + sizeof(WId)) 0161 MimeDataMap data4; 0162 data4.insert(QStringLiteral("windowsystem/multiple-winids"), QByteArray("\x06")); 0163 data4.insert(QStringLiteral("windowsystem/winid"), m_singleWId); 0164 QTest::newRow("Invalid WIds") << data4 << false << 0; 0165 0166 // count < 1 0167 MimeDataMap data5; 0168 data5.insert(QStringLiteral("windowsystem/multiple-winids"), m_negativeCountWIds); 0169 QTest::newRow("Negative count WIds") << data5 << false << 0; 0170 0171 // (unsigned int)data.size() < sizeof(int) + sizeof(WId) * count 0172 MimeDataMap data6; 0173 data6.insert(QStringLiteral("windowsystem/multiple-winids"), m_insufficientWIds); 0174 QTest::newRow("Insufficient count WIds") << data6 << false << 0; 0175 } 0176 0177 void XWindowTasksModelTest::test_winIdsFromMimeData() 0178 { 0179 QFETCH(MimeDataMap, mimeDataMap); 0180 QFETCH(bool, isOK); 0181 QFETCH(int, count); 0182 0183 QMimeData mimeData; 0184 for (auto it = mimeDataMap.cbegin(); it != mimeDataMap.cend(); it = std::next(it)) { 0185 mimeData.setData(it.key(), it.value()); 0186 } 0187 0188 bool ok = !isOK; 0189 auto results = XWindowTasksModel::winIdsFromMimeData(&mimeData, &ok); 0190 QCOMPARE(ok, isOK); 0191 QCOMPARE(results.size(), count); 0192 if (count > 0) { 0193 const bool verified = std::all_of(results.cbegin(), results.cend(), [this](WId id) { 0194 return id == m_WId; 0195 }); 0196 QVERIFY(verified); 0197 } 0198 } 0199 0200 void XWindowTasksModelTest::test_openCloseWindow() 0201 { 0202 TestUtils::testOpenCloseWindow(m_model); 0203 } 0204 0205 void XWindowTasksModelTest::test_modelData() 0206 { 0207 const QString title = QStringLiteral("__testwindow__%1").arg(QDateTime::currentDateTime().toString()); 0208 QModelIndex index; 0209 auto window = TestUtils::createSingleWindow(m_model, title, index); 0210 0211 // See XWindowTasksModel::data for available roles 0212 { // BEGIN Icon 0213 QSignalSpy dataChangedSpy(&m_model, &XWindowTasksModel::dataChanged); 0214 qDebug() << "Start testing Qt::DecorationRole"; 0215 const QIcon oldWindowIcon = index.data(Qt::DecorationRole).value<QIcon>(); // X11 icon 0216 QVERIFY(!oldWindowIcon.isNull()); 0217 window->setIcon(QIcon(QFINDTESTDATA("data/windows/samplewidgetwindow.png"))); 0218 QVERIFY(dataChangedSpy.wait()); 0219 QVERIFY(dataChangedSpy.takeLast().at(2).value<QVector<int>>().contains(Qt::DecorationRole)); 0220 0221 const QIcon newWindowIcon = index.data(Qt::DecorationRole).value<QIcon>(); 0222 QVERIFY(!newWindowIcon.isNull()); 0223 QVERIFY(oldWindowIcon.pixmap(KIconLoader::SizeLarge).toImage().pixelColor(KIconLoader::SizeLarge / 2, KIconLoader::SizeLarge / 2) 0224 != newWindowIcon.pixmap(KIconLoader::SizeLarge).toImage().pixelColor(KIconLoader::SizeLarge / 2, KIconLoader::SizeLarge / 2)); 0225 0226 window->setIcon(QIcon()); 0227 QVERIFY(dataChangedSpy.wait()); 0228 QVERIFY(dataChangedSpy.takeLast().at(2).value<QVector<int>>().contains(Qt::DecorationRole)); 0229 } // END Icon 0230 0231 const NET::Properties windowInfoFlags = 0232 NET::WMState | NET::XAWMState | NET::WMDesktop | NET::WMVisibleName | NET::WMGeometry | NET::WMFrameExtents | NET::WMWindowType | NET::WMPid; 0233 const NET::Properties2 windowInfoFlags2 = NET::WM2DesktopFileName | NET::WM2Activities | NET::WM2WindowClass | NET::WM2AllowedActions 0234 | NET::WM2AppMenuObjectPath | NET::WM2AppMenuServiceName | NET::WM2GTKApplicationId; 0235 KWindowInfo info(window->winId(), windowInfoFlags, windowInfoFlags2); 0236 0237 QTRY_COMPARE(index.data(AbstractTasksModel::AppId).toString(), info.windowClassClass()); 0238 QTRY_COMPARE(index.data(AbstractTasksModel::AppName).toString(), info.windowClassClass()); 0239 QTRY_COMPARE(index.data(AbstractTasksModel::GenericName).toString(), QString()); 0240 QTRY_VERIFY(index.data(AbstractTasksModel::LauncherUrl).toUrl().toLocalFile().endsWith(info.windowClassClass())); 0241 QTRY_VERIFY(index.data(AbstractTasksModel::LauncherUrlWithoutIcon).toUrl().toLocalFile().endsWith(info.windowClassClass())); 0242 QTRY_COMPARE(index.data(AbstractTasksModel::WinIdList).toList().size(), 1); 0243 QTRY_COMPARE(index.data(AbstractTasksModel::MimeType).toString(), QStringLiteral("windowsystem/winid")); 0244 0245 { 0246 QMimeData mimeData; 0247 mimeData.setData(index.data(AbstractTasksModel::MimeType).toString(), index.data(AbstractTasksModel::MimeData).toByteArray()); 0248 bool ok = false; 0249 XWindowTasksModel::winIdFromMimeData(&mimeData, &ok); 0250 QVERIFY(ok); 0251 } 0252 0253 QTRY_VERIFY(index.data(AbstractTasksModel::IsWindow).toBool()); 0254 QTRY_VERIFY(index.data(AbstractTasksModel::IsActive).toBool()); 0255 0256 QTRY_VERIFY(index.data(AbstractTasksModel::IsClosable).toBool()); 0257 QTRY_VERIFY(index.data(AbstractTasksModel::IsMovable).toBool()); 0258 QTRY_VERIFY(index.data(AbstractTasksModel::IsResizable).toBool()); 0259 QTRY_VERIFY(index.data(AbstractTasksModel::IsMaximizable).toBool()); 0260 QTRY_VERIFY(!index.data(AbstractTasksModel::IsMaximized).toBool()); 0261 QTRY_VERIFY(index.data(AbstractTasksModel::IsMinimizable).toBool()); 0262 QTRY_VERIFY(!index.data(AbstractTasksModel::IsKeepAbove).toBool()); 0263 QTRY_VERIFY(!index.data(AbstractTasksModel::IsKeepBelow).toBool()); 0264 QTRY_VERIFY(index.data(AbstractTasksModel::IsFullScreenable).toBool()); 0265 QTRY_VERIFY(!index.data(AbstractTasksModel::IsFullScreen).toBool()); 0266 QTRY_VERIFY(index.data(AbstractTasksModel::IsShadeable).toBool()); 0267 QTRY_VERIFY(!index.data(AbstractTasksModel::IsShaded).toBool()); 0268 QTRY_VERIFY(index.data(AbstractTasksModel::IsVirtualDesktopsChangeable).toBool()); 0269 QTRY_VERIFY(!index.data(AbstractTasksModel::IsOnAllVirtualDesktops).toBool()); 0270 0271 // Due to window decoration, the size of a window can't be determined accurately 0272 const QRect screenGeometry = index.data(AbstractTasksModel::ScreenGeometry).toRect(); 0273 QVERIFY(screenGeometry.width() > 0 && screenGeometry.height() > 0); 0274 0275 KActivities::Consumer activityConsumer; 0276 qDebug() << "Start testing AbstractTasksModel::Activities. Current activity number:" << activityConsumer.runningActivities().size(); 0277 if (activityConsumer.runningActivities().size() > 0) { 0278 QCOMPARE(index.data(AbstractTasksModel::Activities).toStringList(), info.activities()); 0279 } else { 0280 // In CI the window manager is openbox, so there could be no running activity. 0281 QCOMPARE(index.data(AbstractTasksModel::Activities).toStringList().size(), 0); 0282 } 0283 0284 QTRY_VERIFY(!index.data(AbstractTasksModel::IsDemandingAttention).toBool()); 0285 QTRY_VERIFY(!index.data(AbstractTasksModel::SkipTaskbar).toBool()); 0286 QTRY_VERIFY(!index.data(AbstractTasksModel::SkipPager).toBool()); 0287 QTRY_COMPARE(index.data(AbstractTasksModel::AppPid).toInt(), info.pid()); 0288 0289 QVERIFY(index.data(AbstractTasksModel::CanLaunchNewInstance).toBool()); 0290 } 0291 0292 void XWindowTasksModelTest::test_isMinimized() 0293 { 0294 const QString title = QStringLiteral("__testwindow__%1").arg(QDateTime::currentDateTime().toString()); 0295 QModelIndex index; 0296 auto window = TestUtils::createSingleWindow(m_model, title, index); 0297 0298 QTRY_VERIFY(!index.data(AbstractTasksModel::IsMinimized).toBool()); 0299 QTRY_VERIFY(!index.data(AbstractTasksModel::IsHidden).toBool()); 0300 0301 // Minimize the window 0302 QSignalSpy dataChangedSpy(&m_model, &XWindowTasksModel::dataChanged); 0303 window->showMinimized(); 0304 dataChangedSpy.wait(); 0305 // There can be more than one dataChanged signal being emitted due to caching 0306 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0307 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsMinimized); 0308 })); 0309 // The model doesn't notify data change stored under IsHidden role 0310 QTRY_VERIFY(std::none_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0311 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsHidden); 0312 })); 0313 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0314 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsActive); 0315 })); 0316 QTRY_VERIFY(index.data(AbstractTasksModel::IsMinimized).toBool()); 0317 QTRY_VERIFY(index.data(AbstractTasksModel::IsHidden).toBool()); 0318 QTRY_VERIFY(!index.data(AbstractTasksModel::IsActive).toBool()); 0319 0320 // Restore the window 0321 dataChangedSpy.clear(); 0322 window->showNormal(); 0323 window->raise(); 0324 window->requestActivate(); 0325 dataChangedSpy.wait(); 0326 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0327 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsMinimized); 0328 })); 0329 QVERIFY(std::none_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0330 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsHidden); 0331 })); 0332 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0333 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsActive); 0334 })); 0335 QTRY_VERIFY(!index.data(AbstractTasksModel::IsMinimized).toBool()); 0336 QTRY_VERIFY(!index.data(AbstractTasksModel::IsHidden).toBool()); 0337 QTRY_VERIFY(index.data(AbstractTasksModel::IsActive).toBool()); 0338 } 0339 0340 void XWindowTasksModelTest::test_fullscreen() 0341 { 0342 TestUtils::testFullscreen(m_model); 0343 } 0344 0345 void XWindowTasksModelTest::test_geometry() 0346 { 0347 TestUtils::testGeometry(m_model); 0348 } 0349 0350 void XWindowTasksModelTest::test_stackingOrder() 0351 { 0352 TestUtils::testStackingOrder(m_model); 0353 } 0354 0355 void XWindowTasksModelTest::test_lastActivated() 0356 // Re-activate the window to update the last activated time 0357 { 0358 const QString title = QStringLiteral("__testwindow__%1").arg(QDateTime::currentDateTime().toString()); 0359 QModelIndex index; 0360 auto window = TestUtils::createSingleWindow(m_model, title, index); 0361 0362 QSignalSpy dataChangedSpy(&m_model, &XWindowTasksModel::dataChanged); 0363 window->showMinimized(); 0364 dataChangedSpy.wait(); 0365 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0366 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::IsMinimized); 0367 })); 0368 QTRY_VERIFY(index.data(AbstractTasksModel::IsMinimized).toBool()); 0369 0370 window->showNormal(); 0371 window->raise(); 0372 window->requestActivate(); 0373 const QTime lastActivatedTime = QTime::currentTime(); 0374 dataChangedSpy.wait(); 0375 // There can be more than one dataChanged signal being emitted due to caching 0376 QTRY_VERIFY(!index.data(AbstractTasksModel::IsMinimized).toBool()); 0377 // The model doesn't notify data change stored under LastActivated role 0378 QTRY_VERIFY(std::none_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [](const QVariantList &list) { 0379 return list.at(2).value<QVector<int>>().contains(AbstractTasksModel::LastActivated); 0380 })); 0381 qDebug() << lastActivatedTime.msecsSinceStartOfDay() << index.data(AbstractTasksModel::LastActivated).toTime().msecsSinceStartOfDay(); 0382 QVERIFY(std::abs(lastActivatedTime.msecsSinceStartOfDay() - index.data(AbstractTasksModel::LastActivated).toTime().msecsSinceStartOfDay()) < 1000); 0383 } 0384 0385 void XWindowTasksModelTest::test_modelDataFromDesktopFile() 0386 { 0387 TestUtils::testModelDataFromDesktopFile(m_model); 0388 } 0389 0390 void XWindowTasksModelTest::test_windowState() 0391 { 0392 QSignalSpy rowsInsertedSpy(&m_model, &XWindowTasksModel::rowsInserted); 0393 0394 const QString title = QStringLiteral("__testwindow__%1").arg(QDateTime::currentDateTime().toString()); 0395 QModelIndex index; 0396 auto window = TestUtils::createSingleWindow(m_model, title, index); 0397 0398 QSignalSpy dataChangedSpy(&m_model, &XWindowTasksModel::dataChanged); 0399 0400 // NETWinInfo only allows a window manager set window states 0401 std::array<std::string, 11> actions{ 0402 "_NET_WM_ACTION_MOVE", 0403 "_NET_WM_ACTION_RESIZE", 0404 "_NET_WM_ACTION_MINIMIZE", 0405 "_NET_WM_ACTION_SHADE", 0406 "_NET_WM_ACTION_STICK", 0407 "_NET_WM_ACTION_MAXIMIZE_VERT", 0408 "_NET_WM_ACTION_MAXIMIZE_HORZ", 0409 "_NET_WM_ACTION_FULLSCREEN", 0410 "_NET_WM_ACTION_CHANGE_DESKTOP", 0411 "_NET_WM_ACTION_CLOSE", 0412 "_NET_WM_ALLOWED_ACTIONS", 0413 }; 0414 xcb_atom_t atoms[11]; 0415 { 0416 xcb_intern_atom_cookie_t cookies[11]; 0417 for (std::size_t i = 0; i < actions.size(); ++i) { 0418 cookies[i] = xcb_intern_atom(QX11Info::connection(), false, actions[i].size(), actions[i].c_str()); 0419 } 0420 // Get the replies 0421 for (std::size_t i = 0; i < actions.size(); ++i) { 0422 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(QX11Info::connection(), cookies[i], nullptr); 0423 if (!reply) { 0424 continue; 0425 } 0426 atoms[i] = reply->atom; 0427 free(reply); 0428 } 0429 qDebug() << "XCB atom cached"; 0430 } 0431 0432 auto setAllowedActionsAndVerify = [&](AbstractTasksModel::AdditionalRoles role, NET::Actions allowedActions, bool &success) { 0433 qDebug() << "Start testing" << role; 0434 success = false; 0435 dataChangedSpy.clear(); 0436 QVERIFY(index.data(role).toBool()); 0437 0438 uint32_t data[50]; 0439 int count = 0; 0440 if (allowedActions & NET::ActionMove) { 0441 data[count++] = atoms[0]; 0442 } 0443 if (allowedActions & NET::ActionResize) { 0444 data[count++] = atoms[1]; 0445 } 0446 if (allowedActions & NET::ActionMinimize) { 0447 data[count++] = atoms[2]; 0448 } 0449 if (allowedActions & NET::ActionShade) { 0450 data[count++] = atoms[3]; 0451 } 0452 if (allowedActions & NET::ActionStick) { 0453 data[count++] = atoms[4]; 0454 } 0455 if (allowedActions & NET::ActionMaxVert) { 0456 data[count++] = atoms[5]; 0457 } 0458 if (allowedActions & NET::ActionMaxHoriz) { 0459 data[count++] = atoms[6]; 0460 } 0461 if (allowedActions & NET::ActionFullScreen) { 0462 data[count++] = atoms[7]; 0463 } 0464 if (allowedActions & NET::ActionChangeDesktop) { 0465 data[count++] = atoms[8]; 0466 } 0467 if (allowedActions & NET::ActionClose) { 0468 data[count++] = atoms[9]; 0469 } 0470 0471 xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, window->winId(), atoms[10], XCB_ATOM_ATOM, 32, count, (const void *)data); 0472 xcb_flush(QX11Info::connection()); 0473 QCoreApplication::processEvents(); 0474 0475 QTRY_VERIFY(std::any_of(dataChangedSpy.cbegin(), dataChangedSpy.cend(), [role](const QVariantList &list) { 0476 return list.at(2).value<QVector<int>>().contains(role); 0477 })); 0478 QVERIFY(!index.data(role).toBool()); 0479 success = true; 0480 }; 0481 0482 bool success = false; 0483 const auto fullFlags = NET::ActionMove | NET::ActionResize | NET::ActionMinimize | NET::ActionShade | NET::ActionStick | NET::ActionMaxVert 0484 | NET::ActionMaxHoriz | NET::ActionFullScreen | NET::ActionChangeDesktop | NET::ActionClose; 0485 0486 // Make the window not movable 0487 setAllowedActionsAndVerify(AbstractTasksModel::IsMovable, fullFlags & (~NET::ActionMove), success); 0488 QVERIFY(success); 0489 0490 // Make the window not resizable 0491 setAllowedActionsAndVerify(AbstractTasksModel::IsResizable, fullFlags & (~NET::ActionResize), success); 0492 QVERIFY(success); 0493 0494 // Make the window not maximizable 0495 setAllowedActionsAndVerify(AbstractTasksModel::IsMaximizable, fullFlags & (~NET::ActionMax), success); 0496 QVERIFY(success); 0497 0498 // Make the window not minimizable 0499 setAllowedActionsAndVerify(AbstractTasksModel::IsMinimizable, fullFlags & (~NET::ActionMinimize), success); 0500 QVERIFY(success); 0501 0502 // Make the window not fullscreenable 0503 setAllowedActionsAndVerify(AbstractTasksModel::IsFullScreenable, fullFlags & (~NET::ActionFullScreen), success); 0504 QVERIFY(success); 0505 0506 // Make the window not shadeable 0507 setAllowedActionsAndVerify(AbstractTasksModel::IsShadeable, fullFlags & (~NET::ActionShade), success); 0508 QVERIFY(success); 0509 0510 // Make the window not able to change virtual desktop 0511 setAllowedActionsAndVerify(AbstractTasksModel::IsVirtualDesktopsChangeable, fullFlags & (~NET::ActionChangeDesktop), success); 0512 QVERIFY(success); 0513 0514 // Make the window not closable 0515 setAllowedActionsAndVerify(AbstractTasksModel::IsClosable, fullFlags & (~NET::ActionClose), success); 0516 QVERIFY(success); 0517 } 0518 0519 void XWindowTasksModelTest::test_request() 0520 { 0521 TestUtils::testRequest(m_model); 0522 } 0523 0524 QTEST_MAIN(XWindowTasksModelTest) 0525 0526 #include "xwindowtasksmodeltest.moc"