1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <strings.h>
5 #include <unistd.h>
6 #include <wayland-server-core.h>
7 #include <wlr/types/wlr_data_device.h>
8 #include <wlr/types/wlr_seat.h>
9 #include <wlr/util/log.h>
10 #include "types/wlr_data_device.h"
11 #include "util/signal.h"
12
13 #define DATA_DEVICE_MANAGER_VERSION 3
14
15 static const struct wl_data_device_interface data_device_impl;
16
seat_client_from_data_device_resource(struct wl_resource * resource)17 struct wlr_seat_client *seat_client_from_data_device_resource(
18 struct wl_resource *resource) {
19 assert(wl_resource_instance_of(resource, &wl_data_device_interface,
20 &data_device_impl));
21 return wl_resource_get_user_data(resource);
22 }
23
data_device_set_selection(struct wl_client * client,struct wl_resource * device_resource,struct wl_resource * source_resource,uint32_t serial)24 static void data_device_set_selection(struct wl_client *client,
25 struct wl_resource *device_resource,
26 struct wl_resource *source_resource, uint32_t serial) {
27 struct wlr_seat_client *seat_client =
28 seat_client_from_data_device_resource(device_resource);
29 if (seat_client == NULL) {
30 return;
31 }
32
33 struct wlr_client_data_source *source = NULL;
34 if (source_resource != NULL) {
35 source = client_data_source_from_resource(source_resource);
36 }
37
38 if (source != NULL) {
39 source->finalized = true;
40 }
41
42 struct wlr_data_source *wlr_source =
43 source != NULL ? &source->source : NULL;
44 wlr_seat_request_set_selection(seat_client->seat, seat_client, wlr_source, serial);
45 }
46
data_device_start_drag(struct wl_client * client,struct wl_resource * device_resource,struct wl_resource * source_resource,struct wl_resource * origin_resource,struct wl_resource * icon_resource,uint32_t serial)47 static void data_device_start_drag(struct wl_client *client,
48 struct wl_resource *device_resource,
49 struct wl_resource *source_resource,
50 struct wl_resource *origin_resource, struct wl_resource *icon_resource,
51 uint32_t serial) {
52 struct wlr_seat_client *seat_client =
53 seat_client_from_data_device_resource(device_resource);
54 if (seat_client == NULL) {
55 return;
56 }
57
58 struct wlr_surface *origin = wlr_surface_from_resource(origin_resource);
59
60 struct wlr_client_data_source *source = NULL;
61 if (source_resource != NULL) {
62 source = client_data_source_from_resource(source_resource);
63 }
64
65 struct wlr_surface *icon = NULL;
66 if (icon_resource) {
67 icon = wlr_surface_from_resource(icon_resource);
68 if (!wlr_surface_set_role(icon, &drag_icon_surface_role, NULL,
69 icon_resource, WL_DATA_DEVICE_ERROR_ROLE)) {
70 return;
71 }
72 }
73
74 struct wlr_data_source *wlr_source =
75 source != NULL ? &source->source : NULL;
76 struct wlr_drag *drag = wlr_drag_create(seat_client, wlr_source, icon);
77 if (drag == NULL) {
78 wl_resource_post_no_memory(device_resource);
79 return;
80 }
81
82 if (source != NULL) {
83 source->finalized = true;
84 }
85
86 wlr_seat_request_start_drag(seat_client->seat, drag, origin, serial);
87 }
88
data_device_release(struct wl_client * client,struct wl_resource * resource)89 static void data_device_release(struct wl_client *client,
90 struct wl_resource *resource) {
91 wl_resource_destroy(resource);
92 }
93
94 static const struct wl_data_device_interface data_device_impl = {
95 .start_drag = data_device_start_drag,
96 .set_selection = data_device_set_selection,
97 .release = data_device_release,
98 };
99
data_device_handle_resource_destroy(struct wl_resource * resource)100 static void data_device_handle_resource_destroy(struct wl_resource *resource) {
101 wl_list_remove(wl_resource_get_link(resource));
102 }
103
104
device_resource_send_selection(struct wl_resource * device_resource)105 static void device_resource_send_selection(struct wl_resource *device_resource) {
106 struct wlr_seat_client *seat_client =
107 seat_client_from_data_device_resource(device_resource);
108 assert(seat_client != NULL);
109
110 struct wlr_data_source *source = seat_client->seat->selection_source;
111 if (source != NULL) {
112 struct wlr_data_offer *offer = data_offer_create(device_resource,
113 source, WLR_DATA_OFFER_SELECTION);
114 if (offer == NULL) {
115 wl_client_post_no_memory(seat_client->client);
116 return;
117 }
118
119 wl_data_device_send_selection(device_resource, offer->resource);
120 } else {
121 wl_data_device_send_selection(device_resource, NULL);
122 }
123 }
124
seat_client_send_selection(struct wlr_seat_client * seat_client)125 void seat_client_send_selection(struct wlr_seat_client *seat_client) {
126 struct wlr_data_source *source = seat_client->seat->selection_source;
127 if (source != NULL) {
128 source->accepted = false;
129 }
130
131 // Make all current offers inert
132 struct wlr_data_offer *offer, *tmp;
133 wl_list_for_each_safe(offer, tmp,
134 &seat_client->seat->selection_offers, link) {
135 data_offer_destroy(offer);
136 }
137
138 struct wl_resource *device_resource;
139 wl_resource_for_each(device_resource, &seat_client->data_devices) {
140 device_resource_send_selection(device_resource);
141 }
142 }
143
wlr_seat_request_set_selection(struct wlr_seat * seat,struct wlr_seat_client * client,struct wlr_data_source * source,uint32_t serial)144 void wlr_seat_request_set_selection(struct wlr_seat *seat,
145 struct wlr_seat_client *client,
146 struct wlr_data_source *source, uint32_t serial) {
147 if (client && !wlr_seat_client_validate_event_serial(client, serial)) {
148 wlr_log(WLR_DEBUG, "Rejecting set_selection request, "
149 "serial %"PRIu32" was never given to client", serial);
150 return;
151 }
152
153 if (seat->selection_source &&
154 serial - seat->selection_serial > UINT32_MAX / 2) {
155 wlr_log(WLR_DEBUG, "Rejecting set_selection request, serial indicates superseded "
156 "(%"PRIu32" < %"PRIu32")", serial, seat->selection_serial);
157 return;
158 }
159
160 struct wlr_seat_request_set_selection_event event = {
161 .source = source,
162 .serial = serial,
163 };
164 wlr_signal_emit_safe(&seat->events.request_set_selection, &event);
165 }
166
seat_handle_selection_source_destroy(struct wl_listener * listener,void * data)167 static void seat_handle_selection_source_destroy(
168 struct wl_listener *listener, void *data) {
169 struct wlr_seat *seat =
170 wl_container_of(listener, seat, selection_source_destroy);
171
172 wl_list_remove(&seat->selection_source_destroy.link);
173 seat->selection_source = NULL;
174
175 struct wlr_seat_client *focused_client =
176 seat->keyboard_state.focused_client;
177 if (focused_client != NULL) {
178 seat_client_send_selection(focused_client);
179 }
180
181 wlr_signal_emit_safe(&seat->events.set_selection, seat);
182 }
183
wlr_seat_set_selection(struct wlr_seat * seat,struct wlr_data_source * source,uint32_t serial)184 void wlr_seat_set_selection(struct wlr_seat *seat,
185 struct wlr_data_source *source, uint32_t serial) {
186 if (seat->selection_source == source) {
187 seat->selection_serial = serial;
188 return;
189 }
190
191 if (seat->selection_source) {
192 wl_list_remove(&seat->selection_source_destroy.link);
193 wlr_data_source_destroy(seat->selection_source);
194 seat->selection_source = NULL;
195 }
196
197 seat->selection_source = source;
198 seat->selection_serial = serial;
199
200 if (source) {
201 seat->selection_source_destroy.notify =
202 seat_handle_selection_source_destroy;
203 wl_signal_add(&source->events.destroy,
204 &seat->selection_source_destroy);
205 }
206
207 struct wlr_seat_client *focused_client =
208 seat->keyboard_state.focused_client;
209 if (focused_client) {
210 seat_client_send_selection(focused_client);
211 }
212
213 wlr_signal_emit_safe(&seat->events.set_selection, seat);
214 }
215
216
217 static const struct wl_data_device_manager_interface data_device_manager_impl;
218
data_device_manager_from_resource(struct wl_resource * resource)219 static struct wlr_data_device_manager *data_device_manager_from_resource(
220 struct wl_resource *resource) {
221 assert(wl_resource_instance_of(resource, &wl_data_device_manager_interface,
222 &data_device_manager_impl));
223 return wl_resource_get_user_data(resource);
224 }
225
data_device_manager_get_data_device(struct wl_client * client,struct wl_resource * manager_resource,uint32_t id,struct wl_resource * seat_resource)226 static void data_device_manager_get_data_device(struct wl_client *client,
227 struct wl_resource *manager_resource, uint32_t id,
228 struct wl_resource *seat_resource) {
229 struct wlr_seat_client *seat_client =
230 wlr_seat_client_from_resource(seat_resource);
231
232 uint32_t version = wl_resource_get_version(manager_resource);
233 struct wl_resource *resource = wl_resource_create(client,
234 &wl_data_device_interface, version, id);
235 if (resource == NULL) {
236 wl_resource_post_no_memory(manager_resource);
237 return;
238 }
239 wl_resource_set_implementation(resource, &data_device_impl, seat_client,
240 data_device_handle_resource_destroy);
241 wl_list_insert(&seat_client->data_devices, wl_resource_get_link(resource));
242
243 struct wlr_seat_client *focused_client =
244 seat_client->seat->keyboard_state.focused_client;
245 if (focused_client == seat_client) {
246 device_resource_send_selection(resource);
247 }
248 }
249
data_device_manager_create_data_source(struct wl_client * client,struct wl_resource * manager_resource,uint32_t id)250 static void data_device_manager_create_data_source(struct wl_client *client,
251 struct wl_resource *manager_resource, uint32_t id) {
252 struct wlr_data_device_manager *manager =
253 data_device_manager_from_resource(manager_resource);
254
255 client_data_source_create(client, wl_resource_get_version(manager_resource),
256 id, &manager->data_sources);
257 }
258
259 static const struct wl_data_device_manager_interface
260 data_device_manager_impl = {
261 .create_data_source = data_device_manager_create_data_source,
262 .get_data_device = data_device_manager_get_data_device,
263 };
264
data_device_manager_bind(struct wl_client * client,void * data,uint32_t version,uint32_t id)265 static void data_device_manager_bind(struct wl_client *client,
266 void *data, uint32_t version, uint32_t id) {
267 struct wlr_data_device_manager *manager = data;
268
269 struct wl_resource *resource = wl_resource_create(client,
270 &wl_data_device_manager_interface, version, id);
271 if (resource == NULL) {
272 wl_client_post_no_memory(client);
273 return;
274 }
275 wl_resource_set_implementation(resource, &data_device_manager_impl,
276 manager, NULL);
277 }
278
handle_display_destroy(struct wl_listener * listener,void * data)279 static void handle_display_destroy(struct wl_listener *listener, void *data) {
280 struct wlr_data_device_manager *manager =
281 wl_container_of(listener, manager, display_destroy);
282 wlr_signal_emit_safe(&manager->events.destroy, manager);
283 wl_list_remove(&manager->display_destroy.link);
284 wl_global_destroy(manager->global);
285 free(manager);
286 }
287
wlr_data_device_manager_create(struct wl_display * display)288 struct wlr_data_device_manager *wlr_data_device_manager_create(
289 struct wl_display *display) {
290 struct wlr_data_device_manager *manager =
291 calloc(1, sizeof(struct wlr_data_device_manager));
292 if (manager == NULL) {
293 wlr_log(WLR_ERROR, "could not create data device manager");
294 return NULL;
295 }
296
297 wl_list_init(&manager->data_sources);
298 wl_signal_init(&manager->events.destroy);
299
300 manager->global =
301 wl_global_create(display, &wl_data_device_manager_interface,
302 DATA_DEVICE_MANAGER_VERSION, manager, data_device_manager_bind);
303 if (!manager->global) {
304 wlr_log(WLR_ERROR, "could not create data device manager wl_global");
305 free(manager);
306 return NULL;
307 }
308
309 manager->display_destroy.notify = handle_display_destroy;
310 wl_display_add_destroy_listener(display, &manager->display_destroy);
311
312 return manager;
313 }
314