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

KDE's Doxygen guidelines are available online.