File indexing completed on 2024-11-10 04:56:12
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 "wayland/seat.h" 0014 #include "wayland_server.h" 0015 #include "window.h" 0016 #include "workspace.h" 0017 #include "xwayland/databridge.h" 0018 0019 #include <QProcess> 0020 #include <QProcessEnvironment> 0021 #include <QSignalSpy> 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 Test::setOutputConfig({ 0057 QRect(0, 0, 1280, 1024), 0058 QRect(1280, 0, 1280, 1024), 0059 }); 0060 0061 kwinApp()->start(); 0062 QVERIFY(applicationStartedSpy.wait()); 0063 const auto outputs = workspace()->outputs(); 0064 QCOMPARE(outputs.count(), 2); 0065 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0066 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0067 // // wait till the xclipboard sync data device is created 0068 // if (clipboardSyncDevicedCreated.empty()) { 0069 // QVERIFY(clipboardSyncDevicedCreated.wait()); 0070 // } 0071 } 0072 0073 void XwaylandSelectionsTest::testSync_data() 0074 { 0075 QTest::addColumn<QString>("copyPlatform"); 0076 QTest::addColumn<QString>("pastePlatform"); 0077 0078 QTest::newRow("x11->wayland") << QStringLiteral("xcb") << QStringLiteral("wayland"); 0079 QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb"); 0080 } 0081 0082 void XwaylandSelectionsTest::testSync() 0083 { 0084 // this test verifies the syncing of X11 to Wayland clipboard 0085 const QString copy = QFINDTESTDATA(QStringLiteral("copy")); 0086 QVERIFY(!copy.isEmpty()); 0087 const QString paste = QFINDTESTDATA(QStringLiteral("paste")); 0088 QVERIFY(!paste.isEmpty()); 0089 0090 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); 0091 QSignalSpy clipboardChangedSpy(waylandServer()->seat(), &SeatInterface::selectionChanged); 0092 0093 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); 0094 0095 // start the copy process 0096 QFETCH(QString, copyPlatform); 0097 environment.insert(QStringLiteral("QT_QPA_PLATFORM"), copyPlatform); 0098 environment.insert(QStringLiteral("WAYLAND_DISPLAY"), s_socketName); 0099 std::unique_ptr<QProcess, ProcessKillBeforeDeleter> copyProcess(new QProcess()); 0100 copyProcess->setProcessEnvironment(environment); 0101 copyProcess->setProcessChannelMode(QProcess::ForwardedChannels); 0102 copyProcess->setProgram(copy); 0103 copyProcess->start(); 0104 QVERIFY(copyProcess->waitForStarted()); 0105 0106 Window *copyWindow = nullptr; 0107 QVERIFY(windowAddedSpy.wait()); 0108 copyWindow = windowAddedSpy.first().first().value<Window *>(); 0109 QVERIFY(copyWindow); 0110 if (workspace()->activeWindow() != copyWindow) { 0111 workspace()->activateWindow(copyWindow); 0112 } 0113 QCOMPARE(workspace()->activeWindow(), copyWindow); 0114 clipboardChangedSpy.wait(); 0115 0116 // start the paste process 0117 std::unique_ptr<QProcess, ProcessKillBeforeDeleter> pasteProcess(new QProcess()); 0118 QSignalSpy finishedSpy(pasteProcess.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished)); 0119 QFETCH(QString, pastePlatform); 0120 environment.insert(QStringLiteral("QT_QPA_PLATFORM"), pastePlatform); 0121 pasteProcess->setProcessEnvironment(environment); 0122 pasteProcess->setProcessChannelMode(QProcess::ForwardedChannels); 0123 pasteProcess->setProgram(paste); 0124 pasteProcess->start(); 0125 QVERIFY(pasteProcess->waitForStarted()); 0126 0127 windowAddedSpy.clear(); 0128 Window *pasteWindow = nullptr; 0129 QVERIFY(windowAddedSpy.wait()); 0130 pasteWindow = windowAddedSpy.last().first().value<Window *>(); 0131 QCOMPARE(windowAddedSpy.count(), 1); 0132 QVERIFY(pasteWindow); 0133 0134 if (workspace()->activeWindow() != pasteWindow) { 0135 QSignalSpy windowActivatedSpy(workspace(), &Workspace::windowActivated); 0136 workspace()->activateWindow(pasteWindow); 0137 QVERIFY(windowActivatedSpy.wait()); 0138 } 0139 QTRY_COMPARE(workspace()->activeWindow(), pasteWindow); 0140 QVERIFY(finishedSpy.wait()); 0141 QCOMPARE(finishedSpy.first().first().toInt(), 0); 0142 } 0143 0144 WAYLANDTEST_MAIN(XwaylandSelectionsTest) 0145 #include "xwayland_selections_test.moc"