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