KWaylandServer

dataoffer_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3  SPDX-FileCopyrightText: 2020 David Edmundson <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 #include "dataoffer_interface.h"
8 #include "datadevice_interface.h"
9 #include "datasource_interface.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 
19 namespace KWaylandServer
20 {
21 class DataOfferInterfacePrivate : public QtWaylandServer::wl_data_offer
22 {
23 public:
24  DataOfferInterfacePrivate(AbstractDataSource *source, DataOfferInterface *q, wl_resource *resource);
25  DataOfferInterface *q;
27 
28  // defaults are set to sensible values for < version 3 interfaces
29  DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::Copy | DataDeviceManagerInterface::DnDAction::Move;
30  DataDeviceManagerInterface::DnDAction preferredDnDAction = DataDeviceManagerInterface::DnDAction::Copy;
31 
32 protected:
33  void data_offer_destroy_resource(Resource *resource) override;
34  void data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type) override;
35  void data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd) override;
36  void data_offer_destroy(Resource *resource) override;
37  void data_offer_finish(Resource *resource) override;
38  void data_offer_set_actions(Resource *resource, uint32_t dnd_actions, uint32_t preferred_action) override;
39 };
40 
41 DataOfferInterfacePrivate::DataOfferInterfacePrivate(AbstractDataSource *_source, DataOfferInterface *_q, wl_resource *resource)
42  : QtWaylandServer::wl_data_offer(resource)
43  , q(_q)
44  , source(_source)
45 {
46 }
47 
48 void DataOfferInterfacePrivate::data_offer_accept(Resource *resource, uint32_t serial, const QString &mime_type)
49 {
50  Q_UNUSED(resource)
51  Q_UNUSED(serial)
52  if (!source) {
53  return;
54  }
55  source->accept(mime_type);
56 }
57 
58 void DataOfferInterfacePrivate::data_offer_receive(Resource *resource, const QString &mime_type, int32_t fd)
59 {
60  Q_UNUSED(resource)
61  if (!source) {
62  close(fd);
63  return;
64  }
65  source->requestData(mime_type, fd);
66 }
67 
68 void DataOfferInterfacePrivate::data_offer_destroy(QtWaylandServer::wl_data_offer::Resource *resource)
69 {
70  wl_resource_destroy(resource->handle);
71 }
72 
73 void DataOfferInterfacePrivate::data_offer_finish(Resource *resource)
74 {
75  Q_UNUSED(resource)
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 
83 void 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  supportedDnDActions = supportedActions;
123  preferredDnDAction = preferredAction;
124  Q_EMIT q->dragAndDropActionsChanged();
125 }
126 
127 void DataOfferInterface::sendSourceActions()
128 {
129  if (!d->source) {
130  return;
131  }
132  if (d->resource()->version() < WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
133  return;
134  }
135  uint32_t wlActions = QtWaylandServer::wl_data_device_manager::dnd_action_none;
136  const auto actions = d->source->supportedDragAndDropActions();
137  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
138  wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_copy;
139  }
140  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
141  wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_move;
142  }
143  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
144  wlActions |= QtWaylandServer::wl_data_device_manager::dnd_action_ask;
145  }
146  d->send_source_actions(wlActions);
147 }
148 
149 void DataOfferInterfacePrivate::data_offer_destroy_resource(QtWaylandServer::wl_data_offer::Resource *resource)
150 {
151  Q_UNUSED(resource)
152  delete q;
153 }
154 
155 DataOfferInterface::DataOfferInterface(AbstractDataSource *source, wl_resource *resource)
156  : QObject(nullptr)
157  , d(new DataOfferInterfacePrivate(source, this, resource))
158 {
159  Q_ASSERT(source);
160  connect(source, &DataSourceInterface::mimeTypeOffered, this, [this](const QString &mimeType) {
161  d->send_offer(mimeType);
162  });
163 }
164 
165 DataOfferInterface::~DataOfferInterface() = default;
166 
167 void DataOfferInterface::sendAllOffers()
168 {
169  for (const QString &mimeType : d->source->mimeTypes()) {
170  d->send_offer(mimeType);
171  }
172 }
173 
174 wl_resource *DataOfferInterface::resource() const
175 {
176  return d->resource()->handle;
177 }
178 
180 {
181  return d->supportedDnDActions;
182 }
183 
185 {
186  return d->preferredDnDAction;
187 }
188 
190 {
191  if (d->resource()->version() < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
192  return;
193  }
194  uint32_t wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_none;
195  if (action == DataDeviceManagerInterface::DnDAction::Copy) {
196  wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_copy;
197  } else if (action == DataDeviceManagerInterface::DnDAction::Move) {
198  wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_move;
199  } else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
200  wlAction = QtWaylandServer::wl_data_device_manager::dnd_action_ask;
201  }
202  d->send_action(wlAction);
203 }
204 
205 }
const QList< QKeySequence > & close()
DnDAction
Drag and Drop actions supported by the DataSourceInterface.
DataDeviceManagerInterface::DnDAction preferredDragAndDropAction() const
DataDeviceManagerInterface::DnDActions supportedDragAndDropActions() const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void dndAction(DataDeviceManagerInterface::DnDAction action)
This event indicates the action selected by the compositor after matching the source/destination side...
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 23:08:43 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.