xwl: Use direct way of syncing clipboard
Like the primary selection, sync the clipboard directly without doing any roudntrips through the internal connection.
This commit is contained in:
parent
66d74f4398
commit
bc17d0aebd
7 changed files with 84 additions and 61 deletions
|
@ -3,6 +3,7 @@ add_subdirectory(lib)
|
|||
add_library(KWinXwaylandServerModule OBJECT
|
||||
clipboard.cpp
|
||||
databridge.cpp
|
||||
datasource.cpp
|
||||
dnd.cpp
|
||||
drag.cpp
|
||||
drag_wl.cpp
|
||||
|
|
|
@ -8,21 +8,13 @@
|
|||
*/
|
||||
#include "clipboard.h"
|
||||
|
||||
#include "databridge.h"
|
||||
#include "datasource.h"
|
||||
#include "selection_source.h"
|
||||
#include "transfer.h"
|
||||
#include "xwayland.h"
|
||||
|
||||
#include "x11client.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/datadevice.h>
|
||||
#include <KWayland/Client/datasource.h>
|
||||
|
||||
#include <KWaylandServer/datadevice_interface.h>
|
||||
#include <KWaylandServer/datasource_interface.h>
|
||||
#include <KWaylandServer/seat_interface.h>
|
||||
|
||||
#include <xcb/xcb_event.h>
|
||||
|
@ -58,10 +50,6 @@ Clipboard::Clipboard(xcb_atom_t atom, QObject *parent)
|
|||
|
||||
connect(waylandServer()->seat(), &KWaylandServer::SeatInterface::selectionChanged,
|
||||
this, &Clipboard::wlSelectionChanged);
|
||||
|
||||
connect(DataBridge::self()->dataDeviceIface(), &KWaylandServer::DataDeviceInterface::selectionChanged, this, [](KWaylandServer::DataSourceInterface *selection) {
|
||||
waylandServer()->seat()->setSelection(selection);
|
||||
});
|
||||
}
|
||||
|
||||
void Clipboard::wlSelectionChanged(KWaylandServer::AbstractDataSource *dsi)
|
||||
|
@ -84,7 +72,7 @@ void Clipboard::wlSelectionChanged(KWaylandServer::AbstractDataSource *dsi)
|
|||
|
||||
bool Clipboard::ownsSelection(KWaylandServer::AbstractDataSource *dsi) const
|
||||
{
|
||||
return dsi && dsi->client() == DataBridge::self()->dataDeviceIface()->client();
|
||||
return dsi && dsi == m_selectionSource.get();
|
||||
}
|
||||
|
||||
void Clipboard::checkWlSource()
|
||||
|
@ -110,7 +98,7 @@ void Clipboard::checkWlSource()
|
|||
// Otherwise the Wayland source gets destroyed to shield
|
||||
// against snooping X clients.
|
||||
|
||||
if (!dsi || (DataBridge::self()->dataDeviceIface()->client() == dsi->client())) {
|
||||
if (!dsi || ownsSelection(dsi)) {
|
||||
// Xwayland source or no source
|
||||
disconnect(m_checkConnection);
|
||||
m_checkConnection = QMetaObject::Connection();
|
||||
|
@ -169,25 +157,24 @@ void Clipboard::x11OffersChanged(const QStringList &added, const QStringList &re
|
|||
const Mimes offers = source->offers();
|
||||
|
||||
if (!offers.isEmpty()) {
|
||||
// create new Wl DataSource if there is none or when types
|
||||
// were removed (Wl Data Sources can only add types)
|
||||
KWayland::Client::DataDeviceManager *dataDeviceManager =
|
||||
waylandServer()->internalDataDeviceManager();
|
||||
KWayland::Client::DataSource *dataSource =
|
||||
dataDeviceManager->createDataSource(source);
|
||||
|
||||
// also offers directly the currently available types
|
||||
source->setDataSource(dataSource);
|
||||
DataBridge::self()->dataDevice()->setSelection(0, dataSource);
|
||||
QStringList mimeTypes;
|
||||
mimeTypes.reserve(offers.size());
|
||||
std::transform(offers.begin(), offers.end(), std::back_inserter(mimeTypes), [](const Mimes::value_type &pair) {
|
||||
return pair.first;
|
||||
});
|
||||
auto newSelection = std::make_unique<XwlDataSource>();
|
||||
newSelection->setMimeTypes(mimeTypes);
|
||||
connect(newSelection.get(), &XwlDataSource::dataRequested, source, &X11Source::startTransfer);
|
||||
// we keep the old selection around because setSelection needs it to be still alive
|
||||
std::swap(m_selectionSource, newSelection);
|
||||
waylandServer()->seat()->setSelection(m_selectionSource.get());
|
||||
} else {
|
||||
KWaylandServer::AbstractDataSource *currentSelection = waylandServer()->seat()->selection();
|
||||
if (!ownsSelection(currentSelection)) {
|
||||
waylandServer()->seat()->setSelection(nullptr);
|
||||
m_selectionSource.reset();
|
||||
}
|
||||
}
|
||||
|
||||
waylandServer()->internalClientConection()->flush();
|
||||
waylandServer()->dispatch();
|
||||
}
|
||||
|
||||
} // namespace Xwl
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include "selection.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
class AbstractDataSource;
|
||||
|
@ -20,6 +22,7 @@ namespace KWin
|
|||
{
|
||||
namespace Xwl
|
||||
{
|
||||
class XwlDataSource;
|
||||
|
||||
/**
|
||||
* Represents the X clipboard, which is on Wayland side just called
|
||||
|
@ -54,6 +57,7 @@ private:
|
|||
|
||||
Q_DISABLE_COPY(Clipboard)
|
||||
bool m_waitingForTargets = false;
|
||||
std::unique_ptr<XwlDataSource> m_selectionSource;
|
||||
};
|
||||
|
||||
} // namespace Xwl
|
||||
|
|
30
src/xwl/datasource.cpp
Normal file
30
src/xwl/datasource.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "datasource.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace Xwl
|
||||
{
|
||||
void XwlDataSource::requestData(const QString &mimeType, qint32 fd)
|
||||
{
|
||||
Q_EMIT dataRequested(mimeType, fd);
|
||||
}
|
||||
|
||||
void XwlDataSource::cancel()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList XwlDataSource::mimeTypes() const
|
||||
{
|
||||
return m_mimeTypes;
|
||||
}
|
||||
void XwlDataSource::setMimeTypes(const QStringList &mimeTypes)
|
||||
{
|
||||
m_mimeTypes = mimeTypes;
|
||||
}
|
||||
}
|
||||
}
|
29
src/xwl/datasource.h
Normal file
29
src/xwl/datasource.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <KWaylandServer/abstract_data_source.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
namespace Xwl
|
||||
{
|
||||
class XwlDataSource : public KWaylandServer::AbstractDataSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void requestData(const QString &mimeType, qint32 fd) override;
|
||||
void cancel() override;
|
||||
QStringList mimeTypes() const override;
|
||||
void setMimeTypes(const QStringList &mimeTypes);
|
||||
Q_SIGNALS:
|
||||
void dataRequested(const QString &mimeType, qint32 fd);
|
||||
|
||||
private:
|
||||
QStringList m_mimeTypes;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
*/
|
||||
#include "primary.h"
|
||||
|
||||
#include "datasource.h"
|
||||
#include "selection_source.h"
|
||||
|
||||
#include "x11client.h"
|
||||
#include "wayland_server.h"
|
||||
#include "workspace.h"
|
||||
|
||||
#include <KWaylandServer/abstract_data_source.h>
|
||||
#include <KWaylandServer/seat_interface.h>
|
||||
|
||||
#include <xcb/xcb_event.h>
|
||||
|
@ -28,31 +28,6 @@ namespace KWin
|
|||
namespace Xwl
|
||||
{
|
||||
|
||||
class PrimarySelectionSource : public KWaylandServer::AbstractDataSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void requestData(const QString & mimeType, qint32 fd) override
|
||||
{
|
||||
Q_EMIT dataRequested(mimeType, fd);
|
||||
}
|
||||
void cancel() override
|
||||
{
|
||||
}
|
||||
QStringList mimeTypes() const override
|
||||
{
|
||||
return m_mimeTypes;
|
||||
}
|
||||
void setMimeTypes(const QStringList &mimeTypes)
|
||||
{
|
||||
m_mimeTypes = mimeTypes;
|
||||
}
|
||||
Q_SIGNALS:
|
||||
void dataRequested(const QString &mimeType, qint32 fd);
|
||||
private:
|
||||
QStringList m_mimeTypes;
|
||||
};
|
||||
|
||||
Primary::Primary(xcb_atom_t atom, QObject *parent)
|
||||
: Selection(atom, parent)
|
||||
{
|
||||
|
@ -188,9 +163,9 @@ void Primary::x11OffersChanged(const QStringList &added, const QStringList &remo
|
|||
std::transform(offers.begin(), offers.end(), std::back_inserter(mimeTypes), [](const Mimes::value_type &pair) {
|
||||
return pair.first;
|
||||
});
|
||||
auto newSelection = std::make_unique<PrimarySelectionSource>();
|
||||
auto newSelection = std::make_unique<XwlDataSource>();
|
||||
newSelection->setMimeTypes(mimeTypes);
|
||||
connect(newSelection.get(), &PrimarySelectionSource::dataRequested, source, &X11Source::startTransfer);
|
||||
connect(newSelection.get(), &XwlDataSource::dataRequested, source, &X11Source::startTransfer);
|
||||
// we keep the old selection around because setPrimarySelection needs it to be still alive
|
||||
std::swap(m_primarySelectionSource, newSelection);
|
||||
waylandServer()->seat()->setPrimarySelection(m_primarySelectionSource.get());
|
||||
|
@ -205,5 +180,3 @@ void Primary::x11OffersChanged(const QStringList &added, const QStringList &remo
|
|||
|
||||
} // namespace Xwl
|
||||
} // namespace KWin
|
||||
|
||||
#include "primary.moc"
|
||||
|
|
|
@ -23,8 +23,7 @@ namespace KWin
|
|||
{
|
||||
namespace Xwl
|
||||
{
|
||||
|
||||
class PrimarySelectionSource;
|
||||
class XwlDataSource;
|
||||
|
||||
/**
|
||||
* Represents the X clipboard, which is on Wayland side just called
|
||||
|
@ -59,7 +58,7 @@ private:
|
|||
|
||||
Q_DISABLE_COPY(Primary)
|
||||
bool m_waitingForTargets = false;
|
||||
std::unique_ptr<PrimarySelectionSource> m_primarySelectionSource;
|
||||
std::unique_ptr<XwlDataSource> m_primarySelectionSource;
|
||||
};
|
||||
|
||||
} // namespace Xwl
|
||||
|
|
Loading…
Reference in a new issue