parent
							
								
									2b09105bde
								
							
						
					
					
						commit
						6a7560fae0
					
				| @ -1,16 +0,0 @@ | |||||||
| #ifndef WLR_INTERFACES_WLR_DATA_SOURCE_H |  | ||||||
| #define WLR_INTERFACES_WLR_DATA_SOURCE_H |  | ||||||
| 
 |  | ||||||
| #include <wlr/types/wlr_data_source.h> |  | ||||||
| 
 |  | ||||||
| struct wlr_data_source_impl { |  | ||||||
| 	void (*send)(struct wlr_data_source *data_source, const char *type, int fd); |  | ||||||
| 	void (*accepted)(struct wlr_data_source *data_source, const char *type); |  | ||||||
| 	void (*cancelled)(struct wlr_data_source *data_source); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| bool wlr_data_source_init(struct wlr_data_source *source, |  | ||||||
| 		struct wlr_data_source_impl *impl); |  | ||||||
| void wlr_data_source_finish(struct wlr_data_source *source); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | #ifndef WLR_TYPES_WLR_DATA_DEVICE_H | ||||||
|  | #define WLR_TYPES_WLR_DATA_DEVICE_H | ||||||
|  | 
 | ||||||
|  | #include <wayland-server.h> | ||||||
|  | 
 | ||||||
|  | struct wlr_data_device_manager { | ||||||
|  | 	struct wl_global *global; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct wlr_data_offer { | ||||||
|  | 	struct wl_resource *resource; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct wlr_data_source { | ||||||
|  | 	struct wl_resource *resource; | ||||||
|  | 	struct wlr_data_offer *offer; | ||||||
|  | 	struct wlr_seat_handle *seat; | ||||||
|  | 	struct wl_array mime_types; | ||||||
|  | 
 | ||||||
|  | 	struct { | ||||||
|  | 		struct wl_signal destroy; | ||||||
|  | 	} events; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Create a wl data device manager global for this display. | ||||||
|  |  */ | ||||||
|  | struct wlr_data_device_manager *wlr_data_device_manager_create( | ||||||
|  | 		struct wl_display *display); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| @ -1,26 +0,0 @@ | |||||||
| #ifndef WLR_TYPES_WLR_DATA_DEVICE_MANAGER_H |  | ||||||
| #define WLR_TYPES_WLR_DATA_DEVICE_MANAGER_H |  | ||||||
| 
 |  | ||||||
| #include <wayland-server.h> |  | ||||||
| 
 |  | ||||||
| struct wlr_data_device_manager { |  | ||||||
| 	struct wl_global *global; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct wlr_data_device_manager *wlr_data_device_manager_create(struct wl_display *dpy); |  | ||||||
| void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager); |  | ||||||
| 
 |  | ||||||
| struct wlr_data_device { |  | ||||||
| 	struct wlr_seat *seat; |  | ||||||
| 	struct wlr_data_source *selection; |  | ||||||
| 	struct wl_listener selection_destroyed; |  | ||||||
| 
 |  | ||||||
| 	struct { |  | ||||||
| 		struct wl_signal selection_change; |  | ||||||
| 	} events; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void wlr_data_device_set_selection(struct wlr_data_device *manager, |  | ||||||
| 		struct wlr_data_source *source); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,32 +0,0 @@ | |||||||
| #ifndef WLR_TYPES_WLR_DATA_SOURCE_H |  | ||||||
| #define WLR_TYPES_WLR_DATA_SOURCE_H |  | ||||||
| 
 |  | ||||||
| #include <wayland-server.h> |  | ||||||
| #include <wlr/util/list.h> |  | ||||||
| 
 |  | ||||||
| struct wlr_data_source_impl; |  | ||||||
| 
 |  | ||||||
| struct wlr_data_source { |  | ||||||
| 	struct wlr_data_source_impl *impl; |  | ||||||
| 	list_t *types; |  | ||||||
| 	void *data; |  | ||||||
| 
 |  | ||||||
| 	struct { |  | ||||||
| 		struct wl_signal destroy; |  | ||||||
| 	} events; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void wlr_data_source_send(struct wlr_data_source *src, const char *type, int fd); |  | ||||||
| void wlr_data_source_accepted(struct wlr_data_source *src, const char *type); |  | ||||||
| void wlr_data_source_cancelled(struct wlr_data_source *src); |  | ||||||
| 
 |  | ||||||
| struct wlr_wl_data_source { |  | ||||||
| 	struct wlr_data_source base; |  | ||||||
| 	struct wl_resource *resource; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct wlr_wl_data_source *wlr_wl_data_source_create( |  | ||||||
| 		struct wl_client *client, |  | ||||||
| 		uint32_t version, uint32_t id); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -0,0 +1,229 @@ | |||||||
|  | #define _XOPEN_SOURCE 700 | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <assert.h> | ||||||
|  | #include <wayland-server.h> | ||||||
|  | #include <wlr/util/log.h> | ||||||
|  | #include <wlr/types/wlr_seat.h> | ||||||
|  | #include <wlr/types/wlr_data_device.h> | ||||||
|  | 
 | ||||||
|  | static void data_device_start_drag(struct wl_client *client, struct wl_resource | ||||||
|  | 		*resource, struct wl_resource *source_resource, | ||||||
|  | 		struct wl_resource *origin, struct wl_resource *icon, uint32_t serial) { | ||||||
|  | 	wlr_log(L_DEBUG, "TODO: data device start drag"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct wlr_data_offer *wlr_data_source_send_offer( | ||||||
|  | 		struct wlr_data_source *source, | ||||||
|  | 		struct wl_resource *data_device_resourec) { | ||||||
|  | 	// TODO
 | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void wlr_seat_handle_send_selection(struct wlr_seat_handle *handle) { | ||||||
|  | 	if (!handle->data_device) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (handle->wlr_seat->selection_source) { | ||||||
|  | 		struct wlr_data_offer *offer = | ||||||
|  | 			wlr_data_source_send_offer(handle->wlr_seat->selection_source, | ||||||
|  | 				handle->data_device); | ||||||
|  | 		wl_data_device_send_selection(handle->data_device, offer->resource); | ||||||
|  | 	} else { | ||||||
|  | 		wl_data_device_send_selection(handle->data_device, NULL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void wlr_seat_set_selection(struct wlr_seat *seat, | ||||||
|  | 		struct wlr_data_source *source, uint32_t serial) { | ||||||
|  | 	if (seat->selection_source && | ||||||
|  | 			seat->selection_serial - serial < UINT32_MAX / 2) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (seat->selection_source) { | ||||||
|  | 		// TODO cancel
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	seat->selection_source = source; | ||||||
|  | 	seat->selection_serial = serial; | ||||||
|  | 
 | ||||||
|  | 	struct wlr_seat_handle *focused_handle = | ||||||
|  | 		seat->keyboard_state.focused_handle; | ||||||
|  | 
 | ||||||
|  | 	if (focused_handle) { | ||||||
|  | 		// TODO send selection to keyboard
 | ||||||
|  | 		wlr_seat_handle_send_selection(focused_handle); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO emit selection signal
 | ||||||
|  | 
 | ||||||
|  | 	if (source) { | ||||||
|  | 		// TODO set destroy listener
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_device_set_selection(struct wl_client *client, | ||||||
|  | 		struct wl_resource *seat_resource, struct wl_resource *source_resource, | ||||||
|  | 		uint32_t serial) { | ||||||
|  | 	if (!source_resource) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_data_source *source = wl_resource_get_user_data(source_resource); | ||||||
|  | 	struct wlr_seat_handle *handle = wl_resource_get_user_data(seat_resource); | ||||||
|  | 
 | ||||||
|  | 	// TODO: store serial and check against incoming serial here
 | ||||||
|  | 	wlr_seat_set_selection(handle->wlr_seat, source, serial); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_device_release(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource) { | ||||||
|  | 	wl_resource_destroy(resource); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct wl_data_device_interface data_device_impl = { | ||||||
|  | 	.start_drag = data_device_start_drag, | ||||||
|  | 	.set_selection = data_device_set_selection, | ||||||
|  | 	.release = data_device_release, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void data_device_manager_get_data_device(struct wl_client *client, | ||||||
|  | 		struct wl_resource *manager_resource, uint32_t id, | ||||||
|  | 		struct wl_resource *seat_resource) { | ||||||
|  | 	struct wlr_seat_handle *handle = wl_resource_get_user_data(seat_resource); | ||||||
|  | 
 | ||||||
|  | 	struct wl_resource *resource = | ||||||
|  | 		wl_resource_create(client, | ||||||
|  | 			&wl_data_device_interface, | ||||||
|  | 			wl_resource_get_version(manager_resource), id); | ||||||
|  | 	if (resource == NULL) { | ||||||
|  | 		wl_resource_post_no_memory(manager_resource); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO handle a seat handle having multiple data devices
 | ||||||
|  | 	assert(handle->data_device == NULL); | ||||||
|  | 	handle->data_device = resource; | ||||||
|  | 
 | ||||||
|  | 	wl_resource_set_implementation(resource, &data_device_impl, | ||||||
|  | 		handle, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_source_resource_destroy(struct wl_resource *resource) { | ||||||
|  | 	struct wlr_data_source *source = | ||||||
|  | 		wl_resource_get_user_data(resource); | ||||||
|  | 	char **p; | ||||||
|  | 
 | ||||||
|  | 	wl_signal_emit(&source->events.destroy, source); | ||||||
|  | 
 | ||||||
|  | 	wl_array_for_each(p, &source->mime_types) { | ||||||
|  | 		free(*p); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wl_array_release(&source->mime_types); | ||||||
|  | 
 | ||||||
|  | 	free(source); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_source_destroy(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource) { | ||||||
|  | 	wl_resource_destroy(resource); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_source_set_actions(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource, uint32_t dnd_actions) { | ||||||
|  | 	wlr_log(L_DEBUG, "TODO: data source set actions"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void data_source_offer(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource, const char *mime_type) { | ||||||
|  | 	struct wlr_data_source *source = | ||||||
|  | 		wl_resource_get_user_data(resource); | ||||||
|  | 	char **p; | ||||||
|  | 
 | ||||||
|  | 	p = wl_array_add(&source->mime_types, sizeof *p); | ||||||
|  | 
 | ||||||
|  | 	if (p) { | ||||||
|  | 		*p = strdup(mime_type); | ||||||
|  | 	} | ||||||
|  | 	if (!p || !*p){ | ||||||
|  | 		wl_resource_post_no_memory(resource); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct wl_data_source_interface data_source_impl = { | ||||||
|  | 	.offer = data_source_offer, | ||||||
|  | 	.destroy = data_source_destroy, | ||||||
|  | 	.set_actions = data_source_set_actions, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void data_device_manager_create_data_source(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource, uint32_t id) { | ||||||
|  | 	struct wlr_data_source *source = calloc(1, sizeof(struct wlr_data_source)); | ||||||
|  | 	if (source == NULL) { | ||||||
|  | 		wl_resource_post_no_memory(resource); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	source->resource = | ||||||
|  | 		wl_resource_create(client, &wl_data_source_interface, | ||||||
|  | 			wl_resource_get_version(resource), id); | ||||||
|  | 	if (source->resource == NULL) { | ||||||
|  | 		free(source); | ||||||
|  | 		wl_resource_post_no_memory(resource); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wl_array_init(&source->mime_types); | ||||||
|  | 	wl_signal_init(&source->events.destroy); | ||||||
|  | 
 | ||||||
|  | 	wl_resource_set_implementation(source->resource, &data_source_impl, | ||||||
|  | 		source, data_source_resource_destroy); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct wl_data_device_manager_interface | ||||||
|  | data_device_manager_impl = { | ||||||
|  | 	.create_data_source = data_device_manager_create_data_source, | ||||||
|  | 	.get_data_device = data_device_manager_get_data_device, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void data_device_manager_bind(struct wl_client *client, | ||||||
|  | 		void *data, uint32_t version, uint32_t id) { | ||||||
|  | 	struct wl_resource *resource; | ||||||
|  | 
 | ||||||
|  | 	resource = wl_resource_create(client, | ||||||
|  | 			&wl_data_device_manager_interface, | ||||||
|  | 			version, id); | ||||||
|  | 	if (resource == NULL) { | ||||||
|  | 		wl_client_post_no_memory(client); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wl_resource_set_implementation(resource, &data_device_manager_impl, | ||||||
|  | 		NULL, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct wlr_data_device_manager *wlr_data_device_manager_create( | ||||||
|  | 		struct wl_display *display) { | ||||||
|  | 	struct wlr_data_device_manager *manager = | ||||||
|  | 		calloc(1, sizeof(struct wlr_data_device_manager)); | ||||||
|  | 	if (manager == NULL) { | ||||||
|  | 		wlr_log(L_ERROR, "could not create data device manager"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	manager->global = | ||||||
|  | 		wl_global_create(display, &wl_data_device_manager_interface, | ||||||
|  | 			3, NULL, data_device_manager_bind); | ||||||
|  | 
 | ||||||
|  | 	if (!manager->global) { | ||||||
|  | 		wlr_log(L_ERROR, "could not create data device manager wl global"); | ||||||
|  | 		free(manager); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return manager; | ||||||
|  | } | ||||||
| @ -1,198 +0,0 @@ | |||||||
| #include <assert.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <wayland-server.h> |  | ||||||
| #include <wlr/util/log.h> |  | ||||||
| #include <wlr/types/wlr_data_device_manager.h> |  | ||||||
| #include <wlr/types/wlr_data_source.h> |  | ||||||
| #include <wlr/types/wlr_seat.h> |  | ||||||
| 
 |  | ||||||
| static void resource_destroy(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource) { |  | ||||||
| 	wl_resource_destroy(resource); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_device_start_drag(struct wl_client *client, |  | ||||||
| 		struct wl_resource *res, struct wl_resource *source_resource, |  | ||||||
| 		struct wl_resource *origin_res, struct wl_resource *icon_res, |  | ||||||
| 		uint32_t serial) { |  | ||||||
| 	wlr_log(L_DEBUG, "TODO: implement data_device:start_drag"); |  | ||||||
| 
 |  | ||||||
| 	// Will probably look like this:
 |  | ||||||
| 	// struct wlr_seat_handle *handle = wl_resource_get_user_data(res);
 |  | ||||||
| 	// struct wlr_data_device *device = handle->wlr_seat->data_device;
 |  | ||||||
| 	// struct wlr_data_source *src = wl_resource_get_user_data(src_res);
 |  | ||||||
| 	// struct wlr_surface *origin = wl_resource_get_user_data(origin_res);
 |  | ||||||
| 	// struct wlr_surface *icon;
 |  | ||||||
| 	// if (icon_res)
 |  | ||||||
| 	// 	icon = wl_resource_get_user_data(icon_res);
 |  | ||||||
| 	// wlr_seat_start_drag(serial, device->seat, src,
 |  | ||||||
| 	// 	origin, icon); // will set surface roles and emit signal for user
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_device_set_selection(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, struct wl_resource *source_resource, |  | ||||||
| 		uint32_t serial) { |  | ||||||
| 	if (!source_resource) { |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// TODO: serial validation
 |  | ||||||
| 	struct wlr_seat_handle *handle = wl_resource_get_user_data(resource); |  | ||||||
| 	struct wlr_data_device *device = handle->wlr_seat->data_device; |  | ||||||
| 	struct wlr_data_source *source = wl_resource_get_user_data(source_resource); |  | ||||||
| 	wlr_data_device_set_selection(device, source); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct wl_data_device_interface data_device_impl = { |  | ||||||
| 	.start_drag = data_device_start_drag, |  | ||||||
| 	.set_selection = data_device_set_selection, |  | ||||||
| 	.release = resource_destroy |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void data_device_selection_destroy(struct wl_listener *listener, |  | ||||||
| 		void *data) { |  | ||||||
| 	struct wlr_data_device *device = |  | ||||||
| 		wl_container_of(listener, device, selection_destroyed); |  | ||||||
| 	assert(data == device->selection); |  | ||||||
| 	device->selection = NULL; // make sure no cancel is sent
 |  | ||||||
| 	wlr_data_device_set_selection(device, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct wlr_data_device *seat_ensure_data_device( |  | ||||||
| 		struct wlr_data_device_manager *manager, struct wlr_seat *seat) { |  | ||||||
| 	if (seat->data_device) { |  | ||||||
| 		return seat->data_device; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	seat->data_device = calloc(1, sizeof(*seat->data_device)); |  | ||||||
| 	if (!seat->data_device) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to allocate wlr_data_device"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	seat->data_device->seat = seat; |  | ||||||
| 	wl_signal_init(&seat->data_device->events.selection_change); |  | ||||||
| 	seat->data_device->selection_destroyed.notify = |  | ||||||
| 		data_device_selection_destroy; |  | ||||||
| 	return seat->data_device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_device_destroy(struct wl_resource *resource) { |  | ||||||
| 	struct wlr_seat_handle *handle = wl_resource_get_user_data(resource); |  | ||||||
| 	handle->data_device = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_device_manager_create_data_source(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, uint32_t id) { |  | ||||||
| 	uint32_t version = wl_resource_get_version(resource); |  | ||||||
| 	if (!wlr_wl_data_source_create(client, version, id)) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to create wlr_wl_data_source"); |  | ||||||
| 		wl_resource_post_no_memory(resource); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_device_manager_get_data_device(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, uint32_t id, |  | ||||||
| 		struct wl_resource *seat_resource) { |  | ||||||
| 	struct wlr_data_device_manager *manager = |  | ||||||
| 		wl_resource_get_user_data(resource); |  | ||||||
| 	struct wlr_seat_handle *seat_handle = |  | ||||||
| 		wl_resource_get_user_data(seat_resource); |  | ||||||
| 	struct wlr_data_device *device; |  | ||||||
| 	if (!(device = seat_ensure_data_device(manager, seat_handle->wlr_seat))) { |  | ||||||
| 		wl_resource_post_no_memory(resource); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (seat_handle->data_device) { |  | ||||||
| 		// TODO: implement resource lists for seat related handles
 |  | ||||||
| 		//   this is a protocol violation, see the todos in wlr_seat.c
 |  | ||||||
| 		wl_resource_destroy(seat_handle->data_device); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	seat_handle->data_device = wl_resource_create(client, |  | ||||||
| 		&wl_data_device_interface, wl_resource_get_version(resource), id); |  | ||||||
| 	if (!seat_handle->data_device) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to create wl_data_device resource"); |  | ||||||
| 		wl_resource_post_no_memory(resource); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	wl_resource_set_implementation(seat_handle->data_device, &data_device_impl, |  | ||||||
| 		seat_handle, data_device_destroy); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct wl_data_device_manager_interface data_device_manager_impl = { |  | ||||||
| 	.create_data_source = data_device_manager_create_data_source, |  | ||||||
| 	.get_data_device = data_device_manager_get_data_device |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void data_device_manager_bind(struct wl_client *client, void *data, |  | ||||||
| 		uint32_t version, uint32_t id) { |  | ||||||
| 	struct wlr_data_device_manager *manager = data; |  | ||||||
| 	assert(client && manager); |  | ||||||
| 	if (version > 3) { |  | ||||||
| 		wlr_log(L_ERROR, "Client requested unsupported data_device_manager " |  | ||||||
| 			"version, disconnecting"); |  | ||||||
| 		wl_client_destroy(client); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	struct wl_resource *resource = wl_resource_create( |  | ||||||
| 			client, &wl_data_device_manager_interface, version, id); |  | ||||||
| 	if (!resource) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to allocate wl_data_device_manager resource"); |  | ||||||
| 		wl_client_post_no_memory(client); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	wl_resource_set_implementation(resource, &data_device_manager_impl, |  | ||||||
| 		manager, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct wlr_data_device_manager *wlr_data_device_manager_create( |  | ||||||
| 		struct wl_display *display) { |  | ||||||
| 	struct wlr_data_device_manager *manager = calloc(1, sizeof(*manager)); |  | ||||||
| 	if (!manager) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to allocated wlr_data_device_manager"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	manager->global = |  | ||||||
| 		wl_global_create(display, &wl_data_device_manager_interface, 3, manager, |  | ||||||
| 			data_device_manager_bind); |  | ||||||
| 
 |  | ||||||
| 	if (!manager->global) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to create global for wlr_data_device_manager"); |  | ||||||
| 		free(manager); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return manager; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) { |  | ||||||
| 	if (manager) { |  | ||||||
| 		wl_global_destroy(manager->global); |  | ||||||
| 		free(manager); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_device_set_selection(struct wlr_data_device *device, |  | ||||||
| 		struct wlr_data_source *source) { |  | ||||||
| 	if (device->selection == source) { |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (device->selection) { |  | ||||||
| 		wl_list_remove(&device->selection_destroyed.link); |  | ||||||
| 		wlr_data_source_cancelled(device->selection); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	device->selection = source; |  | ||||||
| 	wl_signal_emit(&device->events.selection_change, device); |  | ||||||
| 
 |  | ||||||
| 	if (source) { |  | ||||||
| 		wl_signal_add(&source->events.destroy, &device->selection_destroyed); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,140 +0,0 @@ | |||||||
| #define _XOPEN_SOURCE 700 |  | ||||||
| #include <assert.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <unistd.h> |  | ||||||
| #include <wayland-server.h> |  | ||||||
| #include <wlr/util/list.h> |  | ||||||
| #include <wlr/util/log.h> |  | ||||||
| #include <wlr/types/wlr_data_source.h> |  | ||||||
| #include <wlr/types/wlr_data_device_manager.h> |  | ||||||
| #include <wlr/interfaces/wlr_data_source.h> |  | ||||||
| 
 |  | ||||||
| bool wlr_data_source_init(struct wlr_data_source *source, |  | ||||||
| 		struct wlr_data_source_impl *impl) { |  | ||||||
| 	source->impl = impl; |  | ||||||
| 	wl_signal_init(&source->events.destroy); |  | ||||||
| 	return (source->types = list_create()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_source_finish(struct wlr_data_source *source) { |  | ||||||
| 	if (source) { |  | ||||||
| 		wl_signal_emit(&source->events.destroy, source); |  | ||||||
| 		if (source->types) { |  | ||||||
| 			list_foreach(source->types, free); |  | ||||||
| 		} |  | ||||||
| 		list_free(source->types); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_source_send(struct wlr_data_source *src, const char *type, |  | ||||||
| 		int fd) { |  | ||||||
| 	assert(src && src->impl && src->impl->send); |  | ||||||
| 	src->impl->send(src, type, fd); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_source_accepted(struct wlr_data_source *src, const char *type) { |  | ||||||
| 	assert(src && src->impl); |  | ||||||
| 	if (src->impl->accepted) { |  | ||||||
| 		src->impl->accepted(src, type); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void wlr_data_source_cancelled(struct wlr_data_source *src) { |  | ||||||
| 	assert(src && src->impl); |  | ||||||
| 	if (src->impl->cancelled) { |  | ||||||
| 		src->impl->cancelled(src); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_source_send(struct wlr_data_source *src, |  | ||||||
| 		const char *type, int fd) { |  | ||||||
| 	struct wlr_wl_data_source *wl_src = (struct wlr_wl_data_source *) src; |  | ||||||
| 	wl_data_source_send_send(wl_src->resource, type, fd); |  | ||||||
| 	close(fd); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_source_accepted(struct wlr_data_source *src, |  | ||||||
| 		const char *type) { |  | ||||||
| 	struct wlr_wl_data_source *wl_src = (struct wlr_wl_data_source *) src; |  | ||||||
| 	wl_data_source_send_target(wl_src->resource, type); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_source_cancelled(struct wlr_data_source *src) { |  | ||||||
| 	struct wlr_wl_data_source *wl_src = (struct wlr_wl_data_source *) src; |  | ||||||
| 	wl_data_source_send_cancelled(wl_src->resource); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct wlr_data_source_impl data_source_wl_impl = { |  | ||||||
| 	.send = data_source_send, |  | ||||||
| 	.accepted = data_source_accepted, |  | ||||||
| 	.cancelled = data_source_cancelled, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void data_source_offer(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, |  | ||||||
| 		const char *type) { |  | ||||||
| 	struct wlr_wl_data_source *src = wl_resource_get_user_data(resource); |  | ||||||
| 	char *dtype = strdup(type); |  | ||||||
| 	if (!dtype) { |  | ||||||
| 		wl_resource_post_no_memory(resource); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	list_add(src->base.types, dtype); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_source_destroy(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource) { |  | ||||||
| 	wl_resource_destroy(resource); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void data_source_set_actions(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, uint32_t dnd_actions) { |  | ||||||
| 	wlr_log(L_DEBUG, "TODO: data source set actions"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct wl_data_source_interface wl_data_source_impl = { |  | ||||||
| 	.offer = data_source_offer, |  | ||||||
| 	.destroy = data_source_destroy, |  | ||||||
| 	.set_actions = data_source_set_actions, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void destroy_wl_data_source(struct wl_resource *resource) { |  | ||||||
| 	struct wlr_wl_data_source *src = wl_resource_get_user_data(resource); |  | ||||||
| 	wlr_data_source_finish(&src->base); |  | ||||||
| 	free(src); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct wlr_wl_data_source *wlr_wl_data_source_create( |  | ||||||
| 		struct wl_client *client, |  | ||||||
| 		uint32_t version, uint32_t id) { |  | ||||||
| 	struct wlr_wl_data_source *src = calloc(1, sizeof(*src)); |  | ||||||
| 	if (!src) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to allocator wlr_wl_data_source"); |  | ||||||
| 		wl_client_post_no_memory(client); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!wlr_data_source_init(&src->base, &data_source_wl_impl)) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to init wlr_wl_data_source"); |  | ||||||
| 		wl_client_post_no_memory(client); |  | ||||||
| 		goto err; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!(src->resource = wl_resource_create(client, &wl_data_source_interface, |  | ||||||
| 			version, id))) { |  | ||||||
| 		wlr_log(L_ERROR, "Failed to create wl_resource for wlr_wl_data_source"); |  | ||||||
| 		wl_client_post_no_memory(client); |  | ||||||
| 		goto err; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	wl_resource_set_implementation(src->resource, &wl_data_source_impl, src, |  | ||||||
| 		destroy_wl_data_source); |  | ||||||
| 	return src; |  | ||||||
| 
 |  | ||||||
| err: |  | ||||||
| 	wlr_data_source_finish(&src->base); |  | ||||||
| 	free(src); |  | ||||||
| 	return NULL; |  | ||||||
| } |  | ||||||
					Loading…
					
					
				
		Reference in new issue