KWayland

dataoffer_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "dataoffer_interface_p.h"
7 #include "datadevice_interface.h"
8 #include "datasource_interface.h"
9 // Qt
10 #include <QStringList>
11 // Wayland
12 #include <wayland-server.h>
13 // system
14 #include <unistd.h>
15 
16 namespace KWayland
17 {
18 namespace Server
19 {
20 
21 #ifndef K_DOXYGEN
22 const struct wl_data_offer_interface DataOfferInterface::Private::s_interface = {
23  acceptCallback,
24  receiveCallback,
25  resourceDestroyedCallback,
26  finishCallback,
27  setActionsCallback
28 };
29 #endif
30 
31 DataOfferInterface::Private::Private(DataSourceInterface *source, DataDeviceInterface *parentInterface, DataOfferInterface *q, wl_resource *parentResource)
32  : Resource::Private(q, nullptr, parentResource, &wl_data_offer_interface, &s_interface)
33  , source(source)
34  , dataDevice(parentInterface)
35 {
36  // TODO: connect to new selections
37 }
38 
39 DataOfferInterface::Private::~Private() = default;
40 
41 void DataOfferInterface::Private::acceptCallback(wl_client *client, wl_resource *resource, uint32_t serial, const char *mimeType)
42 {
43  Q_UNUSED(client)
44  Q_UNUSED(serial)
45  auto p = cast<Private>(resource);
46  if (!p->source) {
47  return;
48  }
49  p->source->accept(mimeType ? QString::fromUtf8(mimeType) : QString());
50 }
51 
52 void DataOfferInterface::Private::receiveCallback(wl_client *client, wl_resource *resource, const char *mimeType, int32_t fd)
53 {
54  Q_UNUSED(client)
55  cast<Private>(resource)->receive(QString::fromUtf8(mimeType), fd);
56 }
57 
58 void DataOfferInterface::Private::receive(const QString &mimeType, qint32 fd)
59 {
60  if (!source) {
61  close(fd);
62  return;
63  }
64  source->requestData(mimeType, fd);
65 }
66 
67 void DataOfferInterface::Private::finishCallback(wl_client *client, wl_resource *resource)
68 {
69  Q_UNUSED(client)
70  auto p = cast<Private>(resource);
71  if (!p->source) {
72  return;
73  }
74  p->source->dndFinished();
75  // TODO: It is a client error to perform other requests than wl_data_offer.destroy after this one
76 }
77 
78 void DataOfferInterface::Private::setActionsCallback(wl_client *client, wl_resource *resource, uint32_t dnd_actions, uint32_t preferred_action)
79 {
80  // TODO: check it's drag and drop, otherwise send error
81  Q_UNUSED(client)
82  DataDeviceManagerInterface::DnDActions supportedActions;
83  if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
84  supportedActions |= DataDeviceManagerInterface::DnDAction::Copy;
85  }
86  if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
87  supportedActions |= DataDeviceManagerInterface::DnDAction::Move;
88  }
89  if (dnd_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
90  supportedActions |= DataDeviceManagerInterface::DnDAction::Ask;
91  }
92  // verify that the no other actions are sent
93  if (dnd_actions & ~(WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)) {
94  wl_resource_post_error(resource, WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK, "Invalid action mask");
95  return;
96  }
97  if (preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY &&
98  preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE &&
99  preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK &&
100  preferred_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE) {
101  wl_resource_post_error(resource, WL_DATA_OFFER_ERROR_INVALID_ACTION, "Invalid preferred action");
102  return;
103  }
104 
105  DataDeviceManagerInterface::DnDAction preferredAction = DataDeviceManagerInterface::DnDAction::None;
106  if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) {
107  preferredAction = DataDeviceManagerInterface::DnDAction::Copy;
108  } else if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) {
109  preferredAction = DataDeviceManagerInterface::DnDAction::Move;
110  } else if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) {
111  preferredAction = DataDeviceManagerInterface::DnDAction::Ask;
112  }
113 
114  auto p = cast<Private>(resource);
115  p->supportedDnDActions = supportedActions;
116  p->preferredDnDAction = preferredAction;
117  emit p->q_func()->dragAndDropActionsChanged();
118 }
119 
120 void DataOfferInterface::Private::sendSourceActions()
121 {
122  if (!source) {
123  return;
124  }
125  if (wl_resource_get_version(resource) < WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
126  return;
127  }
128  uint32_t wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
129  const auto actions = source->supportedDragAndDropActions();
130  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Copy)) {
131  wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
132  }
133  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Move)) {
134  wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
135  }
136  if (actions.testFlag(DataDeviceManagerInterface::DnDAction::Ask)) {
137  wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
138  }
139  wl_data_offer_send_source_actions(resource, wlActions);
140 }
141 
142 DataOfferInterface::DataOfferInterface(DataSourceInterface *source, DataDeviceInterface *parentInterface, wl_resource *parentResource)
143  : Resource(new Private(source, parentInterface, this, parentResource))
144 {
145  Q_ASSERT(source);
146  connect(source, &DataSourceInterface::mimeTypeOffered, this,
147  [this](const QString &mimeType) {
148  Q_D();
149  if (!d->resource) {
150  return;
151  }
152  wl_data_offer_send_offer(d->resource, mimeType.toUtf8().constData());
153  }
154  );
155  QObject::connect(source, &QObject::destroyed, this,
156  [this] {
157  Q_D();
158  d->source = nullptr;
159  }
160  );
161 }
162 
163 DataOfferInterface::~DataOfferInterface() = default;
164 
165 void DataOfferInterface::sendAllOffers()
166 {
167  Q_D();
168  for (const QString &mimeType : d->source->mimeTypes()) {
169  wl_data_offer_send_offer(d->resource, mimeType.toUtf8().constData());
170  }
171 }
172 
173 DataOfferInterface::Private *DataOfferInterface::d_func() const
174 {
175  return reinterpret_cast<DataOfferInterface::Private*>(d.data());
176 }
177 
178 DataDeviceManagerInterface::DnDActions DataOfferInterface::supportedDragAndDropActions() const
179 {
180  Q_D();
181  return d->supportedDnDActions;
182 }
183 
184 DataDeviceManagerInterface::DnDAction DataOfferInterface::preferredDragAndDropAction() const
185 {
186  Q_D();
187  return d->preferredDnDAction;
188 }
189 
190 void DataOfferInterface::dndAction(DataDeviceManagerInterface::DnDAction action)
191 {
192  Q_D();
193  if (wl_resource_get_version(d->resource) < WL_DATA_OFFER_ACTION_SINCE_VERSION) {
194  return;
195  }
196  uint32_t wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
197  if (action == DataDeviceManagerInterface::DnDAction::Copy) {
198  wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
199  } else if (action == DataDeviceManagerInterface::DnDAction::Move ) {
200  wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
201  } else if (action == DataDeviceManagerInterface::DnDAction::Ask) {
202  wlAction = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
203  }
204  wl_data_offer_send_action(d->resource, wlAction);
205 }
206 
207 }
208 }
const QList< QKeySequence > & close()
QString fromUtf8(const char *str, int size)
const char * constData() const const
T * data() const const
DnDAction
Drag and Drop actions supported by the DataSourceInterface.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void destroyed(QObject *obj)
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:17 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.