blob: dcdaa27a833c2bb472714e441e1ac18679367b5c [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"
23
24namespace exo {
25namespace wayland {
26namespace {
27
28uint32_t WaylandDataDeviceManagerDndAction(DndAction action) {
29 switch (action) {
30 case DndAction::kNone:
31 return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
32 case DndAction::kCopy:
33 return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
34 case DndAction::kMove:
35 return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
36 case DndAction::kAsk:
37 return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
38 }
39 NOTREACHED();
40}
41
42uint32_t WaylandDataDeviceManagerDndActions(
43 const base::flat_set<DndAction>& dnd_actions) {
44 uint32_t actions = 0;
45 for (DndAction action : dnd_actions)
46 actions |= WaylandDataDeviceManagerDndAction(action);
47 return actions;
48}
49
50DndAction DataDeviceManagerDndAction(uint32_t value) {
51 switch (value) {
52 case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
53 return DndAction::kNone;
54 case WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY:
55 return DndAction::kCopy;
56 case WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE:
57 return DndAction::kMove;
58 case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
59 return DndAction::kAsk;
60 default:
61 NOTREACHED();
62 return DndAction::kNone;
63 }
64}
65
66base::flat_set<DndAction> DataDeviceManagerDndActions(uint32_t value) {
67 base::flat_set<DndAction> actions;
68 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
69 actions.insert(DndAction::kCopy);
70 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
71 actions.insert(DndAction::kMove);
72 if (value & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
73 actions.insert(DndAction::kAsk);
74 return actions;
75}
76
77////////////////////////////////////////////////////////////////////////////////
78// wl_data_source_interface:
79
80class WaylandDataSourceDelegate : public DataSourceDelegate {
81 public:
82 explicit WaylandDataSourceDelegate(wl_resource* source)
83 : data_source_resource_(source) {}
84
85 // Overridden from DataSourceDelegate:
86 void OnDataSourceDestroying(DataSource* device) override { delete this; }
87 void OnTarget(const std::string& mime_type) override {
88 wl_data_source_send_target(data_source_resource_, mime_type.c_str());
89 wl_client_flush(wl_resource_get_client(data_source_resource_));
90 }
91 void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
92 wl_data_source_send_send(data_source_resource_, mime_type.c_str(),
93 fd.get());
94 wl_client_flush(wl_resource_get_client(data_source_resource_));
95 }
96 void OnCancelled() override {
97 wl_data_source_send_cancelled(data_source_resource_);
98 wl_client_flush(wl_resource_get_client(data_source_resource_));
99 }
100 void OnDndDropPerformed() override {
101 if (wl_resource_get_version(data_source_resource_) >=
102 WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) {
103 wl_data_source_send_dnd_drop_performed(data_source_resource_);
104 wl_client_flush(wl_resource_get_client(data_source_resource_));
105 }
106 }
107 void OnDndFinished() override {
108 if (wl_resource_get_version(data_source_resource_) >=
109 WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
110 wl_data_source_send_dnd_finished(data_source_resource_);
111 wl_client_flush(wl_resource_get_client(data_source_resource_));
112 }
113 }
114 void OnAction(DndAction dnd_action) override {
115 if (wl_resource_get_version(data_source_resource_) >=
116 WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
117 wl_data_source_send_action(data_source_resource_,
118 WaylandDataDeviceManagerDndAction(dnd_action));
119 wl_client_flush(wl_resource_get_client(data_source_resource_));
120 }
121 }
122
123 private:
124 wl_resource* const data_source_resource_;
125
126 DISALLOW_COPY_AND_ASSIGN(WaylandDataSourceDelegate);
127};
128
129void data_source_offer(wl_client* client,
130 wl_resource* resource,
131 const char* mime_type) {
132 GetUserDataAs<DataSource>(resource)->Offer(mime_type);
133}
134
135void data_source_destroy(wl_client* client, wl_resource* resource) {
136 wl_resource_destroy(resource);
137}
138
139void data_source_set_actions(wl_client* client,
140 wl_resource* resource,
141 uint32_t dnd_actions) {
142 GetUserDataAs<DataSource>(resource)->SetActions(
143 DataDeviceManagerDndActions(dnd_actions));
144}
145
146const struct wl_data_source_interface data_source_implementation = {
147 data_source_offer, data_source_destroy, data_source_set_actions};
148
149////////////////////////////////////////////////////////////////////////////////
150// wl_data_offer_interface:
151
152class WaylandDataOfferDelegate : public DataOfferDelegate {
153 public:
154 explicit WaylandDataOfferDelegate(wl_resource* offer)
155 : data_offer_resource_(offer) {}
156
157 // Overridden from DataOfferDelegate:
158 void OnDataOfferDestroying(DataOffer* device) override { delete this; }
159 void OnOffer(const std::string& mime_type) override {
160 wl_data_offer_send_offer(data_offer_resource_, mime_type.c_str());
161 wl_client_flush(wl_resource_get_client(data_offer_resource_));
162 }
163 void OnSourceActions(
164 const base::flat_set<DndAction>& source_actions) override {
165 if (wl_resource_get_version(data_offer_resource_) >=
166 WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
167 wl_data_offer_send_source_actions(
168 data_offer_resource_,
169 WaylandDataDeviceManagerDndActions(source_actions));
170 wl_client_flush(wl_resource_get_client(data_offer_resource_));
171 }
172 }
173 void OnAction(DndAction action) override {
174 if (wl_resource_get_version(data_offer_resource_) >=
175 WL_DATA_OFFER_ACTION_SINCE_VERSION) {
176 wl_data_offer_send_action(data_offer_resource_,
177 WaylandDataDeviceManagerDndAction(action));
178 wl_client_flush(wl_resource_get_client(data_offer_resource_));
179 }
180 }
181
182 private:
183 wl_resource* const data_offer_resource_;
184
185 DISALLOW_COPY_AND_ASSIGN(WaylandDataOfferDelegate);
186};
187
188void data_offer_accept(wl_client* client,
189 wl_resource* resource,
190 uint32_t serial,
191 const char* mime_type) {
Daichi Hironof29748c72019-02-07 22:02:04192 if (mime_type == nullptr) {
193 GetUserDataAs<DataOffer>(resource)->Accept(nullptr);
194 return;
195 }
196 const std::string mime_type_string(mime_type);
197 GetUserDataAs<DataOffer>(resource)->Accept(&mime_type_string);
Daniel Nicoaraa2b23512019-01-28 16:42:08198}
199
200void data_offer_receive(wl_client* client,
201 wl_resource* resource,
202 const char* mime_type,
203 int fd) {
204 GetUserDataAs<DataOffer>(resource)->Receive(mime_type, base::ScopedFD(fd));
205}
206
207void data_offer_destroy(wl_client* client, wl_resource* resource) {
208 wl_resource_destroy(resource);
209}
210
211void data_offer_finish(wl_client* client, wl_resource* resource) {
212 GetUserDataAs<DataOffer>(resource)->Finish();
213}
214
215void data_offer_set_actions(wl_client* client,
216 wl_resource* resource,
217 uint32_t dnd_actions,
218 uint32_t preferred_action) {
219 GetUserDataAs<DataOffer>(resource)->SetActions(
220 DataDeviceManagerDndActions(dnd_actions),
221 DataDeviceManagerDndAction(preferred_action));
222}
223
224const struct wl_data_offer_interface data_offer_implementation = {
225 data_offer_accept, data_offer_receive, data_offer_finish,
226 data_offer_destroy, data_offer_set_actions};
227
228////////////////////////////////////////////////////////////////////////////////
229// wl_data_device_interface:
230
231class WaylandDataDeviceDelegate : public DataDeviceDelegate {
232 public:
Fergus Dalldabc0b62019-07-26 07:16:21233 WaylandDataDeviceDelegate(wl_client* client,
234 wl_resource* device_resource,
235 SerialTracker* serial_tracker)
236 : client_(client),
237 data_device_resource_(device_resource),
238 serial_tracker_(serial_tracker) {}
Daniel Nicoaraa2b23512019-01-28 16:42:08239
240 // Overridden from DataDeviceDelegate:
241 void OnDataDeviceDestroying(DataDevice* device) override { delete this; }
242 bool CanAcceptDataEventsForSurface(Surface* surface) override {
243 return surface &&
244 wl_resource_get_client(GetSurfaceResource(surface)) == client_;
245 }
Fergus Dall86907492019-05-16 04:03:21246 DataOffer* OnDataOffer(DataOffer::Purpose purpose) override {
Daniel Nicoaraa2b23512019-01-28 16:42:08247 wl_resource* data_offer_resource =
248 wl_resource_create(client_, &wl_data_offer_interface,
249 wl_resource_get_version(data_device_resource_), 0);
250 std::unique_ptr<DataOffer> data_offer = std::make_unique<DataOffer>(
Fergus Dall86907492019-05-16 04:03:21251 new WaylandDataOfferDelegate(data_offer_resource), purpose);
Daniel Nicoaraa2b23512019-01-28 16:42:08252 SetDataOfferResource(data_offer.get(), data_offer_resource);
253 SetImplementation(data_offer_resource, &data_offer_implementation,
254 std::move(data_offer));
255
256 wl_data_device_send_data_offer(data_device_resource_, data_offer_resource);
257 wl_client_flush(client_);
258
259 return GetUserDataAs<DataOffer>(data_offer_resource);
260 }
261 void OnEnter(Surface* surface,
262 const gfx::PointF& point,
263 const DataOffer& data_offer) override {
264 wl_data_device_send_enter(
265 data_device_resource_,
Fergus Dalldabc0b62019-07-26 07:16:21266 serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT),
Daniel Nicoaraa2b23512019-01-28 16:42:08267 GetSurfaceResource(surface), wl_fixed_from_double(point.x()),
268 wl_fixed_from_double(point.y()), GetDataOfferResource(&data_offer));
269 wl_client_flush(client_);
270 }
271 void OnLeave() override {
272 wl_data_device_send_leave(data_device_resource_);
273 wl_client_flush(client_);
274 }
275 void OnMotion(base::TimeTicks time_stamp, const gfx::PointF& point) override {
276 wl_data_device_send_motion(
277 data_device_resource_, TimeTicksToMilliseconds(time_stamp),
278 wl_fixed_from_double(point.x()), wl_fixed_from_double(point.y()));
279 wl_client_flush(client_);
280 }
281 void OnDrop() override {
282 wl_data_device_send_drop(data_device_resource_);
283 wl_client_flush(client_);
284 }
285 void OnSelection(const DataOffer& data_offer) override {
286 wl_data_device_send_selection(data_device_resource_,
287 GetDataOfferResource(&data_offer));
288 wl_client_flush(client_);
289 }
290
291 private:
292 wl_client* const client_;
293 wl_resource* const data_device_resource_;
294
Fergus Dalldabc0b62019-07-26 07:16:21295 // Owned by Server, which always outlives this delegate.
296 SerialTracker* const serial_tracker_;
297
Daniel Nicoaraa2b23512019-01-28 16:42:08298 DISALLOW_COPY_AND_ASSIGN(WaylandDataDeviceDelegate);
299};
300
301void data_device_start_drag(wl_client* client,
302 wl_resource* resource,
303 wl_resource* source_resource,
304 wl_resource* origin_resource,
305 wl_resource* icon_resource,
306 uint32_t serial) {
307 GetUserDataAs<DataDevice>(resource)->StartDrag(
308 source_resource ? GetUserDataAs<DataSource>(source_resource) : nullptr,
309 GetUserDataAs<Surface>(origin_resource),
310 icon_resource ? GetUserDataAs<Surface>(icon_resource) : nullptr, serial);
311}
312
313void data_device_set_selection(wl_client* client,
314 wl_resource* resource,
315 wl_resource* data_source,
316 uint32_t serial) {
317 GetUserDataAs<DataDevice>(resource)->SetSelection(
318 data_source ? GetUserDataAs<DataSource>(data_source) : nullptr, serial);
319}
320
321void data_device_release(wl_client* client, wl_resource* resource) {
322 wl_resource_destroy(resource);
323}
324
325const struct wl_data_device_interface data_device_implementation = {
326 data_device_start_drag, data_device_set_selection, data_device_release};
327
328////////////////////////////////////////////////////////////////////////////////
329// wl_data_device_manager_interface:
330
331void data_device_manager_create_data_source(wl_client* client,
332 wl_resource* resource,
333 uint32_t id) {
334 wl_resource* data_source_resource = wl_resource_create(
335 client, &wl_data_source_interface, wl_resource_get_version(resource), id);
336 SetImplementation(data_source_resource, &data_source_implementation,
337 std::make_unique<DataSource>(
338 new WaylandDataSourceDelegate(data_source_resource)));
339}
340
341void data_device_manager_get_data_device(wl_client* client,
342 wl_resource* resource,
343 uint32_t id,
344 wl_resource* seat_resource) {
Fergus Dalldabc0b62019-07-26 07:16:21345 auto* data = GetUserDataAs<WaylandDataDeviceManager>(resource);
Daniel Nicoaraa2b23512019-01-28 16:42:08346 wl_resource* data_device_resource = wl_resource_create(
347 client, &wl_data_device_interface, wl_resource_get_version(resource), id);
Fergus Dalldabc0b62019-07-26 07:16:21348 SetImplementation(
349 data_device_resource, &data_device_implementation,
350 data->display->CreateDataDevice(new WaylandDataDeviceDelegate(
351 client, data_device_resource, data->serial_tracker)));
Daniel Nicoaraa2b23512019-01-28 16:42:08352}
353
354const struct wl_data_device_manager_interface
355 data_device_manager_implementation = {
356 data_device_manager_create_data_source,
357 data_device_manager_get_data_device};
358
359} // namespace
360
361void bind_data_device_manager(wl_client* client,
362 void* data,
363 uint32_t version,
364 uint32_t id) {
365 wl_resource* resource =
366 wl_resource_create(client, &wl_data_device_manager_interface,
367 std::min(version, kWlDataDeviceManagerVersion), id);
368 wl_resource_set_implementation(resource, &data_device_manager_implementation,
369 data, nullptr);
370}
371
372} // namespace wayland
373} // namespace exo