KWin
Loading...
Searching...
No Matches
dataoffer.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3 SPDX-FileCopyrightText: 2020 David Edmundson <davidedmundson@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7#include "dataoffer.h"
8#include "datadevice.h"
9#include "datasource.h"
10
11// Qt
12#include <QPointer>
13#include <QStringList>
14// Wayland
15#include <qwayland-server-wayland.h>
16// system
17#include <unistd.h>
18
19namespace KWin
20{
21class DataOfferInterfacePrivate : public QtWaylandServer::wl_data_offer
22{
23public:
26 QPointer<AbstractDataSource> source;
27
28 std::optional<DataDeviceManagerInterface::DnDActions> supportedDnDActions = std::nullopt;
29 std::optional<DataDeviceManagerInterface::DnDAction> preferredDnDAction = std::nullopt;
30
31protected:
32 void data_offer_destroy_resource(Resource *resource) override;
33 void data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type) override;
34 void data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd) override;
35 void data_offer_destroy(Resource *resource) override;
36 void data_offer_finish(Resource *resource) override;
37 void data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action) override;
38};
39
41 : QtWaylandServer::wl_data_offer(resource)
42 , q(_q)
43 , source(_source)
44{
45 // defaults are set to sensible values for < version 3 interfaces
46 if (wl_resource_get_version(resource) < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
47 supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy | DataDeviceManagerInterface::DnDAction::Move;
48 preferredDnDAction = DataDeviceManagerInterface::DnDAction::Copy;
49 }
50}
51
52void DataOfferInterfacePrivate::data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type)
53{
54 if (!source) {
55 return;
56 }
57 source->accept(mime_type);
58}
59
60void DataOfferInterfacePrivate::data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd)
61{
62 if (!source) {
63 close(fd);
64 return;
65 }
66 source->requestData(mime_type, fd);
67}
68
69void DataOfferInterfacePrivate::data_offer_destroy(QtWaylandServer::wl_data_offer::Resource *resource)
70{
71 wl_resource_destroy(resource->handle);
72}
73
75{
76 if (!source) {
77 return;
78 }
79 source->dndFinished();
80 // TODO: It is a client error to perform other requests than wl_data_offer.destroy after this one
81}
82
83void DataOfferInterfacePrivate::data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action)
84{
85 // TODO: check it's drag and drop, otherwise send error
86 // verify that the no other actions are sent
87 if (dnd_actions
88 & ~(QtWaylandServer::wl_data_device_manager::dnd_action_copy | QtWaylandServer::wl_data_device_manager::dnd_action_move
89 | QtWaylandServer::wl_data_device_manager::dnd_action_ask)) {
90 wl_resource_post_error(resource->handle, error_invalid_action_mask, "Invalid action mask");
91 return;
92 }
93
94 if (preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_copy
95 && preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_move
96 && preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_ask
97 && preferred_action != QtWaylandServer::wl_data_device_manager::dnd_action_none) {
98 wl_resource_post_error(resource->handle, error_invalid_action, "Invalid preferred action");
99 return;
100 }
101
102 DataDeviceManagerInterface::DnDActions supportedActions;
103 if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
104 supportedActions |= DataDeviceManagerInterface::DnDAction::Copy;
105 }
106 if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_move) {
107 supportedActions |= DataDeviceManagerInterface::DnDAction::Move;
108 }
109 if (dnd_actions & QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
110 supportedActions |= DataDeviceManagerInterface::DnDAction::Ask;
111 }
112
113 DataDeviceManagerInterface::DnDAction preferredAction = DataDeviceManagerInterface::DnDAction::None;
114 if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_copy) {
115 preferredAction = DataDeviceManagerInterface::DnDAction::Copy;
116 } else if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_move) {
117 preferredAction = DataDeviceManagerInterface::DnDAction::Move;
118 } else if (preferred_action == QtWaylandServer::wl_data_device_manager::dnd_action_ask) {
119 preferredAction = DataDeviceManagerInterface::DnDAction::Ask;
120 }
121
122 if (supportedDnDActions != supportedActions || preferredDnDAction != preferredAction) {
123 supportedDnDActions = supportedActions;
124 preferredDnDAction = preferredAction;
126 }
127}
128
130{
131 if (!d->source) {
132 return;
133 }
134 if (d->resource()->version() < WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
135 return;
136 }
137 uint32_t wlActions = QtWaylandServer::wl_data_device_manager::dnd_action_none;
138 const auto actions = d->source->supportedDragAndDropActions();
139 if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
140 wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_copy;
141 }
142 if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
143 wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_move;
144 }
145 if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
146 wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_ask;
147 }
148 d->send_source_actions(wlActions);
149}
150
151void DataOfferInterfacePrivate::data_offer_destroy_resource(QtWaylandServer::wl_data_offer::Resource *resource)
152{
153 delete q;
154}
155
156DataOfferInterface::DataOfferInterface(AbstractDataSource *source, wl_resource *resource)
157 : QObject(nullptr)
158 , d(new DataOfferInterfacePrivate(source, this, resource))
159{
160 Q_ASSERT(source);
161 connect(source, &DataSourceInterface::mimeTypeOffered, this, [this](const QString &mimeType) {
162 d->send_offer(mimeType);
163 });
164}
165
167
169{
170 for (const QString &mimeType : d->source->mimeTypes()) {
171 d->send_offer(mimeType);
172 }
173}
174
176{
177 return d->resource()->handle;
178}
179
180std::optional<DataDeviceManagerInterface::DnDActions> DataOfferInterface::supportedDragAndDropActions() const
181{
182 return d->supportedDnDActions;
183}
184
185std::optional<DataDeviceManagerInterface::DnDAction> DataOfferInterface::preferredDragAndDropAction() const
186{
187 return d->preferredDnDAction;
188}
189
191{
192 if (d->resource()->version() < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
193 return;
194 }
195 uint32_t wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_none;
196 if (action == DataDeviceManagerInterface::DnDAction::Copy) {
197 wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_copy;
198 } else if (action == DataDeviceManagerInterface::DnDAction::Move) {
199 wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_move;
200 } else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
201 wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_ask;
202 }
203 d->send_action(wlAction);
204}
205}
206
207#include "moc_dataoffer.cpp"
The AbstractDataSource class abstracts the data that can be transferred to another client.
void mimeTypeOffered(const QString &)
Represents the Resource for the wl_data_offer interface.
Definition dataoffer.h:28
std::optional< DataDeviceManagerInterface::DnDAction > preferredDragAndDropAction() const
std::optional< DataDeviceManagerInterface::DnDActions > supportedDragAndDropActions() const
void dndAction(DataDeviceManagerInterface::DnDAction action)
wl_resource * resource() const
QPointer< AbstractDataSource > source
Definition dataoffer.cpp:26
void data_offer_finish(Resource *resource) override
Definition dataoffer.cpp:74
std::optional< DataDeviceManagerInterface::DnDActions > supportedDnDActions
Definition dataoffer.cpp:28
void data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type) override
Definition dataoffer.cpp:52
void data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action) override
Definition dataoffer.cpp:83
void data_offer_destroy(Resource *resource) override
Definition dataoffer.cpp:69
DataOfferInterfacePrivate(AbstractDataSource *source, DataOfferInterface *q, wl_resource *resource)
Definition dataoffer.cpp:40
void data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd) override
Definition dataoffer.cpp:60
void data_offer_destroy_resource(Resource *resource) override
std::optional< DataDeviceManagerInterface::DnDAction > preferredDnDAction
Definition dataoffer.cpp:29