diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -37,7 +37,7 @@ integrationTest(WAYLAND_ONLY NAME testMaximized SRCS maximize_test.cpp) integrationTest(WAYLAND_ONLY NAME testShellClient SRCS shell_client_test.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 testSceneOpenGLShadow SRCS scene_opengl_shadow_test.cpp) integrationTest(WAYLAND_ONLY NAME testSceneOpenGLES SRCS scene_opengl_es_test.cpp generic_scene_opengl_test.cpp) diff --git a/autotests/integration/xclipboardsync_test.cpp b/autotests/integration/xwayland_selections_test.cpp rename from autotests/integration/xclipboardsync_test.cpp rename to autotests/integration/xwayland_selections_test.cpp --- a/autotests/integration/xclipboardsync_test.cpp +++ b/autotests/integration/xwayland_selections_test.cpp @@ -2,7 +2,8 @@ KWin - the KDE window manager This file is part of the KDE project. -Copyright (C) 2016 Martin Gräßlin +Copyright 2016 Martin Gräßlin +Copyright 2019 Roman Gilg 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 @@ -32,9 +33,9 @@ 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 private Q_SLOTS: @@ -48,7 +49,7 @@ QProcess *m_pasteProcess = nullptr; }; -void XClipboardSyncTest::initTestCase() +void XwaylandSelectionsTest::initTestCase() { QSKIP("Skipped as it fails for unknown reasons on build.kde.org"); qRegisterMetaType(); @@ -58,8 +59,8 @@ QVERIFY(workspaceCreatedSpy.isValid()); kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); - QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated}; - QVERIFY(clipboardSyncDevicedCreated.isValid()); +// QSignalSpy clipboardSyncDevicedCreated{waylandServer(), &WaylandServer::xclipboardSyncDataDeviceCreated}; +// QVERIFY(clipboardSyncDevicedCreated.isValid()); QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit())); kwinApp()->start(); @@ -79,7 +80,7 @@ QVERIFY(Xwl::DataBridge::self()->dataDeviceIface() != nullptr); } -void XClipboardSyncTest::cleanup() +void XwaylandSelectionsTest::cleanup() { if (m_copyProcess) { m_copyProcess->terminate(); @@ -93,16 +94,16 @@ } } -void XClipboardSyncTest::testSync_data() +void XwaylandSelectionsTest::testSync_data() { QTest::addColumn("copyPlatform"); QTest::addColumn("pastePlatform"); QTest::newRow("x11->wayland") << QStringLiteral("xcb") << QStringLiteral("wayland"); QTest::newRow("wayland->x11") << QStringLiteral("wayland") << QStringLiteral("xcb"); } -void XClipboardSyncTest::testSync() +void XwaylandSelectionsTest::testSync() { // this test verifies the syncing of X11 to Wayland clipboard const QString copy = QFINDTESTDATA(QStringLiteral("copy")); @@ -192,5 +193,5 @@ m_copyProcess = nullptr; } -WAYLANDTEST_MAIN(XClipboardSyncTest) -#include "xclipboardsync_test.moc" +WAYLANDTEST_MAIN(XwaylandSelectionsTest) +#include "xwayland_selections_test.moc" diff --git a/helpers/CMakeLists.txt b/helpers/CMakeLists.txt --- a/helpers/CMakeLists.txt +++ b/helpers/CMakeLists.txt @@ -1,2 +1 @@ add_subdirectory(killer) -add_subdirectory(xclipboardsync) diff --git a/helpers/xclipboardsync/CMakeLists.txt b/helpers/xclipboardsync/CMakeLists.txt deleted file mode 100644 --- a/helpers/xclipboardsync/CMakeLists.txt +++ /dev/null @@ -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} ) diff --git a/helpers/xclipboardsync/main.cpp b/helpers/xclipboardsync/main.cpp deleted file mode 100644 --- a/helpers/xclipboardsync/main.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2016 Martin Gräßlin - -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 . -*********************************************************************/ -#include "waylandclipboard.h" - -#include -#include - -#include -#if HAVE_PR_SET_PDEATHSIG -#include -#include -#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(); -} diff --git a/helpers/xclipboardsync/waylandclipboard.h b/helpers/xclipboardsync/waylandclipboard.h deleted file mode 100644 --- a/helpers/xclipboardsync/waylandclipboard.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2016 Martin Gräßlin - -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 . -*********************************************************************/ -#ifndef WAYLANDCLIPBOARD_H -#define WAYLANDCLIPBOARD_H - -#include - -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 diff --git a/helpers/xclipboardsync/waylandclipboard.cpp b/helpers/xclipboardsync/waylandclipboard.cpp deleted file mode 100644 --- a/helpers/xclipboardsync/waylandclipboard.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2016 Martin Gräßlin - -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 . -*********************************************************************/ -#include "waylandclipboard.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -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(); -} diff --git a/keyboard_input.cpp b/keyboard_input.cpp --- a/keyboard_input.cpp +++ b/keyboard_input.cpp @@ -184,19 +184,6 @@ if (found && found->surface()) { if (found->surface() != seat->focusedKeyboardSurface()) { 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 { seat->setFocusedKeyboardSurface(nullptr); diff --git a/wayland_server.h b/wayland_server.h --- a/wayland_server.h +++ b/wayland_server.h @@ -23,7 +23,6 @@ #include #include -#include class QThread; class QProcess; @@ -150,8 +149,6 @@ int createInputMethodConnection(); void destroyInputMethodConnection(); - int createXclipboardSyncConnection(); - /** * @returns true if screen is locked. **/ @@ -181,9 +178,6 @@ KWayland::Server::ClientConnection *screenLockerClientConnection() const { return m_screenLockerClientConnection; } - QPointer xclipboardSyncDataDevice() const { - return m_xclipbaordSync.ddi; - } KWayland::Client::Seat *internalSeat() { return m_internalConnection.seat; } @@ -229,10 +223,8 @@ void terminatingInternalClientConnection(); void initialized(); void foreignTransientChanged(KWayland::Server::SurfaceInterface *child); - void xclipboardSyncDataDeviceCreated(); private: - void setupX11ClipboardSync(); void shellClientShown(Toplevel *t); void initOutputs(); void syncOutputsToWayland(); @@ -277,11 +269,6 @@ bool interfacesAnnounced = false; } m_internalConnection; - struct { - QProcess *process = nullptr; - KWayland::Server::ClientConnection *client = nullptr; - QPointer ddi; - } m_xclipbaordSync; KWayland::Server::XdgForeignInterface *m_XdgForeign = nullptr; QList m_clients; QList m_internalClients; diff --git a/wayland_server.cpp b/wayland_server.cpp --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -92,7 +92,6 @@ qRegisterMetaType(); connect(kwinApp(), &Application::screensCreated, this, &WaylandServer::initOutputs); -// connect(kwinApp(), &Application::x11ConnectionChanged, this, &WaylandServer::setupX11ClipboardSync); } WaylandServer::~WaylandServer() @@ -260,24 +259,6 @@ m_display->createPointerConstraints(PointerConstraintsInterfaceVersion::UnstableV1, m_display)->create(); m_dataDeviceManager = m_display->createDataDeviceManager(m_display); 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(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->create(); auto idleInhibition = new IdleInhibition(m_idle); @@ -531,10 +512,6 @@ if (!m_xwayland.client) { return; } - // first terminate the clipboard sync - if (m_xclipbaordSync.process) { - m_xclipbaordSync.process->terminate(); - } disconnect(m_xwayland.destroyConnection); m_xwayland.client->destroy(); m_xwayland.client = nullptr; @@ -559,62 +536,6 @@ 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(&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() { const auto socket = createConnection();