diff --git a/klipper/systemclipboard/waylandclipboard.cpp b/klipper/systemclipboard/waylandclipboard.cpp index 854290e9b..5d3f8edff 100644 --- a/klipper/systemclipboard/waylandclipboard.cpp +++ b/klipper/systemclipboard/waylandclipboard.cpp @@ -28,7 +28,7 @@ class DataControlDeviceManager : public QWaylandClientExtensionTemplate(1) + : QWaylandClientExtensionTemplate(2) { } @@ -232,10 +232,23 @@ public: 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 { @@ -256,9 +269,24 @@ protected: 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); + } + 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) @@ -272,6 +300,20 @@ void DataControlDevice::setSelection(std::unique_ptr selectio 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(); + } +} + WaylandClipboard::WaylandClipboard(QObject *parent) : SystemClipboard(parent) , m_manager(new DataControlDeviceManager) @@ -295,6 +337,14 @@ WaylandClipboard::WaylandClipboard(QObject *parent) connect(m_device.get(), &DataControlDevice::selectionChanged, this, [this]() { emit changed(QClipboard::Clipboard); }); + + connect(m_device.get(), &DataControlDevice::receivedPrimarySelectionChanged, this, [this]() { + emit changed(QClipboard::Selection); + }); + connect(m_device.get(), &DataControlDevice::primarySelectionChanged, this, [this]() { + emit changed(QClipboard::Selection); + }); + } else { m_device.reset(); } @@ -309,6 +359,8 @@ void WaylandClipboard::setMimeData(QMimeData *mime, QClipboard::Mode mode) 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)); } } @@ -331,9 +383,12 @@ const QMimeData *WaylandClipboard::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) { - // return our locally set selection if it's not cancelled to avoid copying data to ourselves return m_device->selection() ? m_device->selection() : m_device->receivedSelection(); + } else if (mode == QClipboard::Selection) { + return m_device->primarySelection() ? m_device->primarySelection() : m_device->receivedPrimarySelection(); } return nullptr; }