File indexing completed on 2024-05-19 09:23:02

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 "activities.h"
0012 #include "core/output.h"
0013 #include "pointer_input.h"
0014 #include "utils/xcbutils.h"
0015 #include "wayland_server.h"
0016 #include "workspace.h"
0017 #include "x11window.h"
0018 
0019 #include <QDBusConnection>
0020 #include <QDBusMessage>
0021 #include <QDBusPendingCall>
0022 
0023 #include <netwm.h>
0024 #include <xcb/xcb_icccm.h>
0025 
0026 namespace KWin
0027 {
0028 
0029 static const QString s_socketName = QStringLiteral("wayland_test_kwin_activities-0");
0030 
0031 class ActivitiesTest : public QObject
0032 {
0033     Q_OBJECT
0034 private Q_SLOTS:
0035     void initTestCase();
0036     void cleanupTestCase();
0037     void init();
0038     void cleanup();
0039     void testSetOnActivitiesValidates();
0040 
0041 private:
0042 };
0043 
0044 void ActivitiesTest::initTestCase()
0045 {
0046     qRegisterMetaType<KWin::Window *>();
0047     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0048     QVERIFY(waylandServer()->init(s_socketName));
0049     Test::setOutputConfig({
0050         QRect(0, 0, 1280, 1024),
0051         QRect(1280, 0, 1280, 1024),
0052     });
0053 
0054     kwinApp()->setUseKActivities(true);
0055     kwinApp()->start();
0056     QVERIFY(applicationStartedSpy.wait());
0057     const auto outputs = workspace()->outputs();
0058     QCOMPARE(outputs.count(), 2);
0059     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0060     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0061     setenv("QT_QPA_PLATFORM", "wayland", true);
0062 }
0063 
0064 void ActivitiesTest::cleanupTestCase()
0065 {
0066     // terminate any still running kactivitymanagerd
0067     QDBusConnection::sessionBus().asyncCall(QDBusMessage::createMethodCall(
0068         QStringLiteral("org.kde.ActivityManager"),
0069         QStringLiteral("/ActivityManager"),
0070         QStringLiteral("org.qtproject.Qt.QCoreApplication"),
0071         QStringLiteral("quit")));
0072 }
0073 
0074 void ActivitiesTest::init()
0075 {
0076     workspace()->setActiveOutput(QPoint(640, 512));
0077     input()->pointer()->warp(QPoint(640, 512));
0078 }
0079 
0080 void ActivitiesTest::cleanup()
0081 {
0082 }
0083 
0084 void ActivitiesTest::testSetOnActivitiesValidates()
0085 {
0086     // this test verifies that windows can't be placed on activities that don't exist
0087     // create an xcb window
0088     Test::XcbConnectionPtr c = Test::createX11Connection();
0089     QVERIFY(!xcb_connection_has_error(c.get()));
0090 
0091     xcb_window_t windowId = xcb_generate_id(c.get());
0092     const QRect windowGeometry(0, 0, 100, 200);
0093 
0094     auto cookie = xcb_create_window_checked(c.get(), 0, windowId, rootWindow(),
0095                                             windowGeometry.x(),
0096                                             windowGeometry.y(),
0097                                             windowGeometry.width(),
0098                                             windowGeometry.height(),
0099                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT, 0, 0, nullptr);
0100     QVERIFY(!xcb_request_check(c.get(), cookie));
0101     xcb_size_hints_t hints;
0102     memset(&hints, 0, sizeof(hints));
0103     xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
0104     xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
0105     xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
0106     xcb_map_window(c.get(), windowId);
0107     xcb_flush(c.get());
0108 
0109     // we should get a window for it
0110     QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
0111     QVERIFY(windowCreatedSpy.wait());
0112     X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
0113     QVERIFY(window);
0114     QCOMPARE(window->window(), windowId);
0115     QVERIFY(window->isDecorated());
0116 
0117     // verify the test machine doesn't have the following activities used
0118     QVERIFY(!Workspace::self()->activities()->all().contains(QStringLiteral("foo")));
0119     QVERIFY(!Workspace::self()->activities()->all().contains(QStringLiteral("bar")));
0120 
0121     window->setOnActivities(QStringList{QStringLiteral("foo"), QStringLiteral("bar")});
0122     QVERIFY(!window->activities().contains(QLatin1String("foo")));
0123     QVERIFY(!window->activities().contains(QLatin1String("bar")));
0124 
0125     // and destroy the window again
0126     xcb_unmap_window(c.get(), windowId);
0127     xcb_destroy_window(c.get(), windowId);
0128     xcb_flush(c.get());
0129     c.reset();
0130 
0131     QSignalSpy windowClosedSpy(window, &X11Window::closed);
0132     QVERIFY(windowClosedSpy.wait());
0133 }
0134 
0135 }
0136 
0137 WAYLANDTEST_MAIN(KWin::ActivitiesTest)
0138 #include "activities_test.moc"