Commit 31ea954b authored by David Edmundson's avatar David Edmundson
Browse files

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
parent d83993a0
......@@ -236,9 +236,9 @@ QVector<TouchInterface *> SeatInterface::Private::touchsForSurface(SurfaceInterf
return interfacesForSurface(surface, touchs);
}
DataDeviceInterface *SeatInterface::Private::dataDeviceForSurface(SurfaceInterface *surface) const
QVector<DataDeviceInterface *> 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<DataDeviceInterface *> 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);
......
......@@ -32,7 +32,7 @@ public:
QVector<PointerInterface *> pointersForSurface(SurfaceInterface *surface) const;
QVector<KeyboardInterface *> keyboardsForSurface(SurfaceInterface *surface) const;
QVector<TouchInterface *> touchsForSurface(SurfaceInterface *surface) const;
DataDeviceInterface *dataDeviceForSurface(SurfaceInterface *surface) const;
QVector<DataDeviceInterface *> dataDevicesForSurface(SurfaceInterface *surface) const;
TextInputInterface *textInputForSurface(SurfaceInterface *surface) const;
void registerDataDevice(DataDeviceInterface *dataDevice);
void registerTextInput(TextInputInterface *textInput);
......@@ -101,7 +101,7 @@ public:
QVector<KeyboardInterface*> keyboards;
QMetaObject::Connection destroyConnection;
quint32 serial = 0;
DataDeviceInterface *selection = nullptr;
QVector<DataDeviceInterface *> selections;
};
Focus focus;
quint32 lastStateSerial = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment