blob: 83c0686eb78fba9bee32da0dc24faf71ead86f29 [file] [log] [blame]
Daniel Nicoaraa2b23512019-01-28 16:42:081// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/exo/wayland/wl_data_device_manager.h"
6
7#include <wayland-server-protocol-core.h>
8
9#include <algorithm>
10#include <memory>
11#include <string>
12#include <utility>
13
14#include "components/exo/data_device.h"
15#include "components/exo/data_device_delegate.h"
16#include "components/exo/data_offer.h"
17#include "components/exo/data_offer_delegate.h"
18#include "components/exo/data_source.h"
19#include "components/exo/data_source_delegate.h"
20#include "components/exo/display.h"
Fergus Dalldabc0b62019-07-26 07:16:2121#include "components/exo/wayland/serial_tracker.h"
Daniel Nicoaraa2b23512019-01-28 16:42:0822#include "components/exo/wayland/server_util.h"
Henrique Ferreiro1748fd12020-08-04 12:51:4623#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
Daniel Nicoaraa2b23512019-01-28 16:42:0824
25namespace exo {
26namespace wayland {
27namespace {
28
29uint32_t WaylandDataDeviceManagerDndAction(DndAction action) {
30 switch (action) {
31 case DndAction::kNone:
32 return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
33 case DndAction::kCopy:
34 return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
35 case DndAction::kMove:
36 return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
37 case DndAction::kAsk:
38 return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
39 }
40 NOTREACHED();
41}
42
43uint32_t WaylandDataDeviceManagerDndActions(
44 const base::flat_set<DndAction>& dnd_actions) {
45 uint32_t actions = 0;
46 for (DndAction action : dnd_actions)
47 actions |= WaylandDataDeviceManagerDndAction(action);
48 return actions;
49}
50
51DndAction DataDeviceManagerDndAction(uint32_t value) {
52 switch (value) {
53 case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
54 return DndAction::kNone;
55 case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
56 return DndAction::kCopy;
57 case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
58 return DndAction::kMove;
59 case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
60 return DndAction::kAsk;
61 default:
62 NOTREACHED();
63 return DndAction::kNone;
64 }
65}
66
67base::flat_set<DndAction> DataDeviceManagerDndActions(uint32_t value) {
68 base::flat_set<DndAction> actions;
69 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
70 actions.insert(DndAction::kCopy);
71 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
72 actions.insert(DndAction::kMove);
73 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
74 actions.insert(DndAction::kAsk);
75 return actions;
76}
77
78////////////////////////////////////////////////////////////////////////////////
79// wl_data_source_interface:
80
81class WaylandDataSourceDelegate : public DataSourceDelegate {
82 public:
matterchen43431472019-12-16 01:43:1083 explicit WaylandDataSourceDelegate(wl_client* client,
84 wl_resource* source)
85 : client_(client),
86 data_source_resource_(source) {}
Daniel Nicoaraa2b23512019-01-28 16:42:0887
88 // Overridden from DataSourceDelegate:
89 void OnDataSourceDestroying(DataSource* device) override { delete this; }
matterchen43431472019-12-16 01:43:1090 bool CanAcceptDataEventsForSurface(Surface* surface) const override {
91 return surface &&
92 wl_resource_get_client(GetSurfaceResource(surface)) == client_;
93 }
Fergus Dall2bcca7c72019-08-21 04:22:4194 void OnTarget(const base::Optional<std::string>& mime_type) override {
95 wl_data_source_send_target(data_source_resource_,
96 mime_type ? mime_type->c_str() : nullptr);
Daniel Nicoaraa2b23512019-01-28 16:42:0897 wl_client_flush(wl_resource_get_client(data_source_resource_));
98 }
99 void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
100 wl_data_source_send_send(data_source_resource_, mime_type.c_str(),
101 fd.get());
102 wl_client_flush(wl_resource_get_client(data_source_resource_));
103 }
104 void OnCancelled() override {
105 wl_data_source_send_cancelled(data_source_resource_);
106 wl_client_flush(wl_resource_get_client(data_source_resource_));
107 }
108 void OnDndDropPerformed() override {
109 if (wl_resource_get_version(data_source_resource_) >=
110 WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) {
111 wl_data_source_send_dnd_drop_performed(data_source_resource_);
112 wl_client_flush(wl_resource_get_client(data_source_resource_));
113 }
114 }
115 void OnDndFinished() override {
116 if (wl_resource_get_version(data_source_resource_) >=
117 WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
118 wl_data_source_send_dnd_finished(data_source_resource_);
119 wl_client_flush(wl_resource_get_client(data_source_resource_));
120 }
121 }
122 void OnAction(DndAction dnd_action) override {
123 if (wl_resource_get_version(data_source_resource_) >=
124 WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
125 wl_data_source_send_action(data_source_resource_,
126 WaylandDataDeviceManagerDndAction(dnd_action));
127 wl_client_flush(wl_resource_get_client(data_source_resource_));
128 }
129 }
130
131 private:
matterchen43431472019-12-16 01:43:10132 wl_client* const client_;
Daniel Nicoaraa2b23512019-01-28 16:42:08133 wl_resource* const data_source_resource_;
134
135 DISALLOW_COPY_AND_ASSIGN(WaylandDataSourceDelegate);
136};
137
138void data_source_offer(wl_client* client,
139 wl_resource* resource,
140 const char* mime_type) {
141 GetUserDataAs<DataSource>(resource)->Offer(mime_type);
142}
143
144void data_source_destroy(wl_client* client, wl_resource* resource) {
145 wl_resource_destroy(resource);
146}
147
148void data_source_set_actions(wl_client* client,
149 wl_resource* resource,
150 uint32_t dnd_actions) {
151 GetUserDataAs<DataSource>(resource)->SetActions(
152 DataDeviceManagerDndActions(dnd_actions));
153}
154
155const struct wl_data_source_interface data_source_implementation = {
156 data_source_offer, data_source_destroy, data_source_set_actions};
157
158////////////////////////////////////////////////////////////////////////////////
159// wl_data_offer_interface:
160
161class WaylandDataOfferDelegate : public DataOfferDelegate {
162 public:
163 explicit WaylandDataOfferDelegate(wl_resource* offer)
164 : data_offer_resource_(offer) {}
165
166 // Overridden from DataOfferDelegate:
167 void OnDataOfferDestroying(DataOffer* device) override { delete this; }
168 void OnOffer(const std::string& mime_type) override {
169 wl_data_offer_send_offer(data_offer_resource_, mime_type.c_str());
170 wl_client_flush(wl_resource_get_client(data_offer_resource_));
171 }
Joel Hockey99d26832021-03-09 08:29:01172 void OnSourceActions(
173 const base::flat_set<DndAction>& source_actions) override {
Daniel Nicoaraa2b23512019-01-28 16:42:08174 if (wl_resource_get_version(data_offer_resource_) >=
175 WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
176 wl_data_offer_send_source_actions(
177 data_offer_resource_,
178 WaylandDataDeviceManagerDndActions(source_actions));
Joel Hockey99d26832021-03-09 08:29:01179 wl_client_flush(wl_resource_get_client(data_offer_resource_));
Daniel Nicoaraa2b23512019-01-28 16:42:08180 }
Joel Hockey99d26832021-03-09 08:29:01181 }
182 void OnAction(DndAction action) override {
Daniel Nicoaraa2b23512019-01-28 16:42:08183 if (wl_resource_get_version(data_offer_resource_) >=
184 WL_DATA_OFFER_ACTION_SINCE_VERSION) {
185 wl_data_offer_send_action(data_offer_resource_,
186 WaylandDataDeviceManagerDndAction(action));
Henrique Ferreiro1c1052b2021-03-03 21:43:31187 wl_client_flush(wl_resource_get_client(data_offer_resource_));
Joel Hockey99d26832021-03-09 08:29:01188 }
Daniel Nicoaraa2b23512019-01-28 16:42:08189 }
190
191 private:
192 wl_resource* const data_offer_resource_;
193
194 DISALLOW_COPY_AND_ASSIGN(WaylandDataOfferDelegate);
195};
196
197void data_offer_accept(wl_client* client,
198 wl_resource* resource,
199 uint32_t serial,
200 const char* mime_type) {
Daichi Hironof29748c72019-02-07 22:02:04201 if (mime_type == nullptr) {
202 GetUserDataAs<DataOffer>(resource)->Accept(nullptr);
203 return;
204 }
205 const std::string mime_type_string(mime_type);
206 GetUserDataAs<DataOffer>(resource)->Accept(&mime_type_string);
Daniel Nicoaraa2b23512019-01-28 16:42:08207}
208
209void data_offer_receive(wl_client* client,
210 wl_resource* resource,
211 const char* mime_type,
212 int fd) {
213 GetUserDataAs<DataOffer>(resource)->Receive(mime_type, base::ScopedFD(fd));
214}
215
216void data_offer_destroy(wl_client* client, wl_resource* resource) {
217 wl_resource_destroy(resource);
218}
219
220void data_offer_finish(wl_client* client, wl_resource* resource) {
221 GetUserDataAs<DataOffer>(resource)->Finish();
222}
223
224void data_offer_set_actions(wl_client* client,
225 wl_resource* resource,
226 uint32_t dnd_actions,
227 uint32_t preferred_action) {
228 GetUserDataAs<DataOffer>(resource)->SetActions(
229 DataDeviceManagerDndActions(dnd_actions),
230 DataDeviceManagerDndAction(preferred_action));
231}
232
233const struct wl_data_offer_interface data_offer_implementation = {
Nicholas Hollingum3fcb1ef72019-07-28 08:03:49234 data_offer_accept, data_offer_receive, data_offer_destroy,
235 data_offer_finish, data_offer_set_actions};
Daniel Nicoaraa2b23512019-01-28 16:42:08236
237////////////////////////////////////////////////////////////////////////////////
238// wl_data_device_interface:
239
240class WaylandDataDeviceDelegate : public DataDeviceDelegate {
241 public:
Fergus Dalldabc0b62019-07-26 07:16:21242 WaylandDataDeviceDelegate(wl_client* client,
243 wl_resource* device_resource,
244 SerialTracker* serial_tracker)
245 : client_(client),
246 data_device_resource_(device_resource),
247 serial_tracker_(serial_tracker) {}
Daniel Nicoaraa2b23512019-01-28 16:42:08248
249 // Overridden from DataDeviceDelegate:
250 void OnDataDeviceDestroying(DataDevice* device) override { delete this; }
matterchen43431472019-12-16 01:43:10251 bool CanAcceptDataEventsForSurface(Surface* surface) const override {
Daniel Nicoaraa2b23512019-01-28 16:42:08252 return surface &&
253 wl_resource_get_client(GetSurfaceResource(surface)) == client_;
254 }
Joel Hockeyca98ffa42020-11-04 22:09:59255 DataOffer* OnDataOffer() override {
Daniel Nicoaraa2b23512019-01-28 16:42:08256 wl_resource* data_offer_resource =
257 wl_resource_create(client_, &wl_data_offer_interface,
258 wl_resource_get_version(data_device_resource_), 0);
259 std::unique_ptr<DataOffer> data_offer = std::make_unique<DataOffer>(
Joel Hockeyca98ffa42020-11-04 22:09:59260 new WaylandDataOfferDelegate(data_offer_resource));
Daniel Nicoaraa2b23512019-01-28 16:42:08261 SetDataOfferResource(data_offer.get(), data_offer_resource);
262 SetImplementation(data_offer_resource, &data_offer_implementation,
263 std::move(data_offer));
264
265 wl_data_device_send_data_offer(data_device_resource_, data_offer_resource);
266 wl_client_flush(client_);
267
268 return GetUserDataAs<DataOffer>(data_offer_resource);
269 }
270 void OnEnter(Surface* surface,
271 const gfx::PointF& point,
272 const DataOffer& data_offer) override {
273 wl_data_device_send_enter(
274 data_device_resource_,
Fergus Dalldabc0b62019-07-26 07:16:21275 serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
Daniel Nicoaraa2b23512019-01-28 16:42:08276 GetSurfaceResource(surface), wl_fixed_from_double(point.x()),
277 wl_fixed_from_double(point.y()), GetDataOfferResource(&data_offer));
278 wl_client_flush(client_);
279 }
280 void OnLeave() override {
281 wl_data_device_send_leave(data_device_resource_);
282 wl_client_flush(client_);
283 }
284 void OnMotion(base::TimeTicks time_stamp, const gfx::PointF& point) override {
285 wl_data_device_send_motion(
286 data_device_resource_, TimeTicksToMilliseconds(time_stamp),
287 wl_fixed_from_double(point.x()), wl_fixed_from_double(point.y()));
288 wl_client_flush(client_);
289 }
290 void OnDrop() override {
291 wl_data_device_send_drop(data_device_resource_);
292 wl_client_flush(client_);
293 }
294 void OnSelection(const DataOffer& data_offer) override {
295 wl_data_device_send_selection(data_device_resource_,
296 GetDataOfferResource(&data_offer));
297 wl_client_flush(client_);
298 }
299
Fergus Dall4466e9782019-07-26 08:04:13300 void StartDrag(DataDevice* data_device,
301 DataSource* source,
302 Surface* origin,
303 Surface* icon,
304 uint32_t serial) {
305 base::Optional<wayland::SerialTracker::EventType> event_type =
306 serial_tracker_->GetEventType(serial);
Tetsui Ohkubo541b75962020-06-23 04:24:37307 if (event_type == base::nullopt) {
308 LOG(ERROR) << "The serial passed to StartDrag does not exist.";
Tetsui Ohkubo541b75962020-06-23 04:24:37309 return;
310 }
Fergus Dall8c755bb2019-08-05 02:26:51311 if (event_type == wayland::SerialTracker::EventType::POINTER_BUTTON_DOWN &&
312 serial_tracker_->GetPointerDownSerial() == serial) {
David Munroe23c00e2020-10-22 23:34:06313 DCHECK(data_device);
Henrique Ferreiro1748fd12020-08-04 12:51:46314 data_device->StartDrag(source, origin, icon,
315 ui::mojom::DragEventSource::kMouse);
Fergus Dall8c755bb2019-08-05 02:26:51316 } else if (event_type == wayland::SerialTracker::EventType::TOUCH_DOWN &&
317 serial_tracker_->GetTouchDownSerial() == serial) {
David Munroe23c00e2020-10-22 23:34:06318 DCHECK(data_device);
Henrique Ferreiro1748fd12020-08-04 12:51:46319 data_device->StartDrag(source, origin, icon,
320 ui::mojom::DragEventSource::kTouch);
Fergus Dall4466e9782019-07-26 08:04:13321 } else {
Tetsui Ohkubo541b75962020-06-23 04:24:37322 LOG(ERROR) << "The serial passed to StartDrag does not match its "
323 "expected types.";
Fergus Dall4466e9782019-07-26 08:04:13324 }
325 }
326
Tetsui Ohkubo541b75962020-06-23 04:24:37327 void SetSelection(DataDevice* data_device,
328 DataSource* source,
329 uint32_t serial) {
330 base::Optional<wayland::SerialTracker::EventType> event_type =
331 serial_tracker_->GetEventType(serial);
332 if (event_type == base::nullopt) {
333 LOG(ERROR) << "The serial passed to SetSelection does not exist.";
Tetsui Ohkubo541b75962020-06-23 04:24:37334 return;
335 }
David Munroe23c00e2020-10-22 23:34:06336 DCHECK(data_device);
Tetsui Ohkubo541b75962020-06-23 04:24:37337 data_device->SetSelection(source);
338 }
339
Daniel Nicoaraa2b23512019-01-28 16:42:08340 private:
341 wl_client* const client_;
342 wl_resource* const data_device_resource_;
343
Fergus Dalldabc0b62019-07-26 07:16:21344 // Owned by Server, which always outlives this delegate.
345 SerialTracker* const serial_tracker_;
346
Daniel Nicoaraa2b23512019-01-28 16:42:08347 DISALLOW_COPY_AND_ASSIGN(WaylandDataDeviceDelegate);
348};
349
350void data_device_start_drag(wl_client* client,
351 wl_resource* resource,
352 wl_resource* source_resource,
353 wl_resource* origin_resource,
354 wl_resource* icon_resource,
355 uint32_t serial) {
Fergus Dall4466e9782019-07-26 08:04:13356 DataDevice* data_device = GetUserDataAs<DataDevice>(resource);
357 static_cast<WaylandDataDeviceDelegate*>(data_device->get_delegate())
358 ->StartDrag(
359 data_device,
360 source_resource ? GetUserDataAs<DataSource>(source_resource)
361 : nullptr,
362 GetUserDataAs<Surface>(origin_resource),
363 icon_resource ? GetUserDataAs<Surface>(icon_resource) : nullptr,
364 serial);
Daniel Nicoaraa2b23512019-01-28 16:42:08365}
366
367void data_device_set_selection(wl_client* client,
368 wl_resource* resource,
Tetsui Ohkubo541b75962020-06-23 04:24:37369 wl_resource* source_resource,
Daniel Nicoaraa2b23512019-01-28 16:42:08370 uint32_t serial) {
Tetsui Ohkubo541b75962020-06-23 04:24:37371 DataDevice* data_device = GetUserDataAs<DataDevice>(resource);
372 static_cast<WaylandDataDeviceDelegate*>(data_device->get_delegate())
373 ->SetSelection(data_device,
374 source_resource
375 ? GetUserDataAs<DataSource>(source_resource)
376 : nullptr,
377 serial);
Daniel Nicoaraa2b23512019-01-28 16:42:08378}
379
380void data_device_release(wl_client* client, wl_resource* resource) {
381 wl_resource_destroy(resource);
382}
383
384const struct wl_data_device_interface data_device_implementation = {
385 data_device_start_drag, data_device_set_selection, data_device_release};
386
387////////////////////////////////////////////////////////////////////////////////
388// wl_data_device_manager_interface:
389
390void data_device_manager_create_data_source(wl_client* client,
391 wl_resource* resource,
392 uint32_t id) {
393 wl_resource* data_source_resource = wl_resource_create(
394 client, &wl_data_source_interface, wl_resource_get_version(resource), id);
395 SetImplementation(data_source_resource, &data_source_implementation,
matterchen43431472019-12-16 01:43:10396 std::make_unique<DataSource>(new WaylandDataSourceDelegate(
397 client, data_source_resource)));
Daniel Nicoaraa2b23512019-01-28 16:42:08398}
399
400void data_device_manager_get_data_device(wl_client* client,
401 wl_resource* resource,
402 uint32_t id,
403 wl_resource* seat_resource) {
Fergus Dalldabc0b62019-07-26 07:16:21404 auto* data = GetUserDataAs<WaylandDataDeviceManager>(resource);
Daniel Nicoaraa2b23512019-01-28 16:42:08405 wl_resource* data_device_resource = wl_resource_create(
406 client, &wl_data_device_interface, wl_resource_get_version(resource), id);
Fergus Dalldabc0b62019-07-26 07:16:21407 SetImplementation(
408 data_device_resource, &data_device_implementation,
409 data->display->CreateDataDevice(new WaylandDataDeviceDelegate(
410 client, data_device_resource, data->serial_tracker)));
Daniel Nicoaraa2b23512019-01-28 16:42:08411}
412
413const struct wl_data_device_manager_interface
414 data_device_manager_implementation = {
415 data_device_manager_create_data_source,
416 data_device_manager_get_data_device};
417
418} // namespace
419
420void bind_data_device_manager(wl_client* client,
421 void* data,
422 uint32_t version,
423 uint32_t id) {
424 wl_resource* resource =
425 wl_resource_create(client, &wl_data_device_manager_interface,
426 std::min(version, kWlDataDeviceManagerVersion), id);
427 wl_resource_set_implementation(resource, &data_device_manager_implementation,
428 data, nullptr);
429}
430
431} // namespace wayland
432} // namespace exo