blob: 865d749794fad3190c938da68c95bdfe14225d6d [file] [log] [blame]
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001/*
2 * Copyright © 2011 Kristian Høgsberg
3 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07004 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
Kristian Høgsberg2158a882013-04-18 15:07:39 -040011 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070012 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
Kristian Høgsberg2158a882013-04-18 15:07:39 -040024 */
25
Daniel Stone8e7a8bd2013-08-15 01:10:24 +010026#include "config.h"
27
Kristian Høgsberg2158a882013-04-18 15:07:39 -040028#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030031#include <stdint.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040032#include <stdio.h>
Jason Ekstranda7af7042013-10-12 22:38:11 -050033#include <assert.h>
Kristian Høgsberg2158a882013-04-18 15:07:39 -040034
Pekka Paalanen3d5d9472019-03-28 16:28:47 +020035#include <libweston/libweston.h>
Jon Cruz867d50e2015-06-15 15:37:10 -070036#include "shared/helpers.h"
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020037#include "shared/timespec-util.h"
Kristian Høgsberg2158a882013-04-18 15:07:39 -040038
Kristian Høgsberg054c50a2013-05-08 15:27:47 -040039struct weston_drag {
40 struct wl_client *client;
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -070041 struct weston_data_source *data_source;
Kristian Høgsberg054c50a2013-05-08 15:27:47 -040042 struct wl_listener data_source_listener;
Jason Ekstranda7af7042013-10-12 22:38:11 -050043 struct weston_view *focus;
Kristian Høgsberg054c50a2013-05-08 15:27:47 -040044 struct wl_resource *focus_resource;
45 struct wl_listener focus_listener;
Jason Ekstranda7af7042013-10-12 22:38:11 -050046 struct weston_view *icon;
Kristian Høgsbergc43aad12013-05-08 15:30:42 -040047 struct wl_listener icon_destroy_listener;
Kristian Høgsberg054c50a2013-05-08 15:27:47 -040048 int32_t dx, dy;
Carlos Garnachob2889882016-01-15 21:14:26 +010049 struct weston_keyboard_grab keyboard_grab;
Kristian Høgsberg054c50a2013-05-08 15:27:47 -040050};
51
Xiong Zhangfd51e7b2013-11-25 18:42:49 +080052struct weston_pointer_drag {
53 struct weston_drag base;
54 struct weston_pointer_grab grab;
55};
56
57struct weston_touch_drag {
58 struct weston_drag base;
59 struct weston_touch_grab grab;
60};
61
Carlos Garnacho9c931792016-01-18 23:52:12 +010062#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
63 WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
64 WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
65
Kristian Høgsberg2158a882013-04-18 15:07:39 -040066static void
67data_offer_accept(struct wl_client *client, struct wl_resource *resource,
68 uint32_t serial, const char *mime_type)
69{
Kristian Høgsberg5e76a492013-07-25 16:09:37 -070070 struct weston_data_offer *offer = wl_resource_get_user_data(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040071
Carlos Garnacho78d4bf92016-01-15 21:14:23 +010072 /* Protect against untimely calls from older data offers */
73 if (!offer->source || offer != offer->source->offer)
74 return;
75
Kristian Høgsberg2158a882013-04-18 15:07:39 -040076 /* FIXME: Check that client is currently focused by the input
77 * device that is currently dragging this data source. Should
78 * this be a wl_data_device request? */
79
Carlos Garnacho78d4bf92016-01-15 21:14:23 +010080 offer->source->accept(offer->source, serial, mime_type);
81 offer->source->accepted = mime_type != NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -040082}
83
84static void
85data_offer_receive(struct wl_client *client, struct wl_resource *resource,
86 const char *mime_type, int32_t fd)
87{
Kristian Høgsberg5e76a492013-07-25 16:09:37 -070088 struct weston_data_offer *offer = wl_resource_get_user_data(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -040089
Carlos Garnacho78d4bf92016-01-15 21:14:23 +010090 if (offer->source && offer == offer->source->offer)
Kristian Høgsberg2158a882013-04-18 15:07:39 -040091 offer->source->send(offer->source, mime_type, fd);
92 else
93 close(fd);
94}
95
96static void
97data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
98{
99 wl_resource_destroy(resource);
100}
101
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100102static void
103data_source_notify_finish(struct weston_data_source *source)
104{
Carlos Garnacho4061e2b2016-02-01 20:28:16 +0100105 if (!source->actions_set)
106 return;
107
Carlos Garnacho9c931792016-01-18 23:52:12 +0100108 if (source->offer->in_ask &&
109 wl_resource_get_version(source->resource) >=
110 WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
111 wl_data_source_send_action(source->resource,
112 source->current_dnd_action);
113 }
114
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100115 if (wl_resource_get_version(source->resource) >=
116 WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
117 wl_data_source_send_dnd_finished(source->resource);
118 }
119
120 source->offer = NULL;
121}
122
Carlos Garnacho9c931792016-01-18 23:52:12 +0100123static uint32_t
124data_offer_choose_action(struct weston_data_offer *offer)
125{
126 uint32_t available_actions, preferred_action = 0;
127 uint32_t source_actions, offer_actions;
128
129 if (wl_resource_get_version(offer->resource) >=
130 WL_DATA_OFFER_ACTION_SINCE_VERSION) {
131 offer_actions = offer->dnd_actions;
132 preferred_action = offer->preferred_dnd_action;
133 } else {
134 offer_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
135 }
136
137 if (wl_resource_get_version(offer->source->resource) >=
138 WL_DATA_SOURCE_ACTION_SINCE_VERSION)
139 source_actions = offer->source->dnd_actions;
140 else
141 source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
142
143 available_actions = offer_actions & source_actions;
144
145 if (!available_actions)
146 return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
147
Carlos Garnachob2889882016-01-15 21:14:26 +0100148 if (offer->source->seat &&
149 offer->source->compositor_action & available_actions)
150 return offer->source->compositor_action;
151
Carlos Garnacho9c931792016-01-18 23:52:12 +0100152 /* If the dest side has a preferred DnD action, use it */
153 if ((preferred_action & available_actions) != 0)
154 return preferred_action;
155
156 /* Use the first found action, in bit order */
157 return 1 << (ffs(available_actions) - 1);
158}
159
160static void
161data_offer_update_action(struct weston_data_offer *offer)
162{
163 uint32_t action;
164
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +0800165 if (!offer->source)
Carlos Garnacho9c931792016-01-18 23:52:12 +0100166 return;
167
168 action = data_offer_choose_action(offer);
169
170 if (offer->source->current_dnd_action == action)
171 return;
172
173 offer->source->current_dnd_action = action;
174
175 if (offer->in_ask)
176 return;
177
178 if (wl_resource_get_version(offer->source->resource) >=
179 WL_DATA_SOURCE_ACTION_SINCE_VERSION)
180 wl_data_source_send_action(offer->source->resource, action);
181
182 if (wl_resource_get_version(offer->resource) >=
183 WL_DATA_OFFER_ACTION_SINCE_VERSION)
184 wl_data_offer_send_action(offer->resource, action);
185}
186
187static void
188data_offer_set_actions(struct wl_client *client,
189 struct wl_resource *resource,
190 uint32_t dnd_actions, uint32_t preferred_action)
191{
192 struct weston_data_offer *offer = wl_resource_get_user_data(resource);
193
194 if (dnd_actions & ~ALL_ACTIONS) {
195 wl_resource_post_error(offer->resource,
196 WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK,
197 "invalid action mask %x", dnd_actions);
198 return;
199 }
200
201 if (preferred_action &&
202 (!(preferred_action & dnd_actions) ||
203 __builtin_popcount(preferred_action) > 1)) {
204 wl_resource_post_error(offer->resource,
205 WL_DATA_OFFER_ERROR_INVALID_ACTION,
206 "invalid action %x", preferred_action);
207 return;
208 }
209
210 offer->dnd_actions = dnd_actions;
211 offer->preferred_dnd_action = preferred_action;
212 data_offer_update_action(offer);
213}
214
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100215static void
216data_offer_finish(struct wl_client *client, struct wl_resource *resource)
217{
218 struct weston_data_offer *offer = wl_resource_get_user_data(resource);
219
220 if (!offer->source || offer->source->offer != offer)
221 return;
222
Harish Krupo737ac0d2019-04-19 22:06:37 +0530223 if (offer->source->set_selection) {
224 wl_resource_post_error(offer->resource,
225 WL_DATA_OFFER_ERROR_INVALID_FINISH,
226 "finish only valid for drag n drop");
227 return;
228 }
229
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100230 /* Disallow finish while we have a grab driving drag-and-drop, or
231 * if the negotiation is not at the right stage
232 */
233 if (offer->source->seat ||
234 !offer->source->accepted) {
235 wl_resource_post_error(offer->resource,
236 WL_DATA_OFFER_ERROR_INVALID_FINISH,
237 "premature finish request");
238 return;
239 }
240
Carlos Garnacho9c931792016-01-18 23:52:12 +0100241 switch (offer->source->current_dnd_action) {
242 case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
243 case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
244 wl_resource_post_error(offer->resource,
245 WL_DATA_OFFER_ERROR_INVALID_OFFER,
246 "offer finished with an invalid action");
247 return;
248 default:
249 break;
250 }
251
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100252 data_source_notify_finish(offer->source);
253}
254
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400255static const struct wl_data_offer_interface data_offer_interface = {
256 data_offer_accept,
257 data_offer_receive,
258 data_offer_destroy,
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100259 data_offer_finish,
Carlos Garnacho9c931792016-01-18 23:52:12 +0100260 data_offer_set_actions,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400261};
262
263static void
264destroy_data_offer(struct wl_resource *resource)
265{
Kristian Høgsberg5e76a492013-07-25 16:09:37 -0700266 struct weston_data_offer *offer = wl_resource_get_user_data(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400267
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100268 if (!offer->source)
269 goto out;
270
271 wl_list_remove(&offer->source_destroy_listener.link);
272
273 if (offer->source->offer != offer)
274 goto out;
275
276 /* If the drag destination has version < 3, wl_data_offer.finish
277 * won't be called, so do this here as a safety net, because
278 * we still want the version >=3 drag source to be happy.
279 */
280 if (wl_resource_get_version(offer->resource) <
281 WL_DATA_OFFER_ACTION_SINCE_VERSION) {
282 data_source_notify_finish(offer->source);
Carlos Garnacho4061e2b2016-02-01 20:28:16 +0100283 } else if (offer->source->resource &&
284 wl_resource_get_version(offer->source->resource) >=
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100285 WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
286 wl_data_source_send_cancelled(offer->source->resource);
287 }
288
289 offer->source->offer = NULL;
290out:
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400291 free(offer);
292}
293
294static void
295destroy_offer_data_source(struct wl_listener *listener, void *data)
296{
Kristian Høgsberg5e76a492013-07-25 16:09:37 -0700297 struct weston_data_offer *offer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400298
Kristian Høgsberg5e76a492013-07-25 16:09:37 -0700299 offer = container_of(listener, struct weston_data_offer,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400300 source_destroy_listener);
301
302 offer->source = NULL;
303}
304
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +0800305static struct weston_data_offer *
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -0700306weston_data_source_send_offer(struct weston_data_source *source,
307 struct wl_resource *target)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400308{
Kristian Høgsberg5e76a492013-07-25 16:09:37 -0700309 struct weston_data_offer *offer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400310 char **p;
311
312 offer = malloc(sizeof *offer);
313 if (offer == NULL)
314 return NULL;
315
Jason Ekstranda85118c2013-06-27 20:17:02 -0500316 offer->resource =
317 wl_resource_create(wl_resource_get_client(target),
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100318 &wl_data_offer_interface,
319 wl_resource_get_version(target), 0);
Kristian Høgsberg3c30f0f2013-08-06 10:24:04 -0700320 if (offer->resource == NULL) {
321 free(offer);
322 return NULL;
323 }
324
Jason Ekstranda85118c2013-06-27 20:17:02 -0500325 wl_resource_set_implementation(offer->resource, &data_offer_interface,
326 offer, destroy_data_offer);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400327
Carlos Garnacho9c931792016-01-18 23:52:12 +0100328 offer->in_ask = false;
329 offer->dnd_actions = 0;
330 offer->preferred_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400331 offer->source = source;
332 offer->source_destroy_listener.notify = destroy_offer_data_source;
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -0500333 wl_signal_add(&source->destroy_signal,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400334 &offer->source_destroy_listener);
335
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -0500336 wl_data_device_send_data_offer(target, offer->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400337
338 wl_array_for_each(p, &source->mime_types)
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -0500339 wl_data_offer_send_offer(offer->resource, *p);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400340
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100341 source->offer = offer;
342 source->accepted = false;
343
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +0800344 return offer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400345}
346
347static void
348data_source_offer(struct wl_client *client,
349 struct wl_resource *resource,
350 const char *type)
351{
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -0700352 struct weston_data_source *source =
353 wl_resource_get_user_data(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400354 char **p;
355
356 p = wl_array_add(&source->mime_types, sizeof *p);
357 if (p)
358 *p = strdup(type);
359 if (!p || !*p)
360 wl_resource_post_no_memory(resource);
361}
362
363static void
364data_source_destroy(struct wl_client *client, struct wl_resource *resource)
365{
366 wl_resource_destroy(resource);
367}
368
Carlos Garnacho9c931792016-01-18 23:52:12 +0100369static void
370data_source_set_actions(struct wl_client *client,
371 struct wl_resource *resource,
372 uint32_t dnd_actions)
373{
374 struct weston_data_source *source =
375 wl_resource_get_user_data(resource);
376
377 if (source->actions_set) {
378 wl_resource_post_error(source->resource,
379 WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
380 "cannot set actions more than once");
381 return;
382 }
383
384 if (dnd_actions & ~ALL_ACTIONS) {
385 wl_resource_post_error(source->resource,
386 WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
387 "invalid action mask %x", dnd_actions);
388 return;
389 }
390
391 if (source->seat) {
392 wl_resource_post_error(source->resource,
393 WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
394 "invalid action change after "
395 "wl_data_device.start_drag");
396 return;
397 }
398
399 source->dnd_actions = dnd_actions;
400 source->actions_set = true;
401}
402
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400403static struct wl_data_source_interface data_source_interface = {
404 data_source_offer,
Carlos Garnacho9c931792016-01-18 23:52:12 +0100405 data_source_destroy,
406 data_source_set_actions
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400407};
408
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400409static void
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800410drag_surface_configure(struct weston_drag *drag,
Jonas Ådahl767d8912013-12-03 22:30:17 +0100411 struct weston_pointer *pointer,
412 struct weston_touch *touch,
413 struct weston_surface *es,
414 int32_t sx, int32_t sy)
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400415{
Giulio Camuffo412e6a52014-07-09 22:12:56 +0300416 struct weston_layer_entry *list;
Kristian Høgsbergaad80992013-05-07 22:53:43 -0400417 float fx, fy;
Kristian Høgsberg415f30c2013-05-07 22:42:28 -0400418
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800419 assert((pointer != NULL && touch == NULL) ||
420 (pointer == NULL && touch != NULL));
Jason Ekstranda7af7042013-10-12 22:38:11 -0500421
Kristian Høgsberg415f30c2013-05-07 22:42:28 -0400422 if (!weston_surface_is_mapped(es) && es->buffer_ref.buffer) {
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800423 if (pointer && pointer->sprite &&
424 weston_view_is_mapped(pointer->sprite))
Kristian Høgsberg195b8692013-05-08 15:02:05 -0400425 list = &pointer->sprite->layer_link;
Kristian Høgsberg415f30c2013-05-07 22:42:28 -0400426 else
Jason Ekstranda7af7042013-10-12 22:38:11 -0500427 list = &es->compositor->cursor_layer.view_list;
Kristian Høgsberg415f30c2013-05-07 22:42:28 -0400428
Giulio Camuffo412e6a52014-07-09 22:12:56 +0300429 weston_layer_entry_remove(&drag->icon->layer_link);
430 weston_layer_entry_insert(list, &drag->icon->layer_link);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500431 weston_view_update_transform(drag->icon);
Jason Ekstrandef540082014-06-26 10:37:36 -0700432 pixman_region32_clear(&es->pending.input);
Armin Krezovićf8486c32016-06-30 06:04:28 +0200433 es->is_mapped = true;
434 drag->icon->is_mapped = true;
Kristian Høgsberg415f30c2013-05-07 22:42:28 -0400435 }
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400436
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400437 drag->dx += sx;
438 drag->dy += sy;
Kristian Høgsbergaad80992013-05-07 22:53:43 -0400439
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800440 /* init to 0 for avoiding a compile warning */
441 fx = fy = 0;
442 if (pointer) {
443 fx = wl_fixed_to_double(pointer->x) + drag->dx;
444 fy = wl_fixed_to_double(pointer->y) + drag->dy;
445 } else if (touch) {
446 fx = wl_fixed_to_double(touch->grab_x) + drag->dx;
447 fy = wl_fixed_to_double(touch->grab_y) + drag->dy;
448 }
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600449 weston_view_set_position(drag->icon, fx, fy);
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400450}
451
Pekka Paalanen8274d902014-08-06 19:36:51 +0300452static int
453pointer_drag_surface_get_label(struct weston_surface *surface,
454 char *buf, size_t len)
455{
456 return snprintf(buf, len, "pointer drag icon");
457}
458
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400459static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200460pointer_drag_surface_committed(struct weston_surface *es,
Jonas Ådahl767d8912013-12-03 22:30:17 +0100461 int32_t sx, int32_t sy)
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800462{
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200463 struct weston_pointer_drag *drag = es->committed_private;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800464 struct weston_pointer *pointer = drag->grab.pointer;
465
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200466 assert(es->committed == pointer_drag_surface_committed);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800467
Jonas Ådahl767d8912013-12-03 22:30:17 +0100468 drag_surface_configure(&drag->base, pointer, NULL, es, sx, sy);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800469}
470
Pekka Paalanen8274d902014-08-06 19:36:51 +0300471static int
472touch_drag_surface_get_label(struct weston_surface *surface,
473 char *buf, size_t len)
474{
475 return snprintf(buf, len, "touch drag icon");
476}
477
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800478static void
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200479touch_drag_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800480{
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200481 struct weston_touch_drag *drag = es->committed_private;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800482 struct weston_touch *touch = drag->grab.touch;
483
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200484 assert(es->committed == touch_drag_surface_committed);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800485
Jonas Ådahl767d8912013-12-03 22:30:17 +0100486 drag_surface_configure(&drag->base, NULL, touch, es, sx, sy);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800487}
488
489static void
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400490destroy_drag_focus(struct wl_listener *listener, void *data)
491{
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400492 struct weston_drag *drag =
493 container_of(listener, struct weston_drag, focus_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400494
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400495 drag->focus_resource = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400496}
497
498static void
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800499weston_drag_set_focus(struct weston_drag *drag,
500 struct weston_seat *seat,
501 struct weston_view *view,
502 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400503{
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100504 struct wl_resource *resource, *offer_resource = NULL;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800505 struct wl_display *display = seat->compositor->wl_display;
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100506 struct weston_data_offer *offer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400507 uint32_t serial;
508
Jason Ekstranda7af7042013-10-12 22:38:11 -0500509 if (drag->focus && view && drag->focus->surface == view->surface) {
510 drag->focus = view;
511 return;
512 }
513
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400514 if (drag->focus_resource) {
515 wl_data_device_send_leave(drag->focus_resource);
516 wl_list_remove(&drag->focus_listener.link);
517 drag->focus_resource = NULL;
518 drag->focus = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400519 }
520
Jason Ekstranda7af7042013-10-12 22:38:11 -0500521 if (!view || !view->surface->resource)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400522 return;
523
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500524 if (!drag->data_source &&
Jason Ekstranda7af7042013-10-12 22:38:11 -0500525 wl_resource_get_client(view->surface->resource) != drag->client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400526 return;
527
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100528 if (drag->data_source &&
529 drag->data_source->offer) {
530 /* Unlink the offer from the source */
531 offer = drag->data_source->offer;
532 offer->source = NULL;
533 drag->data_source->offer = NULL;
534 wl_list_remove(&offer->source_destroy_listener.link);
535 }
536
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800537 resource = wl_resource_find_for_client(&seat->drag_resource_list,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500538 wl_resource_get_client(view->surface->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400539 if (!resource)
540 return;
541
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400542 serial = wl_display_next_serial(display);
543
Kristian Høgsberga34e2f22013-08-20 15:58:25 -0700544 if (drag->data_source) {
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100545 drag->data_source->accepted = false;
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +0800546 offer = weston_data_source_send_offer(drag->data_source, resource);
547 if (offer == NULL)
Kristian Høgsberga34e2f22013-08-20 15:58:25 -0700548 return;
Carlos Garnacho9c931792016-01-18 23:52:12 +0100549
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +0800550 data_offer_update_action(offer);
551
552 offer_resource = offer->resource;
Carlos Garnacho9c931792016-01-18 23:52:12 +0100553 if (wl_resource_get_version (offer_resource) >=
554 WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
555 wl_data_offer_send_source_actions (offer_resource,
556 drag->data_source->dnd_actions);
557 }
Kristian Høgsberga34e2f22013-08-20 15:58:25 -0700558 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400559
Jason Ekstranda7af7042013-10-12 22:38:11 -0500560 wl_data_device_send_enter(resource, serial, view->surface->resource,
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100561 sx, sy, offer_resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400562
Jason Ekstranda7af7042013-10-12 22:38:11 -0500563 drag->focus = view;
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400564 drag->focus_listener.notify = destroy_drag_focus;
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -0500565 wl_resource_add_destroy_listener(resource, &drag->focus_listener);
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400566 drag->focus_resource = resource;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400567}
568
569static void
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400570drag_grab_focus(struct weston_pointer_grab *grab)
571{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800572 struct weston_pointer_drag *drag =
573 container_of(grab, struct weston_pointer_drag, grab);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400574 struct weston_pointer *pointer = grab->pointer;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500575 struct weston_view *view;
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400576 wl_fixed_t sx, sy;
577
Jason Ekstranda7af7042013-10-12 22:38:11 -0500578 view = weston_compositor_pick_view(pointer->seat->compositor,
579 pointer->x, pointer->y,
580 &sx, &sy);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800581 if (drag->base.focus != view)
582 weston_drag_set_focus(&drag->base, pointer->seat, view, sx, sy);
Kristian Høgsberg6848c252013-05-08 22:02:59 -0400583}
584
585static void
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200586drag_grab_motion(struct weston_pointer_grab *grab,
587 const struct timespec *time,
Jonas Ådahld2510102014-10-05 21:39:14 +0200588 struct weston_pointer_motion_event *event)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400589{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800590 struct weston_pointer_drag *drag =
591 container_of(grab, struct weston_pointer_drag, grab);
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400592 struct weston_pointer *pointer = drag->grab.pointer;
Kristian Høgsbergaad80992013-05-07 22:53:43 -0400593 float fx, fy;
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400594 wl_fixed_t sx, sy;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200595 uint32_t msecs;
Kristian Høgsbergaad80992013-05-07 22:53:43 -0400596
Jonas Ådahld2510102014-10-05 21:39:14 +0200597 weston_pointer_move(pointer, event);
Giulio Camuffo1959ab82013-11-14 23:42:52 +0100598
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800599 if (drag->base.icon) {
600 fx = wl_fixed_to_double(pointer->x) + drag->base.dx;
601 fy = wl_fixed_to_double(pointer->y) + drag->base.dy;
602 weston_view_set_position(drag->base.icon, fx, fy);
603 weston_view_schedule_repaint(drag->base.icon);
Kristian Høgsbergaad80992013-05-07 22:53:43 -0400604 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400605
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800606 if (drag->base.focus_resource) {
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200607 msecs = timespec_to_msec(time);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800608 weston_view_from_global_fixed(drag->base.focus,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500609 pointer->x, pointer->y,
610 &sx, &sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400611
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200612 wl_data_device_send_motion(drag->base.focus_resource, msecs, sx, sy);
Kristian Høgsbergbe6403e2013-05-08 21:03:21 -0400613 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400614}
615
616static void
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800617data_device_end_drag_grab(struct weston_drag *drag,
618 struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400619{
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400620 if (drag->icon) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500621 if (weston_view_is_mapped(drag->icon))
622 weston_view_unmap(drag->icon);
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400623
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200624 drag->icon->surface->committed = NULL;
Pekka Paalanen8274d902014-08-06 19:36:51 +0300625 weston_surface_set_label_func(drag->icon->surface, NULL);
Jason Ekstrandef540082014-06-26 10:37:36 -0700626 pixman_region32_clear(&drag->icon->surface->pending.input);
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400627 wl_list_remove(&drag->icon_destroy_listener.link);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500628 weston_view_destroy(drag->icon);
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400629 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400630
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800631 weston_drag_set_focus(drag, seat, NULL, 0, 0);
632}
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400633
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800634static void
635data_device_end_pointer_drag_grab(struct weston_pointer_drag *drag)
636{
637 struct weston_pointer *pointer = drag->grab.pointer;
Carlos Garnachob2889882016-01-15 21:14:26 +0100638 struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400639
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800640 data_device_end_drag_grab(&drag->base, pointer->seat);
641 weston_pointer_end_grab(pointer);
Carlos Garnachob2889882016-01-15 21:14:26 +0100642 weston_keyboard_end_grab(keyboard);
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400643 free(drag);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400644}
645
646static void
Kristian Høgsberg02bbabb2013-05-06 22:15:05 -0400647drag_grab_button(struct weston_pointer_grab *grab,
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200648 const struct timespec *time,
649 uint32_t button, uint32_t state_w)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400650{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800651 struct weston_pointer_drag *drag =
652 container_of(grab, struct weston_pointer_drag, grab);
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400653 struct weston_pointer *pointer = drag->grab.pointer;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400654 enum wl_pointer_button_state state = state_w;
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100655 struct weston_data_source *data_source = drag->base.data_source;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400656
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100657 if (data_source &&
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400658 pointer->grab_button == button &&
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100659 state == WL_POINTER_BUTTON_STATE_RELEASED) {
660 if (drag->base.focus_resource &&
Carlos Garnacho9c931792016-01-18 23:52:12 +0100661 data_source->accepted &&
662 data_source->current_dnd_action) {
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100663 wl_data_device_send_drop(drag->base.focus_resource);
664
665 if (wl_resource_get_version(data_source->resource) >=
666 WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
667 wl_data_source_send_dnd_drop_performed(data_source->resource);
668
Carlos Garnacho9c931792016-01-18 23:52:12 +0100669 data_source->offer->in_ask =
670 data_source->current_dnd_action ==
671 WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
672
Carlos Garnacho78d4bf92016-01-15 21:14:23 +0100673 data_source->seat = NULL;
674 } else if (wl_resource_get_version(data_source->resource) >=
675 WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
676 wl_data_source_send_cancelled(data_source->resource);
677 }
678 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400679
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400680 if (pointer->button_count == 0 &&
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400681 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800682 if (drag->base.data_source)
683 wl_list_remove(&drag->base.data_source_listener.link);
684 data_device_end_pointer_drag_grab(drag);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400685 }
686}
687
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200688static void
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200689drag_grab_axis(struct weston_pointer_grab *grab,
Alexandros Frantzis80321942017-11-16 18:20:56 +0200690 const struct timespec *time,
691 struct weston_pointer_axis_event *event)
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200692{
693}
694
695static void
Peter Hutterer87743e92016-01-18 16:38:22 +1000696drag_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
697{
698}
699
700static void
701drag_grab_frame(struct weston_pointer_grab *grab)
702{
703}
704
705static void
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200706drag_grab_cancel(struct weston_pointer_grab *grab)
707{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800708 struct weston_pointer_drag *drag =
709 container_of(grab, struct weston_pointer_drag, grab);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200710
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800711 if (drag->base.data_source)
712 wl_list_remove(&drag->base.data_source_listener.link);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200713
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800714 data_device_end_pointer_drag_grab(drag);
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200715}
716
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800717static const struct weston_pointer_grab_interface pointer_drag_grab_interface = {
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400718 drag_grab_focus,
719 drag_grab_motion,
720 drag_grab_button,
Jonas Ådahl0336ca02014-10-04 16:28:29 +0200721 drag_grab_axis,
Peter Hutterer87743e92016-01-18 16:38:22 +1000722 drag_grab_axis_source,
723 drag_grab_frame,
Jonas Ådahl1ea343e2013-10-25 23:18:05 +0200724 drag_grab_cancel,
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400725};
726
727static void
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200728drag_grab_touch_down(struct weston_touch_grab *grab,
729 const struct timespec *time, int touch_id,
730 wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400731{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800732}
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400733
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800734static void
735data_device_end_touch_drag_grab(struct weston_touch_drag *drag)
736{
737 struct weston_touch *touch = drag->grab.touch;
Carlos Garnachob2889882016-01-15 21:14:26 +0100738 struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800739
740 data_device_end_drag_grab(&drag->base, touch->seat);
741 weston_touch_end_grab(touch);
Carlos Garnachob2889882016-01-15 21:14:26 +0100742 weston_keyboard_end_grab(keyboard);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800743 free(drag);
744}
745
746static void
747drag_grab_touch_up(struct weston_touch_grab *grab,
Alexandros Frantzis27a51b82017-11-16 18:20:59 +0200748 const struct timespec *time, int touch_id)
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800749{
750 struct weston_touch_drag *touch_drag =
751 container_of(grab, struct weston_touch_drag, grab);
752 struct weston_touch *touch = grab->touch;
753
754 if (touch_id != touch->grab_touch_id)
755 return;
756
757 if (touch_drag->base.focus_resource)
758 wl_data_device_send_drop(touch_drag->base.focus_resource);
759 if (touch_drag->base.data_source)
760 wl_list_remove(&touch_drag->base.data_source_listener.link);
761 data_device_end_touch_drag_grab(touch_drag);
762}
763
764static void
765drag_grab_touch_focus(struct weston_touch_drag *drag)
766{
767 struct weston_touch *touch = drag->grab.touch;
768 struct weston_view *view;
769 wl_fixed_t view_x, view_y;
770
771 view = weston_compositor_pick_view(touch->seat->compositor,
772 touch->grab_x, touch->grab_y,
773 &view_x, &view_y);
774 if (drag->base.focus != view)
775 weston_drag_set_focus(&drag->base, touch->seat,
776 view, view_x, view_y);
777}
778
779static void
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200780drag_grab_touch_motion(struct weston_touch_grab *grab,
781 const struct timespec *time,
782 int touch_id, wl_fixed_t x, wl_fixed_t y)
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800783{
784 struct weston_touch_drag *touch_drag =
785 container_of(grab, struct weston_touch_drag, grab);
786 struct weston_touch *touch = grab->touch;
787 wl_fixed_t view_x, view_y;
788 float fx, fy;
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200789 uint32_t msecs;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800790
791 if (touch_id != touch->grab_touch_id)
792 return;
793
794 drag_grab_touch_focus(touch_drag);
795 if (touch_drag->base.icon) {
796 fx = wl_fixed_to_double(touch->grab_x) + touch_drag->base.dx;
797 fy = wl_fixed_to_double(touch->grab_y) + touch_drag->base.dy;
798 weston_view_set_position(touch_drag->base.icon, fx, fy);
799 weston_view_schedule_repaint(touch_drag->base.icon);
800 }
801
802 if (touch_drag->base.focus_resource) {
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200803 msecs = timespec_to_msec(time);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800804 weston_view_from_global_fixed(touch_drag->base.focus,
805 touch->grab_x, touch->grab_y,
806 &view_x, &view_y);
Alexandros Frantzis7d2abcf2017-11-16 18:21:00 +0200807 wl_data_device_send_motion(touch_drag->base.focus_resource,
808 msecs, view_x, view_y);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800809 }
810}
811
812static void
Jonas Ådahl1679f232014-04-12 09:39:51 +0200813drag_grab_touch_frame(struct weston_touch_grab *grab)
814{
815}
816
817static void
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800818drag_grab_touch_cancel(struct weston_touch_grab *grab)
819{
820 struct weston_touch_drag *touch_drag =
821 container_of(grab, struct weston_touch_drag, grab);
822
823 if (touch_drag->base.data_source)
824 wl_list_remove(&touch_drag->base.data_source_listener.link);
825 data_device_end_touch_drag_grab(touch_drag);
826}
827
828static const struct weston_touch_grab_interface touch_drag_grab_interface = {
829 drag_grab_touch_down,
830 drag_grab_touch_up,
831 drag_grab_touch_motion,
Jonas Ådahl1679f232014-04-12 09:39:51 +0200832 drag_grab_touch_frame,
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800833 drag_grab_touch_cancel
834};
835
836static void
Carlos Garnachob2889882016-01-15 21:14:26 +0100837drag_grab_keyboard_key(struct weston_keyboard_grab *grab,
Alexandros Frantzis47e79c82017-11-16 18:20:57 +0200838 const struct timespec *time, uint32_t key, uint32_t state)
Carlos Garnachob2889882016-01-15 21:14:26 +0100839{
840}
841
842static void
843drag_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
844 uint32_t serial, uint32_t mods_depressed,
845 uint32_t mods_latched,
846 uint32_t mods_locked, uint32_t group)
847{
848 struct weston_keyboard *keyboard = grab->keyboard;
849 struct weston_drag *drag =
850 container_of(grab, struct weston_drag, keyboard_grab);
851 uint32_t compositor_action;
852
853 if (mods_depressed & (1 << keyboard->xkb_info->shift_mod))
854 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
855 else if (mods_depressed & (1 << keyboard->xkb_info->ctrl_mod))
856 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
857 else
858 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
859
860 drag->data_source->compositor_action = compositor_action;
861
862 if (drag->data_source->offer)
863 data_offer_update_action(drag->data_source->offer);
864}
865
866static void
867drag_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
868{
869 struct weston_drag *drag =
870 container_of(grab, struct weston_drag, keyboard_grab);
871 struct weston_pointer *pointer = grab->keyboard->seat->pointer_state;
872 struct weston_touch *touch = grab->keyboard->seat->touch_state;
873
874 if (pointer && pointer->grab->interface == &pointer_drag_grab_interface) {
875 struct weston_touch_drag *touch_drag =
876 (struct weston_touch_drag *) drag;
877 drag_grab_touch_cancel(&touch_drag->grab);
878 } else if (touch && touch->grab->interface == &touch_drag_grab_interface) {
879 struct weston_pointer_drag *pointer_drag =
880 (struct weston_pointer_drag *) drag;
881 drag_grab_cancel(&pointer_drag->grab);
882 }
883}
884
885static const struct weston_keyboard_grab_interface keyboard_drag_grab_interface = {
886 drag_grab_keyboard_key,
887 drag_grab_keyboard_modifiers,
888 drag_grab_keyboard_cancel
889};
890
891static void
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800892destroy_pointer_data_device_source(struct wl_listener *listener, void *data)
893{
894 struct weston_pointer_drag *drag = container_of(listener,
895 struct weston_pointer_drag, base.data_source_listener);
896
897 data_device_end_pointer_drag_grab(drag);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400898}
899
900static void
Kristian Høgsbergc43aad12013-05-08 15:30:42 -0400901handle_drag_icon_destroy(struct wl_listener *listener, void *data)
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400902{
Kristian Høgsberg054c50a2013-05-08 15:27:47 -0400903 struct weston_drag *drag = container_of(listener, struct weston_drag,
Kristian Høgsbergc43aad12013-05-08 15:30:42 -0400904 icon_destroy_listener);
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400905
Kristian Høgsbergc43aad12013-05-08 15:30:42 -0400906 drag->icon = NULL;
Kristian Høgsberg7848bb62013-05-07 11:18:46 -0400907}
908
Kristian Høgsberg85de9c22013-09-04 20:44:26 -0700909WL_EXPORT int
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800910weston_pointer_start_drag(struct weston_pointer *pointer,
Kristian Høgsberg85de9c22013-09-04 20:44:26 -0700911 struct weston_data_source *source,
912 struct weston_surface *icon,
913 struct wl_client *client)
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400914{
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800915 struct weston_pointer_drag *drag;
Carlos Garnachob2889882016-01-15 21:14:26 +0100916 struct weston_keyboard *keyboard =
917 weston_seat_get_keyboard(pointer->seat);
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400918
Peter Huttererf3d62272013-08-08 11:57:05 +1000919 drag = zalloc(sizeof *drag);
Kristian Høgsberg85de9c22013-09-04 20:44:26 -0700920 if (drag == NULL)
921 return -1;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400922
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800923 drag->grab.interface = &pointer_drag_grab_interface;
Carlos Garnachob2889882016-01-15 21:14:26 +0100924 drag->base.keyboard_grab.interface = &keyboard_drag_grab_interface;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800925 drag->base.client = client;
926 drag->base.data_source = source;
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400927
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400928 if (icon) {
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800929 drag->base.icon = weston_view_create(icon);
930 if (drag->base.icon == NULL) {
Jason Ekstranda7af7042013-10-12 22:38:11 -0500931 free(drag);
932 return -1;
933 }
934
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800935 drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy;
Jason Ekstrand26ed73c2013-06-06 22:34:41 -0500936 wl_signal_add(&icon->destroy_signal,
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800937 &drag->base.icon_destroy_listener);
Kristian Høgsberg5a9fb352013-05-08 15:47:52 -0400938
Quentin Glidic2edc3d52016-08-12 10:41:33 +0200939 icon->committed = pointer_drag_surface_committed;
940 icon->committed_private = drag;
Pekka Paalanen8274d902014-08-06 19:36:51 +0300941 weston_surface_set_label_func(icon,
942 pointer_drag_surface_get_label);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500943 } else {
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800944 drag->base.icon = NULL;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500945 }
946
947 if (source) {
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800948 drag->base.data_source_listener.notify = destroy_pointer_data_device_source;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500949 wl_signal_add(&source->destroy_signal,
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800950 &drag->base.data_source_listener);
Kristian Høgsberg2158a882013-04-18 15:07:39 -0400951 }
952
Derek Foremanf9318d12015-05-11 15:40:11 -0500953 weston_pointer_clear_focus(pointer);
Carlos Garnachob2889882016-01-15 21:14:26 +0100954 weston_keyboard_set_focus(keyboard, NULL);
955
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800956 weston_pointer_start_grab(pointer, &drag->grab);
Carlos Garnachob2889882016-01-15 21:14:26 +0100957 weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800958
959 return 0;
960}
961
962static void
963destroy_touch_data_device_source(struct wl_listener *listener, void *data)
964{
965 struct weston_touch_drag *drag = container_of(listener,
966 struct weston_touch_drag, base.data_source_listener);
967
968 data_device_end_touch_drag_grab(drag);
969}
970
971WL_EXPORT int
972weston_touch_start_drag(struct weston_touch *touch,
973 struct weston_data_source *source,
974 struct weston_surface *icon,
975 struct wl_client *client)
976{
977 struct weston_touch_drag *drag;
Carlos Garnachob2889882016-01-15 21:14:26 +0100978 struct weston_keyboard *keyboard =
979 weston_seat_get_keyboard(touch->seat);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +0800980
981 drag = zalloc(sizeof *drag);
982 if (drag == NULL)
983 return -1;
984
985 drag->grab.interface = &touch_drag_grab_interface;
986 drag->base.client = client;
987 drag->base.data_source = source;
988
989 if (icon) {
990 drag->base.icon = weston_view_create(icon);
991 if (drag->base.icon == NULL) {
992 free(drag);
993 return -1;
994 }
995
996 drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy;
997 wl_signal_add(&icon->destroy_signal,
998 &drag->base.icon_destroy_listener);
999
Quentin Glidic2edc3d52016-08-12 10:41:33 +02001000 icon->committed = touch_drag_surface_committed;
1001 icon->committed_private = drag;
Pekka Paalanen8274d902014-08-06 19:36:51 +03001002 weston_surface_set_label_func(icon,
1003 touch_drag_surface_get_label);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +08001004 } else {
1005 drag->base.icon = NULL;
1006 }
1007
1008 if (source) {
1009 drag->base.data_source_listener.notify = destroy_touch_data_device_source;
1010 wl_signal_add(&source->destroy_signal,
1011 &drag->base.data_source_listener);
1012 }
1013
Carlos Garnachob2889882016-01-15 21:14:26 +01001014 weston_keyboard_set_focus(keyboard, NULL);
1015
Xiong Zhangfd51e7b2013-11-25 18:42:49 +08001016 weston_touch_start_grab(touch, &drag->grab);
Carlos Garnachob2889882016-01-15 21:14:26 +01001017 weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +08001018
1019 drag_grab_touch_focus(drag);
Kristian Høgsberg0abad072013-09-11 09:42:26 -07001020
1021 return 0;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001022}
1023
1024static void
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001025data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
1026 struct wl_resource *source_resource,
1027 struct wl_resource *origin_resource,
1028 struct wl_resource *icon_resource, uint32_t serial)
1029{
1030 struct weston_seat *seat = wl_resource_get_user_data(resource);
Derek Foreman1281a362015-07-31 16:55:32 -05001031 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1032 struct weston_touch *touch = weston_seat_get_touch(seat);
Jason Ekstrand8202d722014-06-24 21:19:24 -07001033 struct weston_surface *origin = wl_resource_get_user_data(origin_resource);
Kristian Høgsberg1702d4c2013-09-11 09:45:03 -07001034 struct weston_data_source *source = NULL;
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001035 struct weston_surface *icon = NULL;
Jason Ekstrand8202d722014-06-24 21:19:24 -07001036 int is_pointer_grab, is_touch_grab;
Xiong Zhangfd51e7b2013-11-25 18:42:49 +08001037 int32_t ret = 0;
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001038
Derek Foreman1281a362015-07-31 16:55:32 -05001039 is_pointer_grab = pointer &&
1040 pointer->button_count == 1 &&
1041 pointer->grab_serial == serial &&
1042 pointer->focus &&
1043 pointer->focus->surface == origin;
Jason Ekstrand8202d722014-06-24 21:19:24 -07001044
Derek Foreman1281a362015-07-31 16:55:32 -05001045 is_touch_grab = touch &&
1046 touch->num_tp == 1 &&
1047 touch->grab_serial == serial &&
1048 touch->focus &&
1049 touch->focus->surface == origin;
Jason Ekstrand8202d722014-06-24 21:19:24 -07001050
1051 if (!is_pointer_grab && !is_touch_grab)
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001052 return;
1053
1054 /* FIXME: Check that the data source type array isn't empty. */
1055
1056 if (source_resource)
1057 source = wl_resource_get_user_data(source_resource);
1058 if (icon_resource)
1059 icon = wl_resource_get_user_data(icon_resource);
Pekka Paalanen50b67472014-10-01 15:02:41 +03001060
1061 if (icon) {
1062 if (weston_surface_set_role(icon, "wl_data_device-icon",
1063 resource,
1064 WL_DATA_DEVICE_ERROR_ROLE) < 0)
1065 return;
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001066 }
1067
Jason Ekstrand8202d722014-06-24 21:19:24 -07001068 if (is_pointer_grab)
Derek Foreman1281a362015-07-31 16:55:32 -05001069 ret = weston_pointer_start_drag(pointer, source, icon, client);
Jason Ekstrand8202d722014-06-24 21:19:24 -07001070 else if (is_touch_grab)
Derek Foreman1281a362015-07-31 16:55:32 -05001071 ret = weston_touch_start_drag(touch, source, icon, client);
Xiong Zhangfd51e7b2013-11-25 18:42:49 +08001072
1073 if (ret < 0)
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001074 wl_resource_post_no_memory(resource);
Carlos Garnacho78d4bf92016-01-15 21:14:23 +01001075 else
1076 source->seat = seat;
Kristian Høgsberg85de9c22013-09-04 20:44:26 -07001077}
1078
1079static void
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001080destroy_selection_data_source(struct wl_listener *listener, void *data)
1081{
Kristian Høgsberge3148752013-05-06 23:19:49 -04001082 struct weston_seat *seat = container_of(listener, struct weston_seat,
1083 selection_data_source_listener);
Derek Foreman1281a362015-07-31 16:55:32 -05001084 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001085 struct wl_resource *data_device;
Neil Roberts96d790e2013-09-19 17:32:00 +01001086 struct weston_surface *focus = NULL;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001087
1088 seat->selection_data_source = NULL;
1089
Derek Foreman1281a362015-07-31 16:55:32 -05001090 if (keyboard)
1091 focus = keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01001092 if (focus && focus->resource) {
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001093 data_device = wl_resource_find_for_client(&seat->drag_resource_list,
Neil Roberts96d790e2013-09-19 17:32:00 +01001094 wl_resource_get_client(focus->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001095 if (data_device)
1096 wl_data_device_send_selection(data_device, NULL);
1097 }
1098
1099 wl_signal_emit(&seat->selection_signal, seat);
1100}
1101
Giulio Camuffodddf9e62015-05-01 12:59:35 +03001102/** \brief Send the selection to the specified client
1103 *
1104 * This function creates a new wl_data_offer if there is a wl_data_source
1105 * currently set as the selection and sends it to the specified client,
1106 * followed by the wl_data_device.selection() event.
1107 * If there is no current selection the wl_data_device.selection() event
1108 * will carry a NULL wl_data_offer.
1109 *
1110 * If the client does not have a wl_data_device for the specified seat
1111 * nothing will be done.
1112 *
1113 * \param seat The seat owning the wl_data_device used to send the events.
1114 * \param client The client to which to send the selection.
1115 */
1116WL_EXPORT void
1117weston_seat_send_selection(struct weston_seat *seat, struct wl_client *client)
1118{
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +08001119 struct weston_data_offer *offer;
1120 struct wl_resource *data_device;
Giulio Camuffodddf9e62015-05-01 12:59:35 +03001121
Giulio Camuffod46bb012015-05-01 12:59:36 +03001122 wl_resource_for_each(data_device, &seat->drag_resource_list) {
1123 if (wl_resource_get_client(data_device) != client)
1124 continue;
1125
1126 if (seat->selection_data_source) {
1127 offer = weston_data_source_send_offer(seat->selection_data_source,
Jonas Ådahl8b6c9fc2016-03-15 15:23:50 +08001128 data_device);
1129 wl_data_device_send_selection(data_device, offer->resource);
Giulio Camuffod46bb012015-05-01 12:59:36 +03001130 } else {
1131 wl_data_device_send_selection(data_device, NULL);
1132 }
Giulio Camuffodddf9e62015-05-01 12:59:35 +03001133 }
1134}
1135
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001136WL_EXPORT void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001137weston_seat_set_selection(struct weston_seat *seat,
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001138 struct weston_data_source *source, uint32_t serial)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001139{
Neil Roberts96d790e2013-09-19 17:32:00 +01001140 struct weston_surface *focus = NULL;
Derek Foreman1281a362015-07-31 16:55:32 -05001141 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001142
1143 if (seat->selection_data_source &&
1144 seat->selection_serial - serial < UINT32_MAX / 2)
1145 return;
1146
1147 if (seat->selection_data_source) {
1148 seat->selection_data_source->cancel(seat->selection_data_source);
1149 wl_list_remove(&seat->selection_data_source_listener.link);
1150 seat->selection_data_source = NULL;
1151 }
1152
1153 seat->selection_data_source = source;
1154 seat->selection_serial = serial;
Emmanuel Gil Peyrot45f5e532019-08-15 14:02:22 +02001155
1156 if (source)
1157 source->set_selection = true;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001158
Derek Foreman1281a362015-07-31 16:55:32 -05001159 if (keyboard)
1160 focus = keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01001161 if (focus && focus->resource) {
Giulio Camuffodddf9e62015-05-01 12:59:35 +03001162 weston_seat_send_selection(seat, wl_resource_get_client(focus->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001163 }
1164
1165 wl_signal_emit(&seat->selection_signal, seat);
1166
1167 if (source) {
1168 seat->selection_data_source_listener.notify =
1169 destroy_selection_data_source;
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001170 wl_signal_add(&source->destroy_signal,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001171 &seat->selection_data_source_listener);
1172 }
1173}
1174
1175static void
1176data_device_set_selection(struct wl_client *client,
1177 struct wl_resource *resource,
1178 struct wl_resource *source_resource, uint32_t serial)
1179{
Alexandros Frantzis8480d132018-02-15 13:07:09 +02001180 struct weston_seat *seat = wl_resource_get_user_data(resource);
Carlos Garnacho9c931792016-01-18 23:52:12 +01001181 struct weston_data_source *source;
1182
Alexandros Frantzis8480d132018-02-15 13:07:09 +02001183 if (!seat || !source_resource)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001184 return;
1185
Carlos Garnacho9c931792016-01-18 23:52:12 +01001186 source = wl_resource_get_user_data(source_resource);
1187
1188 if (source->actions_set) {
1189 wl_resource_post_error(source_resource,
1190 WL_DATA_SOURCE_ERROR_INVALID_SOURCE,
1191 "cannot set drag-and-drop source as selection");
1192 return;
1193 }
1194
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001195 /* FIXME: Store serial and check against incoming serial here. */
Alexandros Frantzis8480d132018-02-15 13:07:09 +02001196 weston_seat_set_selection(seat, source, serial);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001197}
kabeer khan3a510d82014-10-20 11:47:15 +05301198static void
1199data_device_release(struct wl_client *client, struct wl_resource *resource)
1200{
1201 wl_resource_destroy(resource);
1202}
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001203
1204static const struct wl_data_device_interface data_device_interface = {
1205 data_device_start_drag,
1206 data_device_set_selection,
kabeer khan3a510d82014-10-20 11:47:15 +05301207 data_device_release
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001208};
1209
1210static void
1211destroy_data_source(struct wl_resource *resource)
1212{
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001213 struct weston_data_source *source =
1214 wl_resource_get_user_data(resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001215 char **p;
1216
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001217 wl_signal_emit(&source->destroy_signal, source);
1218
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001219 wl_array_for_each(p, &source->mime_types)
1220 free(*p);
1221
1222 wl_array_release(&source->mime_types);
1223
Kristian Høgsberg489b2792013-06-25 11:26:31 -04001224 free(source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001225}
1226
1227static void
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001228client_source_accept(struct weston_data_source *source,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001229 uint32_t time, const char *mime_type)
1230{
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001231 wl_data_source_send_target(source->resource, mime_type);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001232}
1233
1234static void
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001235client_source_send(struct weston_data_source *source,
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001236 const char *mime_type, int32_t fd)
1237{
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001238 wl_data_source_send_send(source->resource, mime_type, fd);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001239 close(fd);
1240}
1241
1242static void
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001243client_source_cancel(struct weston_data_source *source)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001244{
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001245 wl_data_source_send_cancelled(source->resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001246}
1247
1248static void
1249create_data_source(struct wl_client *client,
1250 struct wl_resource *resource, uint32_t id)
1251{
Kristian Høgsberg7ff3bdb2013-07-25 15:52:14 -07001252 struct weston_data_source *source;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001253
1254 source = malloc(sizeof *source);
1255 if (source == NULL) {
1256 wl_resource_post_no_memory(resource);
1257 return;
1258 }
1259
cpaul@redhat.comc9f8f8a2016-01-05 11:18:30 -05001260 source->resource =
Carlos Garnacho78d4bf92016-01-15 21:14:23 +01001261 wl_resource_create(client, &wl_data_source_interface,
1262 wl_resource_get_version(resource), id);
cpaul@redhat.comc9f8f8a2016-01-05 11:18:30 -05001263 if (source->resource == NULL) {
1264 free(source);
1265 wl_resource_post_no_memory(resource);
1266 return;
1267 }
1268
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001269 wl_signal_init(&source->destroy_signal);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001270 source->accept = client_source_accept;
1271 source->send = client_source_send;
1272 source->cancel = client_source_cancel;
Carlos Garnacho78d4bf92016-01-15 21:14:23 +01001273 source->offer = NULL;
1274 source->accepted = false;
1275 source->seat = NULL;
Carlos Garnacho9c931792016-01-18 23:52:12 +01001276 source->actions_set = false;
1277 source->dnd_actions = 0;
1278 source->current_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
Carlos Garnachob2889882016-01-15 21:14:26 +01001279 source->compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
Harish Krupo737ac0d2019-04-19 22:06:37 +05301280 source->set_selection = false;
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001281
1282 wl_array_init(&source->mime_types);
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001283
Jason Ekstranda85118c2013-06-27 20:17:02 -05001284 wl_resource_set_implementation(source->resource, &data_source_interface,
1285 source, destroy_data_source);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001286}
1287
1288static void unbind_data_device(struct wl_resource *resource)
1289{
Jason Ekstrand8a4a9eb2013-06-14 10:07:55 -05001290 wl_list_remove(wl_resource_get_link(resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001291}
1292
1293static void
1294get_data_device(struct wl_client *client,
1295 struct wl_resource *manager_resource,
1296 uint32_t id, struct wl_resource *seat_resource)
1297{
Jason Ekstranda0d2dde2013-06-14 10:08:01 -05001298 struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001299 struct wl_resource *resource;
1300
Jason Ekstranda85118c2013-06-27 20:17:02 -05001301 resource = wl_resource_create(client,
kabeer khan3a510d82014-10-20 11:47:15 +05301302 &wl_data_device_interface,
1303 wl_resource_get_version(manager_resource),
1304 id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001305 if (resource == NULL) {
1306 wl_resource_post_no_memory(manager_resource);
1307 return;
1308 }
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001309
Alexandros Frantzis8480d132018-02-15 13:07:09 +02001310 if (seat) {
1311 wl_list_insert(&seat->drag_resource_list,
1312 wl_resource_get_link(resource));
1313 } else {
1314 wl_list_init(wl_resource_get_link(resource));
1315 }
1316
Jason Ekstranda85118c2013-06-27 20:17:02 -05001317 wl_resource_set_implementation(resource, &data_device_interface,
1318 seat, unbind_data_device);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001319}
1320
1321static const struct wl_data_device_manager_interface manager_interface = {
1322 create_data_source,
1323 get_data_device
1324};
1325
1326static void
1327bind_manager(struct wl_client *client,
1328 void *data, uint32_t version, uint32_t id)
1329{
Jason Ekstranda85118c2013-06-27 20:17:02 -05001330 struct wl_resource *resource;
1331
kabeer khan3a510d82014-10-20 11:47:15 +05301332 resource = wl_resource_create(client,
1333 &wl_data_device_manager_interface,
1334 version, id);
Kristian Høgsberg0ff79082013-08-06 16:46:25 -07001335 if (resource == NULL) {
1336 wl_client_post_no_memory(client);
1337 return;
1338 }
1339
1340 wl_resource_set_implementation(resource, &manager_interface,
1341 NULL, NULL);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001342}
1343
1344WL_EXPORT void
Kristian Høgsberge3148752013-05-06 23:19:49 -04001345wl_data_device_set_keyboard_focus(struct weston_seat *seat)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001346{
Neil Roberts96d790e2013-09-19 17:32:00 +01001347 struct weston_surface *focus;
Derek Foreman1281a362015-07-31 16:55:32 -05001348 struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001349
Derek Foreman1281a362015-07-31 16:55:32 -05001350 if (!keyboard)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001351 return;
1352
Derek Foreman1281a362015-07-31 16:55:32 -05001353 focus = keyboard->focus;
Neil Roberts96d790e2013-09-19 17:32:00 +01001354 if (!focus || !focus->resource)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001355 return;
1356
Giulio Camuffodddf9e62015-05-01 12:59:35 +03001357 weston_seat_send_selection(seat, wl_resource_get_client(focus->resource));
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001358}
1359
1360WL_EXPORT int
1361wl_data_device_manager_init(struct wl_display *display)
1362{
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001363 if (wl_global_create(display,
Carlos Garnacho78d4bf92016-01-15 21:14:23 +01001364 &wl_data_device_manager_interface, 3,
Kristian Høgsberg919cddb2013-07-08 19:03:57 -04001365 NULL, bind_manager) == NULL)
Kristian Høgsberg2158a882013-04-18 15:07:39 -04001366 return -1;
1367
1368 return 0;
1369}