Remove X clipboard sync helper and rename its autotest
Summary: With the gneric X selections infrastructure and clipboard support the X clipboard sync helper utility can be removed. Also rename its autotest as it tests the inner workings of the new mechanism since this mechanism was introduced. Test Plan: Autotest still passes under new name. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: graesslin, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D15063
This commit is contained in:
parent
6e08fb2fa5
commit
2776f829ef
10 changed files with 13 additions and 402 deletions
|
@ -37,7 +37,7 @@ integrationTest(WAYLAND_ONLY NAME testPlasmaSurface SRCS plasma_surface_test.cpp
|
||||||
integrationTest(WAYLAND_ONLY NAME testMaximized SRCS maximize_test.cpp)
|
integrationTest(WAYLAND_ONLY NAME testMaximized SRCS maximize_test.cpp)
|
||||||
integrationTest(WAYLAND_ONLY NAME testShellClient SRCS shell_client_test.cpp)
|
integrationTest(WAYLAND_ONLY NAME testShellClient SRCS shell_client_test.cpp)
|
||||||
integrationTest(WAYLAND_ONLY NAME testDontCrashNoBorder SRCS dont_crash_no_border.cpp)
|
integrationTest(WAYLAND_ONLY NAME testDontCrashNoBorder SRCS dont_crash_no_border.cpp)
|
||||||
integrationTest(NAME testXClipboardSync SRCS xclipboardsync_test.cpp)
|
integrationTest(NAME testXwaylandSelections SRCS xwayland_selections_test.cpp)
|
||||||
integrationTest(WAYLAND_ONLY NAME testSceneOpenGL SRCS scene_opengl_test.cpp generic_scene_opengl_test.cpp)
|
integrationTest(WAYLAND_ONLY NAME testSceneOpenGL SRCS scene_opengl_test.cpp generic_scene_opengl_test.cpp)
|
||||||
integrationTest(WAYLAND_ONLY NAME testSceneOpenGLShadow SRCS scene_opengl_shadow_test.cpp)
|
integrationTest(WAYLAND_ONLY NAME testSceneOpenGLShadow SRCS scene_opengl_shadow_test.cpp)
|
||||||
integrationTest(WAYLAND_ONLY NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp generic_scene_opengl_test.cpp)
|
integrationTest(WAYLAND_ONLY NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp generic_scene_opengl_test.cpp)
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
KWin - the KDE window manager
|
KWin - the KDE window manager
|
||||||
This file is part of the KDE project.
|
This file is part of the KDE project.
|
||||||
|
|
||||||
Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org>
|
Copyright 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
Copyright 2019 Roman Gilg <subdiff@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,9 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using namespace KWin;
|
using namespace KWin;
|
||||||
|
|
||||||
static const QString s_socketName = QStringLiteral("wayland_test_kwin_xclipboard_sync-0");
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_xwayland_selections-0");
|
||||||
|
|
||||||
class XClipboardSyncTest : public QObject
|
class XwaylandSelectionsTest : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
@ -48,7 +49,7 @@ private:
|
||||||
QProcess *m_pasteProcess = nullptr;
|
QProcess *m_pasteProcess = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void XClipboardSyncTest::initTestCase()
|
void XwaylandSelectionsTest::initTestCase()
|
||||||
{
|
{
|
||||||
QSKIP("Skipped as it fails for unknown reasons on build.kde.org");
|
QSKIP("Skipped as it fails for unknown reasons on build.kde.org");
|
||||||
qRegisterMetaType<KWin::ShellClient*>();
|
qRegisterMetaType<KWin::ShellClient*>();
|
||||||
|
@ -58,8 +59,8 @@ void XClipboardSyncTest::initTestCase()
|
||||||
QVERIFY(workspaceCreatedSpy.isValid());
|
QVERIFY(workspaceCreatedSpy.isValid());
|
||||||
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
|
||||||
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
|
QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2));
|
||||||
QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated};
|
// QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated};
|
||||||
QVERIFY(clipboardSyncDevicedCreated.isValid());
|
// QVERIFY(clipboardSyncDevicedCreated.isValid());
|
||||||
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
|
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
|
||||||
|
|
||||||
kwinApp()->start();
|
kwinApp()->start();
|
||||||
|
@ -79,7 +80,7 @@ void XClipboardSyncTest::initTestCase()
|
||||||
QVERIFY(Xwl::DataBridge::self()->dataDeviceIface() != nullptr);
|
QVERIFY(Xwl::DataBridge::self()->dataDeviceIface() != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XClipboardSyncTest::cleanup()
|
void XwaylandSelectionsTest::cleanup()
|
||||||
{
|
{
|
||||||
if (m_copyProcess) {
|
if (m_copyProcess) {
|
||||||
m_copyProcess->terminate();
|
m_copyProcess->terminate();
|
||||||
|
@ -93,7 +94,7 @@ void XClipboardSyncTest::cleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XClipboardSyncTest::testSync_data()
|
void XwaylandSelectionsTest::testSync_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("copyPlatform");
|
QTest::addColumn<QString>("copyPlatform");
|
||||||
QTest::addColumn<QString>("pastePlatform");
|
QTest::addColumn<QString>("pastePlatform");
|
||||||
|
@ -102,7 +103,7 @@ void XClipboardSyncTest::testSync_data()
|
||||||
QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb");
|
QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb");
|
||||||
}
|
}
|
||||||
|
|
||||||
void XClipboardSyncTest::testSync()
|
void XwaylandSelectionsTest::testSync()
|
||||||
{
|
{
|
||||||
// this test verifies the syncing of X11 to Wayland clipboard
|
// this test verifies the syncing of X11 to Wayland clipboard
|
||||||
const QString copy = QFINDTESTDATA(QStringLiteral("copy"));
|
const QString copy = QFINDTESTDATA(QStringLiteral("copy"));
|
||||||
|
@ -192,5 +193,5 @@ void XClipboardSyncTest::testSync()
|
||||||
m_copyProcess = nullptr;
|
m_copyProcess = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
WAYLANDTEST_MAIN(XClipboardSyncTest)
|
WAYLANDTEST_MAIN(XwaylandSelectionsTest)
|
||||||
#include "xclipboardsync_test.moc"
|
#include "xwayland_selections_test.moc"
|
|
@ -1,2 +1 @@
|
||||||
add_subdirectory(killer)
|
add_subdirectory(killer)
|
||||||
add_subdirectory(xclipboardsync)
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
set(xclipboard_SRCS main.cpp waylandclipboard.cpp)
|
|
||||||
add_executable(org_kde_kwin_xclipboard_syncer ${xclipboard_SRCS})
|
|
||||||
target_link_libraries(org_kde_kwin_xclipboard_syncer Qt5::Gui KF5::WaylandClient KF5::Crash)
|
|
||||||
|
|
||||||
install(TARGETS org_kde_kwin_xclipboard_syncer DESTINATION ${LIBEXEC_INSTALL_DIR} )
|
|
|
@ -1,47 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
#include "waylandclipboard.h"
|
|
||||||
|
|
||||||
#include <KCrash>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
|
|
||||||
#include <config-kwin.h>
|
|
||||||
#if HAVE_PR_SET_PDEATHSIG
|
|
||||||
#include <sys/prctl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
#if HAVE_PR_SET_PDEATHSIG
|
|
||||||
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
|
||||||
#endif
|
|
||||||
qputenv("QT_QPA_PLATFORM", "xcb");
|
|
||||||
QGuiApplication app(argc, argv);
|
|
||||||
// perform sanity checks
|
|
||||||
if (app.platformName().toLower() != QStringLiteral("xcb")) {
|
|
||||||
fprintf(stderr, "%s: FATAL ERROR expecting platform xcb but got platform %s\n",
|
|
||||||
argv[0], qPrintable(app.platformName()));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
KCrash::initialize();
|
|
||||||
new WaylandClipboard(&app);
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
#include "waylandclipboard.h"
|
|
||||||
|
|
||||||
#include <KWayland/Client/connection_thread.h>
|
|
||||||
#include <KWayland/Client/datadevicemanager.h>
|
|
||||||
#include <KWayland/Client/datadevice.h>
|
|
||||||
#include <KWayland/Client/datasource.h>
|
|
||||||
#include <KWayland/Client/event_queue.h>
|
|
||||||
#include <KWayland/Client/seat.h>
|
|
||||||
#include <KWayland/Client/registry.h>
|
|
||||||
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QMimeData>
|
|
||||||
#include <QMimeType>
|
|
||||||
#include <qplatformdefs.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
using namespace KWayland::Client;
|
|
||||||
|
|
||||||
WaylandClipboard::WaylandClipboard(QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_thread(new QThread)
|
|
||||||
, m_connectionThread(new ConnectionThread)
|
|
||||||
{
|
|
||||||
m_connectionThread->setSocketFd(qEnvironmentVariableIntValue("WAYLAND_SOCKET"));
|
|
||||||
m_connectionThread->moveToThread(m_thread);
|
|
||||||
m_thread->start();
|
|
||||||
|
|
||||||
connect(m_connectionThread, &ConnectionThread::connected, this, &WaylandClipboard::setup, Qt::QueuedConnection);
|
|
||||||
|
|
||||||
m_connectionThread->initConnection();
|
|
||||||
|
|
||||||
connect(qApp->clipboard(), &QClipboard::changed, this,
|
|
||||||
[this] (QClipboard::Mode mode) {
|
|
||||||
if (mode != QClipboard::Clipboard) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: do we need to take a copy of the clipboard in order to keep it after the X application quit?
|
|
||||||
if (!m_dataDeviceManager || !m_dataDevice) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto source = m_dataDeviceManager->createDataSource(this);
|
|
||||||
auto mimeData = qApp->clipboard()->mimeData();
|
|
||||||
const auto formats = mimeData->formats();
|
|
||||||
for (const auto &format : formats) {
|
|
||||||
source->offer(format);
|
|
||||||
}
|
|
||||||
connect(source, &DataSource::sendDataRequested, this,
|
|
||||||
[] (const QString &type, qint32 fd) {
|
|
||||||
auto mimeData = qApp->clipboard()->mimeData();
|
|
||||||
if (!mimeData->hasFormat(type)) {
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto data = mimeData->data(type);
|
|
||||||
QFile writePipe;
|
|
||||||
if (writePipe.open(fd, QIODevice::WriteOnly, QFile::AutoCloseHandle)) {
|
|
||||||
writePipe.write(data);
|
|
||||||
writePipe.close();
|
|
||||||
} else {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
m_dataDevice->setSelection(0, source);
|
|
||||||
delete m_dataSource;
|
|
||||||
m_dataSource = source;
|
|
||||||
m_connectionThread->flush();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
WaylandClipboard::~WaylandClipboard()
|
|
||||||
{
|
|
||||||
m_connectionThread->deleteLater();
|
|
||||||
m_thread->quit();
|
|
||||||
m_thread->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int readData(int fd, QByteArray &data)
|
|
||||||
{
|
|
||||||
// implementation based on QtWayland file qwaylanddataoffer.cpp
|
|
||||||
char buf[4096];
|
|
||||||
int retryCount = 0;
|
|
||||||
int n;
|
|
||||||
while (true) {
|
|
||||||
n = QT_READ(fd, buf, sizeof buf);
|
|
||||||
if (n == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && ++retryCount < 1000) {
|
|
||||||
usleep(1000);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (n > 0) {
|
|
||||||
data.append(buf, n);
|
|
||||||
n = readData(fd, data);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaylandClipboard::setup()
|
|
||||||
{
|
|
||||||
EventQueue *queue = new EventQueue(this);
|
|
||||||
queue->setup(m_connectionThread);
|
|
||||||
|
|
||||||
Registry *registry = new Registry(this);
|
|
||||||
registry->setEventQueue(queue);
|
|
||||||
registry->create(m_connectionThread);
|
|
||||||
connect(registry, &Registry::interfacesAnnounced, this,
|
|
||||||
[this, registry] {
|
|
||||||
const auto seatInterface = registry->interface(Registry::Interface::Seat);
|
|
||||||
if (seatInterface.name != 0) {
|
|
||||||
m_seat = registry->createSeat(seatInterface.name, seatInterface.version, this);
|
|
||||||
}
|
|
||||||
const auto ddmInterface = registry->interface(Registry::Interface::DataDeviceManager);
|
|
||||||
if (ddmInterface.name != 0) {
|
|
||||||
m_dataDeviceManager = registry->createDataDeviceManager(ddmInterface.name, ddmInterface.version, this);
|
|
||||||
}
|
|
||||||
if (m_seat && m_dataDeviceManager) {
|
|
||||||
m_dataDevice = m_dataDeviceManager->getDataDevice(m_seat, this);
|
|
||||||
connect(m_dataDevice, &DataDevice::selectionOffered, this,
|
|
||||||
[this] (DataOffer *offer) {
|
|
||||||
if (offer->offeredMimeTypes().isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int pipeFds[2];
|
|
||||||
if (pipe(pipeFds) != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto mimeType = offer->offeredMimeTypes().first();
|
|
||||||
offer->receive(mimeType, pipeFds[1]);
|
|
||||||
m_connectionThread->flush();
|
|
||||||
close(pipeFds[1]);
|
|
||||||
QByteArray content;
|
|
||||||
if (readData(pipeFds[0], content) != 0) {
|
|
||||||
content = QByteArray();
|
|
||||||
}
|
|
||||||
close(pipeFds[0]);
|
|
||||||
QMimeData *mimeData = new QMimeData();
|
|
||||||
mimeData->setData(mimeType.name(), content);
|
|
||||||
qApp->clipboard()->setMimeData(mimeData);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
connect(m_dataDevice, &DataDevice::selectionCleared, this,
|
|
||||||
[this] {
|
|
||||||
qApp->clipboard()->clear();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
registry->setup();
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/********************************************************************
|
|
||||||
KWin - the KDE window manager
|
|
||||||
This file is part of the KDE project.
|
|
||||||
|
|
||||||
Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*********************************************************************/
|
|
||||||
#ifndef WAYLANDCLIPBOARD_H
|
|
||||||
#define WAYLANDCLIPBOARD_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class QThread;
|
|
||||||
|
|
||||||
namespace KWayland
|
|
||||||
{
|
|
||||||
namespace Client
|
|
||||||
{
|
|
||||||
class ConnectionThread;
|
|
||||||
class Seat;
|
|
||||||
class DataDeviceManager;
|
|
||||||
class DataDevice;
|
|
||||||
class DataSource;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WaylandClipboard : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit WaylandClipboard(QObject *parent);
|
|
||||||
~WaylandClipboard();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setup();
|
|
||||||
QThread *m_thread;
|
|
||||||
KWayland::Client::ConnectionThread *m_connectionThread;
|
|
||||||
KWayland::Client::Seat *m_seat = nullptr;
|
|
||||||
KWayland::Client::DataDeviceManager *m_dataDeviceManager = nullptr;
|
|
||||||
KWayland::Client::DataDevice *m_dataDevice = nullptr;
|
|
||||||
KWayland::Client::DataSource *m_dataSource = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -184,19 +184,6 @@ void KeyboardInputRedirection::update()
|
||||||
if (found && found->surface()) {
|
if (found && found->surface()) {
|
||||||
if (found->surface() != seat->focusedKeyboardSurface()) {
|
if (found->surface() != seat->focusedKeyboardSurface()) {
|
||||||
seat->setFocusedKeyboardSurface(found->surface());
|
seat->setFocusedKeyboardSurface(found->surface());
|
||||||
auto newKeyboard = seat->focusedKeyboard();
|
|
||||||
if (newKeyboard && newKeyboard->client() == waylandServer()->xWaylandConnection()) {
|
|
||||||
// focus passed to an XWayland surface
|
|
||||||
const auto selection = seat->selection();
|
|
||||||
auto xclipboard = waylandServer()->xclipboardSyncDataDevice();
|
|
||||||
if (xclipboard && selection != xclipboard.data()) {
|
|
||||||
if (selection) {
|
|
||||||
xclipboard->sendSelection(selection);
|
|
||||||
} else {
|
|
||||||
xclipboard->sendClearSelection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
seat->setFocusedKeyboardSurface(nullptr);
|
seat->setFocusedKeyboardSurface(nullptr);
|
||||||
|
|
|
@ -92,7 +92,6 @@ WaylandServer::WaylandServer(QObject *parent)
|
||||||
qRegisterMetaType<KWayland::Server::OutputInterface::DpmsMode>();
|
qRegisterMetaType<KWayland::Server::OutputInterface::DpmsMode>();
|
||||||
|
|
||||||
connect(kwinApp(), &Application::screensCreated, this, &WaylandServer::initOutputs);
|
connect(kwinApp(), &Application::screensCreated, this, &WaylandServer::initOutputs);
|
||||||
// connect(kwinApp(), &Application::x11ConnectionChanged, this, &WaylandServer::setupX11ClipboardSync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaylandServer::~WaylandServer()
|
WaylandServer::~WaylandServer()
|
||||||
|
@ -260,24 +259,6 @@ bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
|
||||||
m_display->createPointerConstraints(PointerConstraintsInterfaceVersion::UnstableV1, m_display)->create();
|
m_display->createPointerConstraints(PointerConstraintsInterfaceVersion::UnstableV1, m_display)->create();
|
||||||
m_dataDeviceManager = m_display->createDataDeviceManager(m_display);
|
m_dataDeviceManager = m_display->createDataDeviceManager(m_display);
|
||||||
m_dataDeviceManager->create();
|
m_dataDeviceManager->create();
|
||||||
connect(m_dataDeviceManager, &DataDeviceManagerInterface::dataDeviceCreated, this,
|
|
||||||
[this] (DataDeviceInterface *ddi) {
|
|
||||||
if (ddi->client() == m_xclipbaordSync.client && m_xclipbaordSync.client != nullptr) {
|
|
||||||
m_xclipbaordSync.ddi = QPointer<DataDeviceInterface>(ddi);
|
|
||||||
emit xclipboardSyncDataDeviceCreated();
|
|
||||||
connect(m_xclipbaordSync.ddi.data(), &DataDeviceInterface::selectionChanged, this,
|
|
||||||
[this] {
|
|
||||||
// testing whether the active client inherits Client
|
|
||||||
// it would be better to test for the keyboard focus, but we might get a clipboard update
|
|
||||||
// when the Client is already active, but no Surface is created yet.
|
|
||||||
if (workspace()->activeClient() && workspace()->activeClient()->inherits("KWin::Client")) {
|
|
||||||
m_seat->setSelection(m_xclipbaordSync.ddi.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
m_idle = m_display->createIdle(m_display);
|
m_idle = m_display->createIdle(m_display);
|
||||||
m_idle->create();
|
m_idle->create();
|
||||||
auto idleInhibition = new IdleInhibition(m_idle);
|
auto idleInhibition = new IdleInhibition(m_idle);
|
||||||
|
@ -531,10 +512,6 @@ void WaylandServer::destroyXWaylandConnection()
|
||||||
if (!m_xwayland.client) {
|
if (!m_xwayland.client) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// first terminate the clipboard sync
|
|
||||||
if (m_xclipbaordSync.process) {
|
|
||||||
m_xclipbaordSync.process->terminate();
|
|
||||||
}
|
|
||||||
disconnect(m_xwayland.destroyConnection);
|
disconnect(m_xwayland.destroyConnection);
|
||||||
m_xwayland.client->destroy();
|
m_xwayland.client->destroy();
|
||||||
m_xwayland.client = nullptr;
|
m_xwayland.client = nullptr;
|
||||||
|
@ -559,62 +536,6 @@ void WaylandServer::destroyInputMethodConnection()
|
||||||
m_inputMethodServerConnection = nullptr;
|
m_inputMethodServerConnection = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WaylandServer::createXclipboardSyncConnection()
|
|
||||||
{
|
|
||||||
const auto socket = createConnection();
|
|
||||||
if (!socket.connection) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
m_xclipbaordSync.client = socket.connection;
|
|
||||||
return socket.fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaylandServer::setupX11ClipboardSync()
|
|
||||||
{
|
|
||||||
if (m_xclipbaordSync.process) {
|
|
||||||
qCWarning(KWIN_CORE) << "Tried to start x clipboard syncer although process already started";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int socket = dup(createXclipboardSyncConnection());
|
|
||||||
if (socket == -1) {
|
|
||||||
delete m_xclipbaordSync.client;
|
|
||||||
m_xclipbaordSync.client = nullptr;
|
|
||||||
qCWarning(KWIN_CORE) << "Could not create wayland socket for x clipboard syncer";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (socket >= 0) {
|
|
||||||
QProcessEnvironment environment = kwinApp()->processStartupEnvironment();
|
|
||||||
environment.insert(QStringLiteral("WAYLAND_SOCKET"), QByteArray::number(socket));
|
|
||||||
environment.insert(QStringLiteral("DISPLAY"), QString::fromUtf8(qgetenv("DISPLAY")));
|
|
||||||
environment.remove("WAYLAND_DISPLAY");
|
|
||||||
m_xclipbaordSync.process = new Process(this);
|
|
||||||
m_xclipbaordSync.process->setProcessChannelMode(QProcess::ForwardedChannels);
|
|
||||||
auto finishedSignal = static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished);
|
|
||||||
connect(m_xclipbaordSync.process, finishedSignal, this,
|
|
||||||
[this] {
|
|
||||||
qCDebug(KWIN_CORE) << "X clipboard syncer process finished";
|
|
||||||
m_xclipbaordSync.process->deleteLater();
|
|
||||||
m_xclipbaordSync.process = nullptr;
|
|
||||||
m_xclipbaordSync.ddi.clear();
|
|
||||||
m_xclipbaordSync.client->destroy();
|
|
||||||
m_xclipbaordSync.client = nullptr;
|
|
||||||
// TODO: restart
|
|
||||||
}
|
|
||||||
);
|
|
||||||
m_xclipbaordSync.process->setProcessEnvironment(environment);
|
|
||||||
// start from build directory if executable is available there (e.g. autotests), otherwise start libexec executable
|
|
||||||
const QFileInfo clipboardSync{QDir{QCoreApplication::applicationDirPath()}, QStringLiteral("org_kde_kwin_xclipboard_syncer")};
|
|
||||||
if (clipboardSync.exists()) {
|
|
||||||
qCDebug(KWIN_CORE) << "Starting" << clipboardSync.absoluteFilePath();
|
|
||||||
m_xclipbaordSync.process->start(clipboardSync.absoluteFilePath());
|
|
||||||
} else {
|
|
||||||
qCDebug(KWIN_CORE) << "Starting" << KWIN_XCLIPBOARD_SYNC_BIN;
|
|
||||||
m_xclipbaordSync.process->start(QStringLiteral(KWIN_XCLIPBOARD_SYNC_BIN));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaylandServer::createInternalConnection()
|
void WaylandServer::createInternalConnection()
|
||||||
{
|
{
|
||||||
const auto socket = createConnection();
|
const auto socket = createConnection();
|
||||||
|
|
|
@ -23,7 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <kwinglobals.h>
|
#include <kwinglobals.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
class QThread;
|
class QThread;
|
||||||
class QProcess;
|
class QProcess;
|
||||||
|
@ -150,8 +149,6 @@ public:
|
||||||
int createInputMethodConnection();
|
int createInputMethodConnection();
|
||||||
void destroyInputMethodConnection();
|
void destroyInputMethodConnection();
|
||||||
|
|
||||||
int createXclipboardSyncConnection();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns true if screen is locked.
|
* @returns true if screen is locked.
|
||||||
**/
|
**/
|
||||||
|
@ -181,9 +178,6 @@ public:
|
||||||
KWayland::Server::ClientConnection *screenLockerClientConnection() const {
|
KWayland::Server::ClientConnection *screenLockerClientConnection() const {
|
||||||
return m_screenLockerClientConnection;
|
return m_screenLockerClientConnection;
|
||||||
}
|
}
|
||||||
QPointer<KWayland::Server::DataDeviceInterface> xclipboardSyncDataDevice() const {
|
|
||||||
return m_xclipbaordSync.ddi;
|
|
||||||
}
|
|
||||||
KWayland::Client::Seat *internalSeat() {
|
KWayland::Client::Seat *internalSeat() {
|
||||||
return m_internalConnection.seat;
|
return m_internalConnection.seat;
|
||||||
}
|
}
|
||||||
|
@ -229,10 +223,8 @@ Q_SIGNALS:
|
||||||
void terminatingInternalClientConnection();
|
void terminatingInternalClientConnection();
|
||||||
void initialized();
|
void initialized();
|
||||||
void foreignTransientChanged(KWayland::Server::SurfaceInterface *child);
|
void foreignTransientChanged(KWayland::Server::SurfaceInterface *child);
|
||||||
void xclipboardSyncDataDeviceCreated();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupX11ClipboardSync();
|
|
||||||
void shellClientShown(Toplevel *t);
|
void shellClientShown(Toplevel *t);
|
||||||
void initOutputs();
|
void initOutputs();
|
||||||
void syncOutputsToWayland();
|
void syncOutputsToWayland();
|
||||||
|
@ -277,11 +269,6 @@ private:
|
||||||
bool interfacesAnnounced = false;
|
bool interfacesAnnounced = false;
|
||||||
|
|
||||||
} m_internalConnection;
|
} m_internalConnection;
|
||||||
struct {
|
|
||||||
QProcess *process = nullptr;
|
|
||||||
KWayland::Server::ClientConnection *client = nullptr;
|
|
||||||
QPointer<KWayland::Server::DataDeviceInterface> ddi;
|
|
||||||
} m_xclipbaordSync;
|
|
||||||
KWayland::Server::XdgForeignInterface *m_XdgForeign = nullptr;
|
KWayland::Server::XdgForeignInterface *m_XdgForeign = nullptr;
|
||||||
QList<ShellClient*> m_clients;
|
QList<ShellClient*> m_clients;
|
||||||
QList<ShellClient*> m_internalClients;
|
QList<ShellClient*> m_internalClients;
|
||||||
|
|
Loading…
Reference in a new issue