KWin
Loading...
Searching...
No Matches
xwayland_selections_test.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10#include "kwin_wayland_test.h"
11
12#include "core/output.h"
13#include "wayland/seat.h"
14#include "wayland_server.h"
15#include "window.h"
16#include "workspace.h"
17#include "xwayland/databridge.h"
18
19#include <QProcess>
20#include <QProcessEnvironment>
21#include <QSignalSpy>
22
23using namespace KWin;
24
25static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_selections-0");
26
28{
29 void operator()(QProcess *pointer)
30 {
31 if (pointer) {
32 pointer->kill();
33 }
34 delete pointer;
35 }
36};
37
38class XwaylandSelectionsTest : public QObject
39{
40 Q_OBJECT
41private Q_SLOTS:
42 void initTestCase();
43 void testSync_data();
44 void testSync();
45};
46
47void XwaylandSelectionsTest::initTestCase()
48{
49 // QSKIP("Skipped as it fails for unknown reasons on build.kde.org");
50 qRegisterMetaType<KWin::Window *>();
51 qRegisterMetaType<QProcess::ExitStatus>();
52 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
53 // QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated};
54 // QVERIFY(clipboardSyncDevicedCreated.isValid());
55 QVERIFY(waylandServer()->init(s_socketName));
57 QRect(0, 0, 1280, 1024),
58 QRect(1280, 0, 1280, 1024),
59 });
60
61 kwinApp()->start();
62 QVERIFY(applicationStartedSpy.wait());
63 const auto outputs = workspace()->outputs();
64 QCOMPARE(outputs.count(), 2);
65 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
66 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
67 // // wait till the xclipboard sync data device is created
68 // if (clipboardSyncDevicedCreated.empty()) {
69 // QVERIFY(clipboardSyncDevicedCreated.wait());
70 // }
71}
72
73void XwaylandSelectionsTest::testSync_data()
74{
75 QTest::addColumn<QString>("copyPlatform");
76 QTest::addColumn<QString>("pastePlatform");
77
78 QTest::newRow("x11->wayland") << QStringLiteral("xcb") << QStringLiteral("wayland");
79 QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb");
80}
81
82void XwaylandSelectionsTest::testSync()
83{
84 // this test verifies the syncing of X11 to Wayland clipboard
85 const QString copy = QFINDTESTDATA(QStringLiteral("copy"));
86 QVERIFY(!copy.isEmpty());
87 const QString paste = QFINDTESTDATA(QStringLiteral("paste"));
88 QVERIFY(!paste.isEmpty());
89
90 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
91 QSignalSpy clipboardChangedSpy(waylandServer()->seat(), &SeatInterface::selectionChanged);
92
93 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
94
95 // start the copy process
96 QFETCH(QString, copyPlatform);
97 environment.insert(QStringLiteral("QT_QPA_PLATFORM"), copyPlatform);
98 environment.insert(QStringLiteral("WAYLAND_DISPLAY"), s_socketName);
99 std::unique_ptr<QProcess, ProcessKillBeforeDeleter> copyProcess(new QProcess());
100 copyProcess->setProcessEnvironment(environment);
101 copyProcess->setProcessChannelMode(QProcess::ForwardedChannels);
102 copyProcess->setProgram(copy);
103 copyProcess->start();
104 QVERIFY(copyProcess->waitForStarted());
105
106 Window *copyWindow = nullptr;
107 QVERIFY(windowAddedSpy.wait());
108 copyWindow = windowAddedSpy.first().first().value<Window *>();
109 QVERIFY(copyWindow);
110 if (workspace()->activeWindow() != copyWindow) {
111 workspace()->activateWindow(copyWindow);
112 }
113 QCOMPARE(workspace()->activeWindow(), copyWindow);
114 clipboardChangedSpy.wait();
115
116 // start the paste process
117 std::unique_ptr<QProcess, ProcessKillBeforeDeleter> pasteProcess(new QProcess());
118 QSignalSpy finishedSpy(pasteProcess.get(), static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished));
119 QFETCH(QString, pastePlatform);
120 environment.insert(QStringLiteral("QT_QPA_PLATFORM"), pastePlatform);
121 pasteProcess->setProcessEnvironment(environment);
122 pasteProcess->setProcessChannelMode(QProcess::ForwardedChannels);
123 pasteProcess->setProgram(paste);
124 pasteProcess->start();
125 QVERIFY(pasteProcess->waitForStarted());
126
127 windowAddedSpy.clear();
128 Window *pasteWindow = nullptr;
129 QVERIFY(windowAddedSpy.wait());
130 pasteWindow = windowAddedSpy.last().first().value<Window *>();
131 QCOMPARE(windowAddedSpy.count(), 1);
132 QVERIFY(pasteWindow);
133
134 if (workspace()->activeWindow() != pasteWindow) {
135 QSignalSpy windowActivatedSpy(workspace(), &Workspace::windowActivated);
136 workspace()->activateWindow(pasteWindow);
137 QVERIFY(windowActivatedSpy.wait());
138 }
139 QTRY_COMPARE(workspace()->activeWindow(), pasteWindow);
140 QVERIFY(finishedSpy.wait());
141 QCOMPARE(finishedSpy.first().first().toInt(), 0);
142}
143
145#include "xwayland_selections_test.moc"
void selectionChanged(KWin::AbstractDataSource *)
void activateWindow(Window *window, bool force=false)
void windowActivated(KWin::Window *)
void windowAdded(KWin::Window *)
QList< Output * > outputs() const
Definition workspace.h:762
#define WAYLANDTEST_MAIN(TestObject)
void setOutputConfig(const QList< QRect > &geometries)
KWayland::Client::Seat * seat
QList< KWayland::Client::Output * > outputs
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
void operator()(QProcess *pointer)