diff --git a/CMakeLists.txt b/CMakeLists.txt index 517e81ade..2b4aab5b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ if (SAILFISHOS) set(KF5_MIN_VERSION "5.36.0") set(QT_MIN_VERSION "5.6.0") else() - set(KF5_MIN_VERSION "5.71.0") + set(KF5_MIN_VERSION "5.89.0") set(QT_MIN_VERSION "5.10.0") endif() set(QCA_MIN_VERSION "2.1.0") @@ -60,7 +60,7 @@ else() find_package(Qca-qt5 ${QCA_MIN_VERSION} REQUIRED) set(Qca_LIBRARY qca-qt5) - set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem) + set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons) set(KF5_OPTIONAL_COMPONENTS DocTools Wayland) set_package_properties(KF5Kirigami2 PROPERTIES diff --git a/plugins/clipboard/CMakeLists.txt b/plugins/clipboard/CMakeLists.txt index 61dbf3c36..0b271c84c 100644 --- a/plugins/clipboard/CMakeLists.txt +++ b/plugins/clipboard/CMakeLists.txt @@ -1,8 +1,3 @@ -if(UNIX AND NOT APPLE) - find_package(QtWaylandScanner REQUIRED) - find_package(Wayland 1.15 COMPONENTS Client) - find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient) -endif() set(debug_file_SRCS) ecm_qt_declare_logging_category( @@ -17,20 +12,9 @@ set(kdeconnect_clipboard_SRCS ${debug_file_SRCS} ) -if(UNIX AND NOT APPLE) - list(APPEND kdeconnect_clipboard_SRCS datacontrol.cpp) - ecm_add_qtwayland_client_protocol(kdeconnect_clipboard_SRCS - PROTOCOL wlr-data-control-unstable-v1.xml - BASENAME wlr-data-control-unstable-v1 - ) - set(kdeconnect_clipboard_WL_LINK_LIBS Qt5::GuiPrivate # for native interface to get wl_seat - Wayland::Client Qt::WaylandClient) -endif() - - kdeconnect_add_plugin(kdeconnect_clipboard SOURCES ${kdeconnect_clipboard_SRCS}) target_link_libraries(kdeconnect_clipboard kdeconnectcore - Qt5::Gui + KF5::GuiAddons ${kdeconnect_clipboard_WL_LINK_LIBS} ) diff --git a/plugins/clipboard/clipboardlistener.cpp b/plugins/clipboard/clipboardlistener.cpp index 6d3bad2bf..aed78f810 100644 --- a/plugins/clipboard/clipboardlistener.cpp +++ b/plugins/clipboard/clipboardlistener.cpp @@ -5,15 +5,11 @@ */ #include "clipboardlistener.h" -#include + +#include + #include - -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) -#include "datacontrol.h" -#endif - -ClipboardListener::ClipboardListener() -{} +#include QString ClipboardListener::currentContent() { @@ -27,17 +23,9 @@ qint64 ClipboardListener::updateTimestamp(){ ClipboardListener* ClipboardListener::instance() { - static ClipboardListener* me = nullptr; + static ClipboardListener *me = nullptr; if (!me) { -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) { - me = new WaylandClipboardListener(); - } else { -#endif - me = new QClipboardListener(); -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) - } -#endif + me = new ClipboardListener(); } return me; } @@ -48,23 +36,23 @@ void ClipboardListener::refreshContent(const QString& content) m_currentContent = content; } -QClipboardListener::QClipboardListener() - : clipboard(QGuiApplication::clipboard()) +ClipboardListener::ClipboardListener() + : clipboard(KSystemClipboard::instance()) { #ifdef Q_OS_MAC connect(&m_clipboardMonitorTimer, &QTimer::timeout, this, [this](){ updateClipboard(QClipboard::Clipboard); }); m_clipboardMonitorTimer.start(1000); // Refresh 1s #endif - connect(clipboard, &QClipboard::changed, this, &QClipboardListener::updateClipboard); + connect(clipboard, &KSystemClipboard::changed, this, &ClipboardListener::updateClipboard); } -void QClipboardListener::updateClipboard(QClipboard::Mode mode) +void ClipboardListener::updateClipboard(QClipboard::Mode mode) { if (mode != QClipboard::Clipboard) { return; } - const QString content = clipboard->text(); + const QString content = clipboard->text(QClipboard::Clipboard); if (content == m_currentContent) { return; } @@ -72,39 +60,10 @@ void QClipboardListener::updateClipboard(QClipboard::Mode mode) Q_EMIT clipboardChanged(content); } -void QClipboardListener::setText(const QString& content) -{ - refreshContent(content); - clipboard->setText(content); -} - -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) -WaylandClipboardListener::WaylandClipboardListener() - : m_dataControl(new DataControl(this)) -{ - connect(m_dataControl, &DataControl::changed, this, &WaylandClipboardListener::refresh); -} - -void WaylandClipboardListener::setText(const QString& content) +void ClipboardListener::setText(const QString& content) { refreshContent(content); auto mime = new QMimeData; mime->setText(content); - m_dataControl->setMimeData(mime, QClipboard::Clipboard); + clipboard->setMimeData(mime, QClipboard::Clipboard); } - -void WaylandClipboardListener::refresh() -{ - const QMimeData *mime = m_dataControl->mimeData(QClipboard::Clipboard); - if (!mime || !mime->hasText()) { - return; - } - - const QString content = mime->text(); - if (content == m_currentContent) { - return; - } - refreshContent(content); - Q_EMIT clipboardChanged(content); -} -#endif diff --git a/plugins/clipboard/clipboardlistener.h b/plugins/clipboard/clipboardlistener.h index 29b64db82..171393e9e 100644 --- a/plugins/clipboard/clipboardlistener.h +++ b/plugins/clipboard/clipboardlistener.h @@ -7,11 +7,14 @@ #ifndef CLIPBOARDLISTENER_H #define CLIPBOARDLISTENER_H -#include -#include #include #include -#include + +#ifdef Q_OS_MAC +#include +#endif + +class KSystemClipboard; /** * Wrapper around QClipboard, which emits clipboardChanged only when it really changed @@ -32,43 +35,21 @@ private: public: static ClipboardListener* instance(); - virtual void setText(const QString& content) = 0; + void setText(const QString& content); QString currentContent(); qint64 updateTimestamp(); Q_SIGNALS: void clipboardChanged(const QString& content); -}; - -class QClipboardListener : public ClipboardListener -{ -public: - QClipboardListener(); - - void setText(const QString & content) override; private: -#ifdef Q_OS_MAC - QTimer m_clipboardMonitorTimer; -#endif void updateClipboard(QClipboard::Mode mode); - QClipboard* clipboard; -}; -class DataControl; - -class WaylandClipboardListener : public ClipboardListener -{ -public: - WaylandClipboardListener(); - - void setText(const QString & content) override; - -private: - void refresh(); - - DataControl *m_dataControl; +#ifdef Q_OS_MAC + QTimer *m_clipboardMonitorTimer; +#endif + KSystemClipboard *clipboard; }; #endif diff --git a/plugins/clipboard/clipboardplugin.cpp b/plugins/clipboard/clipboardplugin.cpp index 543fe16bf..80d212e0f 100644 --- a/plugins/clipboard/clipboardplugin.cpp +++ b/plugins/clipboard/clipboardplugin.cpp @@ -40,7 +40,6 @@ void ClipboardPlugin::sendConnectPacket() sendPacket(np); } - bool ClipboardPlugin::receivePacket(const NetworkPacket& np) { QString content = np.get(QStringLiteral("content")); diff --git a/plugins/clipboard/datacontrol.cpp b/plugins/clipboard/datacontrol.cpp deleted file mode 100644 index f195a0a8f..000000000 --- a/plugins/clipboard/datacontrol.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 David Edmundson - - SPDX-License-Identifier: LGPL-2.0-or-later -*/ - -#include "datacontrol.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -#include "qwayland-wlr-data-control-unstable-v1.h" - -static QString utf8Text() -{ - return QStringLiteral("text/plain;charset=utf-8"); -} - -class DataControlDeviceManager : public QWaylandClientExtensionTemplate, public QtWayland::zwlr_data_control_manager_v1 -{ - Q_OBJECT -public: - DataControlDeviceManager() - : QWaylandClientExtensionTemplate(2) - { - } - - ~DataControlDeviceManager() override - { - destroy(); - } -}; - -class DataControlOffer : public QMimeData, public QtWayland::zwlr_data_control_offer_v1 -{ - Q_OBJECT -public: - DataControlOffer(struct ::zwlr_data_control_offer_v1 *id) - : QtWayland::zwlr_data_control_offer_v1(id) - { - } - - ~DataControlOffer() override - { - destroy(); - } - - QStringList formats() const override - { - return m_receivedFormats; - } - - bool hasFormat(const QString &mimeType) const override - { - if (mimeType == QStringLiteral("text/plain") && m_receivedFormats.contains(utf8Text())) { - return true; - } - return m_receivedFormats.contains(mimeType); - } - -protected: - void zwlr_data_control_offer_v1_offer(const QString &mime_type) override - { - m_receivedFormats << mime_type; - } - - QVariant retrieveData(const QString &mimeType, QVariant::Type type) const override; - -private: - static bool readData(int fd, QByteArray &data); - QStringList m_receivedFormats; -}; - -QVariant DataControlOffer::retrieveData(const QString &mimeType, QVariant::Type type) const -{ - Q_UNUSED(type); - - QString mime = mimeType; - if (!m_receivedFormats.contains(mimeType)) { - if (mimeType == QStringLiteral("text/plain") && m_receivedFormats.contains(utf8Text())) { - mime = utf8Text(); - } else { - return QVariant(); - } - } - - int pipeFds[2]; - if (pipe(pipeFds) != 0) { - return QVariant(); - } - - auto t = const_cast(this); - t->receive(mime, pipeFds[1]); - - close(pipeFds[1]); - - /* - * Ideally we need to introduce a non-blocking QMimeData object - * Or a non-blocking constructor to QMimeData with the mimetypes that are relevant - * - * However this isn't actually any worse than X. - */ - - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - auto display = static_cast(native->nativeResourceForIntegration("wl_display")); - wl_display_flush(display); - - QFile readPipe; - if (readPipe.open(pipeFds[0], QIODevice::ReadOnly)) { - QByteArray data; - if (readData(pipeFds[0], data)) { - close(pipeFds[0]); - return data; - } - close(pipeFds[0]); - } - return QVariant(); -} - -// reads data from a file descriptor with a timeout of 1 second -// true if data is read successfully -bool DataControlOffer::readData(int fd, QByteArray &data) -{ - pollfd pfds[1]; - pfds[0].fd = fd; - pfds[0].events = POLLIN; - - while (true) { - const int ready = poll(pfds, 1, 1000); - if (ready < 0) { - if (errno != EINTR) { - qWarning("DataControlOffer: poll() failed: %s", strerror(errno)); - return false; - } - } else if (ready == 0) { - qWarning("DataControlOffer: timeout reading from pipe"); - return false; - } else { - char buf[4096]; - int n = read(fd, buf, sizeof buf); - - if (n < 0) { - qWarning("DataControlOffer: read() failed: %s", strerror(errno)); - return false; - } else if (n == 0) { - return true; - } else if (n > 0) { - data.append(buf, n); - } - } - } -} - -class DataControlSource : public QObject, public QtWayland::zwlr_data_control_source_v1 -{ - Q_OBJECT -public: - DataControlSource(struct ::zwlr_data_control_source_v1 *id, QMimeData *mimeData); - DataControlSource(); - ~DataControlSource() override - { - destroy(); - } - - QMimeData *mimeData() - { - return m_mimeData; - } - -Q_SIGNALS: - void cancelled(); - -protected: - void zwlr_data_control_source_v1_send(const QString &mime_type, int32_t fd) override; - void zwlr_data_control_source_v1_cancelled() override; - -private: - QMimeData *m_mimeData; -}; - -DataControlSource::DataControlSource(struct ::zwlr_data_control_source_v1 *id, QMimeData *mimeData) - : QtWayland::zwlr_data_control_source_v1(id) - , m_mimeData(mimeData) -{ - for (const QString &format : mimeData->formats()) { - offer(format); - } - if (mimeData->hasText()) { - // ensure GTK applications get this mimetype to avoid them discarding the offer - offer(QStringLiteral("text/plain;charset=utf-8")); - } -} - -void DataControlSource::zwlr_data_control_source_v1_send(const QString &mime_type, int32_t fd) -{ - QFile c; - QString send_mime_type = mime_type; - if (send_mime_type == QStringLiteral("text/plain;charset=utf-8")) { - // if we get a request on the fallback mime, send the data from the original mime type - send_mime_type = QStringLiteral("text/plain"); - } - if (c.open(fd, QFile::WriteOnly, QFile::AutoCloseHandle)) { - c.write(m_mimeData->data(send_mime_type)); - c.close(); - } -} - -void DataControlSource::zwlr_data_control_source_v1_cancelled() -{ - Q_EMIT cancelled(); -} - -class DataControlDevice : public QObject, public QtWayland::zwlr_data_control_device_v1 -{ - Q_OBJECT -public: - DataControlDevice(struct ::zwlr_data_control_device_v1 *id) - : QtWayland::zwlr_data_control_device_v1(id) - { - } - - ~DataControlDevice() override - { - destroy(); - } - - void setSelection(std::unique_ptr selection); - QMimeData *receivedSelection() - { - return m_receivedSelection.get(); - } - QMimeData *selection() - { - return m_selection ? m_selection->mimeData() : nullptr; - } - - void setPrimarySelection(std::unique_ptr selection); - QMimeData *receivedPrimarySelection() - { - return m_receivedPrimarySelection.get(); - } - QMimeData *primarySelection() - { - return m_primarySelection ? m_primarySelection->mimeData() : nullptr; - } - -Q_SIGNALS: - void receivedSelectionChanged(); - void selectionChanged(); - - void receivedPrimarySelectionChanged(); - void primarySelectionChanged(); - -protected: - void zwlr_data_control_device_v1_data_offer(struct ::zwlr_data_control_offer_v1 *id) override - { - new DataControlOffer(id); - // this will become memory managed when we retrieve the selection event - // a compositor calling data_offer without doing that would be a bug - } - - void zwlr_data_control_device_v1_selection(struct ::zwlr_data_control_offer_v1 *id) override - { - if (!id) { - m_receivedSelection.reset(); - } else { - auto deriv = QtWayland::zwlr_data_control_offer_v1::fromObject(id); - auto offer = dynamic_cast(deriv); // dynamic because of the dual inheritance - m_receivedSelection.reset(offer); - } - Q_EMIT receivedSelectionChanged(); - } - - void zwlr_data_control_device_v1_primary_selection(struct ::zwlr_data_control_offer_v1 *id) override - { - if (!id) { - m_receivedPrimarySelection.reset(); - } else { - auto deriv = QtWayland::zwlr_data_control_offer_v1::fromObject(id); - auto offer = dynamic_cast(deriv); // dynamic because of the dual inheritance - m_receivedPrimarySelection.reset(offer); - } - Q_EMIT receivedPrimarySelectionChanged(); - } - -private: - std::unique_ptr m_selection; // selection set locally - std::unique_ptr m_receivedSelection; // latest selection set from externally to here - - std::unique_ptr m_primarySelection; // selection set locally - std::unique_ptr m_receivedPrimarySelection; // latest selection set from externally to here -}; - -void DataControlDevice::setSelection(std::unique_ptr selection) -{ - m_selection = std::move(selection); - connect(m_selection.get(), &DataControlSource::cancelled, this, [this]() { - m_selection.reset(); - Q_EMIT selectionChanged(); - }); - set_selection(m_selection->object()); - Q_EMIT selectionChanged(); -} - -void DataControlDevice::setPrimarySelection(std::unique_ptr selection) -{ - m_primarySelection = std::move(selection); - connect(m_primarySelection.get(), &DataControlSource::cancelled, this, [this]() { - m_primarySelection.reset(); - Q_EMIT primarySelectionChanged(); - }); - - if (zwlr_data_control_device_v1_get_version(object()) >= ZWLR_DATA_CONTROL_DEVICE_V1_SET_PRIMARY_SELECTION_SINCE_VERSION) { - set_primary_selection(m_primarySelection->object()); - Q_EMIT primarySelectionChanged(); - } -} - -DataControl::DataControl(QObject *parent) - : QObject(parent) - , m_manager(new DataControlDeviceManager) -{ - connect(m_manager.get(), &DataControlDeviceManager::activeChanged, this, [this]() { - if (m_manager->isActive()) { - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - if (!native) { - return; - } - auto seat = static_cast(native->nativeResourceForIntegration("wl_seat")); - if (!seat) { - return; - } - - m_device.reset(new DataControlDevice(m_manager->get_data_device(seat))); - - connect(m_device.get(), &DataControlDevice::receivedSelectionChanged, this, [this]() { - Q_EMIT changed(QClipboard::Clipboard); - }); - connect(m_device.get(), &DataControlDevice::selectionChanged, this, [this]() { - Q_EMIT changed(QClipboard::Clipboard); - }); - - connect(m_device.get(), &DataControlDevice::receivedPrimarySelectionChanged, this, [this]() { - Q_EMIT changed(QClipboard::Selection); - }); - connect(m_device.get(), &DataControlDevice::primarySelectionChanged, this, [this]() { - Q_EMIT changed(QClipboard::Selection); - }); - - } else { - m_device.reset(); - } - }); -} - -DataControl::~DataControl() = default; - -void DataControl::setMimeData(QMimeData *mime, QClipboard::Mode mode) -{ - if (!m_device) { - return; - } - auto source = std::make_unique(m_manager->create_data_source(), mime); - if (mode == QClipboard::Clipboard) { - m_device->setSelection(std::move(source)); - } else if (mode == QClipboard::Selection) { - m_device->setPrimarySelection(std::move(source)); - } -} - -void DataControl::clear(QClipboard::Mode mode) -{ - if (!m_device) { - return; - } - if (mode == QClipboard::Clipboard) { - m_device->set_selection(nullptr); - } else if (mode == QClipboard::Selection) { - if (zwlr_data_control_device_v1_get_version(m_device->object()) >= ZWLR_DATA_CONTROL_DEVICE_V1_SET_PRIMARY_SELECTION_SINCE_VERSION) { - m_device->set_primary_selection(nullptr); - } - } -} - -const QMimeData *DataControl::mimeData(QClipboard::Mode mode) const -{ - if (!m_device) { - return nullptr; - } - - // return our locally set selection if it's not cancelled to avoid copying data to ourselves - if (mode == QClipboard::Clipboard) { - if (m_device->selection()) { - return m_device->selection(); - } - // This application owns the clipboard via the regular data_device, use it so we don't block ourselves - if (QGuiApplication::clipboard()->ownsClipboard()) { - return QGuiApplication::clipboard()->mimeData(mode); - } - return m_device->receivedSelection(); - } else if (mode == QClipboard::Selection) { - if (m_device->primarySelection()) { - return m_device->primarySelection(); - } - // This application owns the primary selection via the regular primary_selection_device, use it so we don't block ourselves - if (QGuiApplication::clipboard()->ownsSelection()) { - return QGuiApplication::clipboard()->mimeData(mode); - } - return m_device->receivedPrimarySelection(); - } - return nullptr; -} - -#include "datacontrol.moc" diff --git a/plugins/clipboard/datacontrol.h b/plugins/clipboard/datacontrol.h deleted file mode 100644 index 7ed55fb1a..000000000 --- a/plugins/clipboard/datacontrol.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - SPDX-FileCopyrightText: 2020 David Edmundson - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - -#pragma once -#include -#include -#include -#include - -class DataControlDevice; -class DataControlDeviceManager; -class QMimeData; - -class DataControl : public QObject -{ - Q_OBJECT -public: - DataControl(QObject *parent = nullptr); - ~DataControl() override; - - const QMimeData *mimeData(QClipboard::Mode mode) const; - void setMimeData(QMimeData *mime, QClipboard::Mode mode); - void clear(QClipboard::Mode mode); - -Q_SIGNALS: - void changed(QClipboard::Mode mode); - -private: - std::unique_ptr m_manager; - std::unique_ptr m_device; -}; diff --git a/plugins/clipboard/wlr-data-control-unstable-v1.xml b/plugins/clipboard/wlr-data-control-unstable-v1.xml deleted file mode 100644 index 75e8671b0..000000000 --- a/plugins/clipboard/wlr-data-control-unstable-v1.xml +++ /dev/null @@ -1,278 +0,0 @@ - - - - Copyright © 2018 Simon Ser - Copyright © 2019 Ivan Molodetskikh - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - This protocol allows a privileged client to control data devices. In - particular, the client will be able to manage the current selection and take - the role of a clipboard manager. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - - - - - This interface is a manager that allows creating per-seat data device - controls. - - - - - Create a new data source. - - - - - - - Create a data device that can be used to manage a seat's selection. - - - - - - - - All objects created by the manager will still remain valid, until their - appropriate destroy request has been called. - - - - - - - This interface allows a client to manage a seat's selection. - - When the seat is destroyed, this object becomes inert. - - - - - This request asks the compositor to set the selection to the data from - the source on behalf of the client. - - The given source may not be used in any further set_selection or - set_primary_selection requests. Attempting to use a previously used - source is a protocol error. - - To unset the selection, set the source to NULL. - - - - - - - Destroys the data device object. - - - - - - The data_offer event introduces a new wlr_data_control_offer object, - which will subsequently be used in either the - wlr_data_control_device.selection event (for the regular clipboard - selections) or the wlr_data_control_device.primary_selection event (for - the primary clipboard selections). Immediately following the - wlr_data_control_device.data_offer event, the new data_offer object - will send out wlr_data_control_offer.offer events to describe the MIME - types it offers. - - - - - - - The selection event is sent out to notify the client of a new - wlr_data_control_offer for the selection for this device. The - wlr_data_control_device.data_offer and the wlr_data_control_offer.offer - events are sent out immediately before this event to introduce the data - offer object. The selection event is sent to a client when a new - selection is set. The wlr_data_control_offer is valid until a new - wlr_data_control_offer or NULL is received. The client must destroy the - previous selection wlr_data_control_offer, if any, upon receiving this - event. - - The first selection event is sent upon binding the - wlr_data_control_device object. - - - - - - - This data control object is no longer valid and should be destroyed by - the client. - - - - - - - - The primary_selection event is sent out to notify the client of a new - wlr_data_control_offer for the primary selection for this device. The - wlr_data_control_device.data_offer and the wlr_data_control_offer.offer - events are sent out immediately before this event to introduce the data - offer object. The primary_selection event is sent to a client when a - new primary selection is set. The wlr_data_control_offer is valid until - a new wlr_data_control_offer or NULL is received. The client must - destroy the previous primary selection wlr_data_control_offer, if any, - upon receiving this event. - - If the compositor supports primary selection, the first - primary_selection event is sent upon binding the - wlr_data_control_device object. - - - - - - - This request asks the compositor to set the primary selection to the - data from the source on behalf of the client. - - The given source may not be used in any further set_selection or - set_primary_selection requests. Attempting to use a previously used - source is a protocol error. - - To unset the primary selection, set the source to NULL. - - The compositor will ignore this request if it does not support primary - selection. - - - - - - - - - - - - The wlr_data_control_source object is the source side of a - wlr_data_control_offer. It is created by the source client in a data - transfer and provides a way to describe the offered data and a way to - respond to requests to transfer the data. - - - - - - - - - This request adds a MIME type to the set of MIME types advertised to - targets. Can be called several times to offer multiple types. - - Calling this after wlr_data_control_device.set_selection is a protocol - error. - - - - - - - Destroys the data source object. - - - - - - Request for data from the client. Send the data as the specified MIME - type over the passed file descriptor, then close it. - - - - - - - - This data source is no longer valid. The data source has been replaced - by another data source. - - The client should clean up and destroy this data source. - - - - - - - A wlr_data_control_offer represents a piece of data offered for transfer - by another client (the source client). The offer describes the different - MIME types that the data can be converted to and provides the mechanism - for transferring the data directly from the source client. - - - - - To transfer the offered data, the client issues this request and - indicates the MIME type it wants to receive. The transfer happens - through the passed file descriptor (typically created with the pipe - system call). The source client writes the data in the MIME type - representation requested and then closes the file descriptor. - - The receiving client reads from the read end of the pipe until EOF and - then closes its end, at which point the transfer is complete. - - This request may happen multiple times for different MIME types. - - - - - - - - Destroys the data offer object. - - - - - - Sent immediately after creating the wlr_data_control_offer object. - One event per offered MIME type. - - - - -