Warning, file /plasma/kwin/autotests/integration/xwayland_selections_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     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 #include "kwin_wayland_test.h"
0011 
0012 #include "core/output.h"
0013 #include "core/outputbackend.h"
0014 #include "wayland/seat_interface.h"
0015 #include "wayland_server.h"
0016 #include "window.h"
0017 #include "workspace.h"
0018 #include "xwayland/databridge.h"
0019 
0020 #include <QProcess>
0021 #include <QProcessEnvironment>
0022 
0023 using namespace KWin;
0024 
0025 static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_selections-0");
0026 
0027 struct ProcessKillBeforeDeleter
0028 {
0029     void operator()(QProcess *pointer)
0030     {
0031         if (pointer) {
0032             pointer->kill();
0033         }
0034         delete pointer;
0035     }
0036 };
0037 
0038 class XwaylandSelectionsTest : public QObject
0039 {
0040     Q_OBJECT
0041 private Q_SLOTS:
0042     void initTestCase();
0043     void testSync_data();
0044     void testSync();
0045 };
0046 
0047 void XwaylandSelectionsTest::initTestCase()
0048 {
0049     //    QSKIP("Skipped as it fails for unknown reasons on build.kde.org");
0050     qRegisterMetaType<KWin::Window *>();
0051     qRegisterMetaType<QProcess::ExitStatus>();
0052     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0053     //    QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated};
0054     //    QVERIFY(clipboardSyncDevicedCreated.isValid());
0055     QVERIFY(waylandServer()->init(s_socketName));
0056     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0057 
0058     kwinApp()->start();
0059     QVERIFY(applicationStartedSpy.wait());
0060     const auto outputs = workspace()->outputs();
0061     QCOMPARE(outputs.count(), 2);
0062     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0063     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0064     //    // wait till the xclipboard sync data device is created
0065     //    if (clipboardSyncDevicedCreated.empty()) {
0066     //        QVERIFY(clipboardSyncDevicedCreated.wait());
0067     //    }
0068 }
0069 
0070 void XwaylandSelectionsTest::testSync_data()
0071 {
0072     QTest::addColumn<QString>("copyPlatform");
0073     QTest::addColumn<QString>("pastePlatform");
0074 
0075     QTest::newRow("x11->wayland") << QStringLiteral("xcb") << QStringLiteral("wayland");
0076     QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb");
0077 }
0078 
0079 void XwaylandSelectionsTest::testSync()
0080 {
0081     // this test verifies the syncing of X11 to Wayland clipboard
0082     const QString copy = QFINDTESTDATA(QStringLiteral("copy"));
0083     QVERIFY(!copy.isEmpty());
0084     const QString paste = QFINDTESTDATA(QStringLiteral("paste"));
0085     QVERIFY(!paste.isEmpty());
0086 
0087     QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
0088     QSignalSpy clipboardChangedSpy(waylandServer()->seat(), &KWaylandServer::SeatInterface::selectionChanged);
0089 
0090     QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
0091 
0092     // start the copy process
0093     QFETCH(QString, copyPlatform);
0094     environment.insert(QStringLiteral("QT_QPA_PLATFORM"), copyPlatform);
0095     environment.insert(QStringLiteral("WAYLAND_DISPLAY"), s_socketName);
0096     std::unique_ptr<QProcess, ProcessKillBeforeDeleter> copyProcess(new QProcess());
0097     copyProcess->setProcessEnvironment(environment);
0098     copyProcess->setProcessChannelMode(QProcess::ForwardedChannels);
0099     copyProcess->setProgram(copy);
0100     copyProcess->start();
0101     QVERIFY(copyProcess->waitForStarted());
0102 
0103     Window *copyWindow = nullptr;
0104     QVERIFY(windowAddedSpy.wait());
0105     copyWindow = windowAddedSpy.first().first().value<Window *>();
0106     QVERIFY(copyWindow);
0107     if (workspace()->activeWindow() != copyWindow) {
0108         workspace()->activateWindow(copyWindow);
0109     }
0110     QCOMPARE(workspace()->activeWindow(), copyWindow);
0111     clipboardChangedSpy.wait();
0112 
0113     // start the paste process
0114     std::unique_ptr<QProcess, ProcessKillBeforeDeleter> pasteProcess(new QProcess());
0115     QSignalSpy finishedSpy(pasteProcess.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished));
0116     QFETCH(QString, pastePlatform);
0117     environment.insert(QStringLiteral("QT_QPA_PLATFORM"), pastePlatform);
0118     pasteProcess->setProcessEnvironment(environment);
0119     pasteProcess->setProcessChannelMode(QProcess::ForwardedChannels);
0120     pasteProcess->setProgram(paste);
0121     pasteProcess->start();
0122     QVERIFY(pasteProcess->waitForStarted());
0123 
0124     windowAddedSpy.clear();
0125     Window *pasteWindow = nullptr;
0126     QVERIFY(windowAddedSpy.wait());
0127     pasteWindow = windowAddedSpy.last().first().value<Window *>();
0128     QCOMPARE(windowAddedSpy.count(), 1);
0129     QVERIFY(pasteWindow);
0130 
0131     if (workspace()->activeWindow() != pasteWindow) {
0132         QSignalSpy windowActivatedSpy(workspace(), &Workspace::windowActivated);
0133         workspace()->activateWindow(pasteWindow);
0134         QVERIFY(windowActivatedSpy.wait());
0135     }
0136     QTRY_COMPARE(workspace()->activeWindow(), pasteWindow);
0137     QVERIFY(finishedSpy.wait());
0138     QCOMPARE(finishedSpy.first().first().toInt(), 0);
0139 }
0140 
0141 WAYLANDTEST_MAIN(XwaylandSelectionsTest)
0142 #include "xwayland_selections_test.moc"