From 9454421ff796fcb0a78eb430863395788c15ed06 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 18 May 2020 09:18:24 +0100 Subject: [PATCH] Support mulitple data devices on a single client Summary: Firefox has two wl_data_devices. One in firefox code one in GTK code. Both need to get data offers. I've left handling the case for multiple data devices and drags to make this patch feasible to put into 5.19 and I didn't want to make this patch invasive. Test Plan: Firefox in wayland WAYLAND_DEBUG=1 firefox |& grep data Shows now both created devices get offers Also I can paste Reviewers: #kwin, zzag Reviewed By: #kwin, zzag Subscribers: ngraham, zzag Differential Revision: https://phabricator.kde.org/D29720 --- src/wayland/seat_interface.cpp | 50 ++++++++++++++++++++-------------- src/wayland/seat_interface_p.h | 4 +-- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 7f4debe75d..ea4a02e447 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -236,9 +236,9 @@ QVector SeatInterface::Private::touchsForSurface(SurfaceInterf return interfacesForSurface(surface, touchs); } -DataDeviceInterface *SeatInterface::Private::dataDeviceForSurface(SurfaceInterface *surface) const +QVector SeatInterface::Private::dataDevicesForSurface(SurfaceInterface *surface) const { - return interfaceForSurface(surface, dataDevices); + return interfacesForSurface(surface, dataDevices); } TextInputInterface *SeatInterface::Private::textInputForSurface(SurfaceInterface *surface) const @@ -252,15 +252,14 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice) dataDevices << dataDevice; auto dataDeviceCleanup = [this, dataDevice] { dataDevices.removeOne(dataDevice); - if (keys.focus.selection == dataDevice) { - keys.focus.selection = nullptr; - } + keys.focus.selections.removeOne(dataDevice); + if (currentSelection == dataDevice) { // current selection is cleared currentSelection = nullptr; emit q->selectionChanged(nullptr); - if (keys.focus.selection) { - keys.focus.selection->sendClearSelection(); + for (auto selection: keys.focus.selections) { + selection->sendClearSelection(); } } }; @@ -328,10 +327,10 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice) } ); // is the new DataDevice for the current keyoard focus? - if (keys.focus.surface && !keys.focus.selection) { + if (keys.focus.surface) { // same client? if (keys.focus.surface->client() == dataDevice->client()) { - keys.focus.selection = dataDevice; + keys.focus.selections.append(dataDevice); if (currentSelection && currentSelection->selection()) { dataDevice->sendSelection(currentSelection); } @@ -408,11 +407,11 @@ void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice, bo } if (dataDevice == currentSelection) { // need to send out the selection - if (keys.focus.selection) { + for (auto focussedDevice: qAsConst(keys.focus.selections)) { if (set) { - keys.focus.selection->sendSelection(dataDevice); + focussedDevice->sendSelection(dataDevice); } else { - keys.focus.selection->sendClearSelection(); + focussedDevice->sendClearSelection(); currentSelection = nullptr; selChanged = true; } @@ -648,7 +647,15 @@ void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &glob if (d->drag.target) { d->drag.target->updateDragTarget(nullptr, serial); } - d->drag.target = d->dataDeviceForSurface(surface); + + // technically we can have mulitple 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 mulitple data devices is for clipboard overriding + d->drag.target = nullptr; + if (d->dataDevicesForSurface(surface).size() > 0) { + d->drag.target = d->dataDevicesForSurface(surface).first(); + } + if (d->drag.mode == Private::Drag::Mode::Pointer) { setPointerPos(globalPosition); } else if (d->drag.mode == Private::Drag::Mode::Touch && @@ -1128,12 +1135,13 @@ void SeatInterface::setFocusedKeyboardSurface(SurfaceInterface *surface) ); d->keys.focus.serial = serial; // selection? - d->keys.focus.selection = d->dataDeviceForSurface(surface); - if (d->keys.focus.selection) { - if (d->currentSelection && d->currentSelection->selection()) { - d->keys.focus.selection->sendSelection(d->currentSelection); + const QVector dataDevices = d->dataDevicesForSurface(surface); + d->keys.focus.selections = dataDevices; + for (auto dataDevice : dataDevices) { + if (d->currentSelection) { + dataDevice->sendSelection(d->currentSelection); } else { - d->keys.focus.selection->sendClearSelection(); + dataDevice->sendClearSelection(); } } } @@ -1602,11 +1610,11 @@ void SeatInterface::setSelection(DataDeviceInterface *dataDevice) // cancel the previous selection d->cancelPreviousSelection(dataDevice); d->currentSelection = dataDevice; - if (d->keys.focus.selection) { + for (auto focussedDevice: qAsConst(d->keys.focus.selections)) { if (dataDevice && dataDevice->selection()) { - d->keys.focus.selection->sendSelection(dataDevice); + focussedDevice->sendSelection(dataDevice); } else { - d->keys.focus.selection->sendClearSelection(); + focussedDevice->sendClearSelection(); } } emit selectionChanged(dataDevice); diff --git a/src/wayland/seat_interface_p.h b/src/wayland/seat_interface_p.h index 0ec152a713..387f334231 100644 --- a/src/wayland/seat_interface_p.h +++ b/src/wayland/seat_interface_p.h @@ -32,7 +32,7 @@ public: QVector pointersForSurface(SurfaceInterface *surface) const; QVector keyboardsForSurface(SurfaceInterface *surface) const; QVector touchsForSurface(SurfaceInterface *surface) const; - DataDeviceInterface *dataDeviceForSurface(SurfaceInterface *surface) const; + QVector dataDevicesForSurface(SurfaceInterface *surface) const; TextInputInterface *textInputForSurface(SurfaceInterface *surface) const; void registerDataDevice(DataDeviceInterface *dataDevice); void registerTextInput(TextInputInterface *textInput); @@ -101,7 +101,7 @@ public: QVector keyboards; QMetaObject::Connection destroyConnection; quint32 serial = 0; - DataDeviceInterface *selection = nullptr; + QVector selections; }; Focus focus; quint32 lastStateSerial = 0;