wayland: Fix drag-and-drop issues in Firefox
At the moment, the data offer initializes supported and preferred action to "none". But if the target doesn't accept anything the source provides, the compositor may still need to send action events with "none" This change makes data offer and data source provide dnd actions wrapped in std::optional in order to indicate if they have been set explicitly.
This commit is contained in:
parent
20a94d7157
commit
1ee00bc6f9
3 changed files with 28 additions and 21 deletions
|
@ -212,6 +212,25 @@ void DataDeviceInterface::drop()
|
|||
d->drag.surface = nullptr;
|
||||
}
|
||||
|
||||
static DataDeviceManagerInterface::DnDAction chooseDndAction(AbstractDataSource *source, DataOfferInterface *offer)
|
||||
{
|
||||
if (offer->preferredDragAndDropAction().has_value()) {
|
||||
if (source->supportedDragAndDropActions().testFlag(*offer->preferredDragAndDropAction())) {
|
||||
return *offer->preferredDragAndDropAction();
|
||||
}
|
||||
}
|
||||
|
||||
if (offer->supportedDragAndDropActions().has_value()) {
|
||||
for (const auto &action : {DataDeviceManagerInterface::DnDAction::Copy, DataDeviceManagerInterface::DnDAction::Move, DataDeviceManagerInterface::DnDAction::Ask}) {
|
||||
if (source->supportedDragAndDropActions().testFlag(action) && offer->supportedDragAndDropActions()->testFlag(action)) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DataDeviceManagerInterface::DnDAction::None;
|
||||
}
|
||||
|
||||
void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 serial)
|
||||
{
|
||||
if (d->drag.surface) {
|
||||
|
@ -291,21 +310,7 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se
|
|||
if (offer) {
|
||||
offer->sendSourceActions();
|
||||
auto matchOffers = [dragSource, offer] {
|
||||
DataDeviceManagerInterface::DnDAction action{DataDeviceManagerInterface::DnDAction::None};
|
||||
if (dragSource->supportedDragAndDropActions().testFlag(offer->preferredDragAndDropAction())) {
|
||||
action = offer->preferredDragAndDropAction();
|
||||
} else {
|
||||
if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Copy;
|
||||
} else if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Move;
|
||||
} else if (dragSource->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)
|
||||
&& offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
|
||||
action = DataDeviceManagerInterface::DnDAction::Ask;
|
||||
}
|
||||
}
|
||||
const DataDeviceManagerInterface::DnDAction action = chooseDndAction(dragSource, offer);
|
||||
offer->dndAction(action);
|
||||
dragSource->dndAction(action);
|
||||
};
|
||||
|
|
|
@ -25,8 +25,8 @@ public:
|
|||
DataOfferInterface *q;
|
||||
QPointer<AbstractDataSource> source;
|
||||
|
||||
DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::None;
|
||||
DataDeviceManagerInterface::DnDAction preferredDnDAction = DataDeviceManagerInterface::DnDAction::None;
|
||||
std::optional<DataDeviceManagerInterface::DnDActions> supportedDnDActions = std::nullopt;
|
||||
std::optional<DataDeviceManagerInterface::DnDAction> preferredDnDAction = std::nullopt;
|
||||
|
||||
protected:
|
||||
void data_offer_destroy_resource(Resource *resource) override;
|
||||
|
@ -182,12 +182,12 @@ wl_resource *DataOfferInterface::resource() const
|
|||
return d->resource()->handle;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDActions DataOfferInterface::supportedDragAndDropActions() const
|
||||
std::optional<DataDeviceManagerInterface::DnDActions> DataOfferInterface::supportedDragAndDropActions() const
|
||||
{
|
||||
return d->supportedDnDActions;
|
||||
}
|
||||
|
||||
DataDeviceManagerInterface::DnDAction DataOfferInterface::preferredDragAndDropAction() const
|
||||
std::optional<DataDeviceManagerInterface::DnDAction> DataOfferInterface::preferredDragAndDropAction() const
|
||||
{
|
||||
return d->preferredDnDAction;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "datadevicemanager_interface.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
class DataDeviceInterface;
|
||||
|
@ -35,12 +37,12 @@ public:
|
|||
/**
|
||||
* @returns The Drag and Drop actions supported by this DataOfferInterface.
|
||||
*/
|
||||
DataDeviceManagerInterface::DnDActions supportedDragAndDropActions() const;
|
||||
std::optional<DataDeviceManagerInterface::DnDActions> supportedDragAndDropActions() const;
|
||||
|
||||
/**
|
||||
* @returns The preferred Drag and Drop action of this DataOfferInterface.
|
||||
*/
|
||||
DataDeviceManagerInterface::DnDAction preferredDragAndDropAction() const;
|
||||
std::optional<DataDeviceManagerInterface::DnDAction> preferredDragAndDropAction() const;
|
||||
|
||||
/**
|
||||
* This event indicates the @p action selected by the compositor after matching the
|
||||
|
|
Loading…
Reference in a new issue