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