[plasma/kwin/Plasma/6.7] src/wayland: Support more than one wl_data_device
Vlad Zahorodnii <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 528acd49e4e3b849a5fed2307f4a5e12e1a5a395 by Vlad Zahorodnii. Committed on 10/08/2026 at 11:08. Pushed by vladz into branch 'Plasma/6.7'. Support more than one wl_data_device KWin uses only first data_device and ignores any other. This patch allows to create and use more wl_data_devices per wl_seat. BUG: 521494 (cherry picked from commit e07d87d69916defcdc78ee2cb559ff9363ab2b5f) Co-authored-by: Martin Stransky <[email protected]> M +37 -22 src/wayland/seat.cpp M +1 -1 src/wayland/seat_p.h https://invent.kde.org/plasma/kwin/-/commit/528acd49e4e3b849a5fed2307f4a5e12e1a5a395 diff --git a/src/wayland/seat.cpp b/src/wayland/seat.cpp index 095ca86c24e..549627cd73e 100644 --- a/src/wayland/seat.cpp +++ b/src/wayland/seat.cpp @@ -163,6 +163,7 @@ void SeatInterfacePrivate::registerDataDevice(DataDeviceInterface *dataDevice) auto dataDeviceCleanup = [this, dataDevice] { dataDevices.removeOne(dataDevice); globalDataDevice.selections.removeOne(dataDevice); + drag.targets.removeOne(dataDevice); }; QObject::connect(dataDevice, &QObject::destroyed, q, dataDeviceCleanup); QObject::connect(dataDevice, &DataDeviceInterface::selectionChanged, q, [this](DataSourceInterface *source, quint32 serial) { @@ -195,13 +196,16 @@ void SeatInterface::endDrag() QObject::disconnect(d->drag.dragSourceDestroyConnection); - AbstractDropHandler *dragTargetDevice = d->drag.target.data(); + const auto dragTargets = d->drag.targets; AbstractDataSource *dragSource = d->drag.source; + const bool hasTarget = !dragTargets.isEmpty(); if (dragSource) { - if (dragTargetDevice && dragSource->isAccepted() && dragSource->selectedDndAction() != DnDAction::None) { + if (hasTarget && dragSource->isAccepted() && dragSource->selectedDndAction() != DnDAction::None) { Q_EMIT dragDropped(); - dragTargetDevice->drop(); + for (const auto &target : dragTargets) { + target->drop(); + } dragSource->dropPerformed(); } else { dragSource->dropPerformed(); @@ -209,8 +213,8 @@ void SeatInterface::endDrag() } } - if (dragTargetDevice) { - dragTargetDevice->updateDragTarget(nullptr, QPointF(), 0); + for (const auto &target : dragTargets) { + target->updateDragTarget(nullptr, QPointF(), 0); } d->drag = {}; @@ -227,9 +231,8 @@ void SeatInterface::cancelDrag() if (d->drag.source) { d->drag.source->dndCancelled(); } - if (d->drag.target) { - d->drag.target->updateDragTarget(nullptr, QPointF(), 0); - d->drag.target = nullptr; + for (const auto &target : std::as_const(d->drag.targets)) { + target->updateDragTarget(nullptr, QPointF(), 0); } d->drag = {}; Q_EMIT dragEnded(); @@ -472,22 +475,30 @@ void SeatInterface::setDragTarget(AbstractDropHandler *dropTarget, return; } const quint32 serial = d->display->nextSerial(); - if (d->drag.target) { - d->drag.target->updateDragTarget(nullptr, QPointF(), serial); + for (const auto &target : std::as_const(d->drag.targets)) { + target->updateDragTarget(nullptr, QPointF(), serial); } + d->drag.targets.clear(); - // TODO: technically we can have multiple data devices - // and we should send the drag to all of them, but that seems overly complicated - // in practice so far the only case for multiple data devices is for clipboard overriding - d->drag.target = dropTarget; + if (surface) { + const auto dataDevices = d->dataDevicesForSurface(surface); + for (auto device : dataDevices) { + d->drag.targets.append(device); + } + if (d->drag.targets.isEmpty() && dropTarget) { + d->drag.targets.append(dropTarget); + } + } - if (d->drag.target) { + if (!d->drag.targets.isEmpty()) { d->drag.surface = surface; d->drag.transformation = inputTransformation; if (d->dragInhibitsPointer(d->globalPointer.focus.surface)) { notifyPointerLeave(); } - d->drag.target->updateDragTarget(surface, globalPosition, serial); + for (const auto &target : std::as_const(d->drag.targets)) { + target->updateDragTarget(surface, globalPosition, serial); + } } else { d->drag.surface = nullptr; } @@ -501,8 +512,8 @@ QPointF SeatInterface::dragPosition() const void SeatInterface::notifyDragMotion(const QPointF &position) { d->drag.position = position; - if (d->drag.target) { - d->drag.target->motion(position); + for (const auto &target : std::as_const(d->drag.targets)) { + target->motion(position); } Q_EMIT dragMoved(position); } @@ -1293,14 +1304,18 @@ bool SeatInterfacePrivate::startDrag(Drag::Mode mode, AbstractDataSource *dragSo } drag.dragIcon = dragIcon; - if (!dataDevicesForSurface(originSurface).isEmpty()) { - drag.target = dataDevicesForSurface(originSurface)[0]; + const auto devices = dataDevicesForSurface(originSurface); + for (auto device : devices) { + drag.targets.append(device); } - if (drag.target) { + if (!drag.targets.isEmpty()) { if (dragInhibitsPointer(originSurface)) { q->notifyPointerLeave(); } - drag.target->updateDragTarget(originSurface, drag.position, display->nextSerial()); + const quint32 serial = display->nextSerial(); + for (const auto &target : std::as_const(drag.targets)) { + target->updateDragTarget(originSurface, drag.position, serial); + } } Q_EMIT q->dragStarted(); return true; diff --git a/src/wayland/seat_p.h b/src/wayland/seat_p.h index ae664f31f13..6c4ee1bee58 100644 --- a/src/wayland/seat_p.h +++ b/src/wayland/seat_p.h @@ -135,7 +135,7 @@ public: Mode mode = Mode::None; AbstractDataSource *source = nullptr; QPointer<SurfaceInterface> surface; - QPointer<AbstractDropHandler> target; + QList<AbstractDropHandler *> targets; QPointer<DragAndDropIcon> dragIcon; QPointF position; QMatrix4x4 transformation;