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