primary-selection: introduce wlr_primary_selection_source
This is a common interface that can be used for all primary selection protocols, as discussed in [1]. A new function wlr_seat_set_primary_selection is added to set the primary selection for all protocols. The seat now owns again the source, and resets the selection to NULL when destroyed. [1]: https://github.com/swaywm/wlroots/issues/1367#issuecomment-442403454
This commit is contained in:
		
							parent
							
								
									658b590567
								
							
						
					
					
						commit
						9f0720c03a
					
				|  | @ -23,6 +23,7 @@ install_headers( | |||
| 	'wlr_output.h', | ||||
| 	'wlr_pointer.h', | ||||
| 	'wlr_presentation_time.h', | ||||
| 	'wlr_primary_selection.h', | ||||
| 	'wlr_region.h', | ||||
| 	'wlr_screencopy_v1.h', | ||||
| 	'wlr_screenshooter.h', | ||||
|  |  | |||
|  | @ -35,37 +35,11 @@ struct wlr_gtk_primary_selection_device { | |||
| 	struct wl_list link; // wlr_gtk_primary_selection_device_manager::devices
 | ||||
| 	struct wl_list resources; // wl_resource_get_link
 | ||||
| 
 | ||||
| 	struct wlr_gtk_primary_selection_source *source; | ||||
| 	struct wl_list offers; // wl_resource_get_link
 | ||||
| 
 | ||||
| 	struct wl_listener seat_destroy; | ||||
| 	struct wl_listener seat_focus_change; | ||||
| 	struct wl_listener source_destroy; | ||||
| 
 | ||||
| 	void *data; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * A data source implementation. Only the `send` function is mandatory. | ||||
|  */ | ||||
| struct wlr_gtk_primary_selection_source_impl { | ||||
| 	void (*send)(struct wlr_gtk_primary_selection_source *source, | ||||
| 		const char *mime_type, int fd); | ||||
| 	void (*destroy)(struct wlr_gtk_primary_selection_source *source); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * A source is the sending side of a selection. | ||||
|  */ | ||||
| struct wlr_gtk_primary_selection_source { | ||||
| 	const struct wlr_gtk_primary_selection_source_impl *impl; | ||||
| 
 | ||||
| 	// source metadata
 | ||||
| 	struct wl_array mime_types; | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal destroy; | ||||
| 	} events; | ||||
| 	struct wl_listener seat_primary_selection; | ||||
| 
 | ||||
| 	void *data; | ||||
| }; | ||||
|  | @ -75,18 +49,4 @@ struct wlr_gtk_primary_selection_device_manager * | |||
| void wlr_gtk_primary_selection_device_manager_destroy( | ||||
| 	struct wlr_gtk_primary_selection_device_manager *manager); | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_device_manager_set_selection( | ||||
| 	struct wlr_gtk_primary_selection_device_manager *manager, | ||||
| 	struct wlr_seat *seat, | ||||
| 	struct wlr_gtk_primary_selection_source *source); | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_source_init( | ||||
| 	struct wlr_gtk_primary_selection_source *source, | ||||
| 	const struct wlr_gtk_primary_selection_source_impl *impl); | ||||
| void wlr_gtk_primary_selection_source_destroy( | ||||
| 	struct wlr_gtk_primary_selection_source *source); | ||||
| void wlr_gtk_primary_selection_source_send( | ||||
| 	struct wlr_gtk_primary_selection_source *source, const char *mime_type, | ||||
| 	int fd); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -0,0 +1,54 @@ | |||
| /*
 | ||||
|  * This an unstable interface of wlroots. No guarantees are made regarding the | ||||
|  * future consistency of this API. | ||||
|  */ | ||||
| #ifndef WLR_USE_UNSTABLE | ||||
| #error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" | ||||
| #endif | ||||
| 
 | ||||
| #ifndef WLR_TYPES_WLR_PRIMARY_SELECTION_H | ||||
| #define WLR_TYPES_WLR_PRIMARY_SELECTION_H | ||||
| 
 | ||||
| #include <wayland-server.h> | ||||
| #include <wlr/types/wlr_seat.h> | ||||
| 
 | ||||
| struct wlr_primary_selection_source; | ||||
| 
 | ||||
| /**
 | ||||
|  * A data source implementation. Only the `send` function is mandatory. | ||||
|  */ | ||||
| struct wlr_primary_selection_source_impl { | ||||
| 	void (*send)(struct wlr_primary_selection_source *source, | ||||
| 		const char *mime_type, int fd); | ||||
| 	void (*destroy)(struct wlr_primary_selection_source *source); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * A source is the sending side of a selection. | ||||
|  */ | ||||
| struct wlr_primary_selection_source { | ||||
| 	const struct wlr_primary_selection_source_impl *impl; | ||||
| 
 | ||||
| 	// source metadata
 | ||||
| 	struct wl_array mime_types; | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal destroy; | ||||
| 	} events; | ||||
| 
 | ||||
| 	void *data; | ||||
| }; | ||||
| 
 | ||||
| void wlr_primary_selection_source_init( | ||||
| 	struct wlr_primary_selection_source *source, | ||||
| 	const struct wlr_primary_selection_source_impl *impl); | ||||
| void wlr_primary_selection_source_destroy( | ||||
| 	struct wlr_primary_selection_source *source); | ||||
| void wlr_primary_selection_source_send( | ||||
| 	struct wlr_primary_selection_source *source, const char *mime_type, | ||||
| 	int fd); | ||||
| 
 | ||||
| void wlr_seat_set_primary_selection(struct wlr_seat *seat, | ||||
| 	struct wlr_primary_selection_source *source); | ||||
| 
 | ||||
| #endif | ||||
|  | @ -184,6 +184,8 @@ struct wlr_seat_touch_state { | |||
| 	struct wlr_seat_touch_grab *default_grab; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_primary_selection_source; | ||||
| 
 | ||||
| struct wlr_seat { | ||||
| 	struct wl_global *global; | ||||
| 	struct wl_display *display; | ||||
|  | @ -197,8 +199,7 @@ struct wlr_seat { | |||
| 	struct wlr_data_source *selection_source; | ||||
| 	uint32_t selection_serial; | ||||
| 
 | ||||
| 	// not owned by the seat
 | ||||
| 	struct wlr_gtk_primary_selection_source *primary_selection_source; | ||||
| 	struct wlr_primary_selection_source *primary_selection_source; | ||||
| 
 | ||||
| 	// `drag` goes away before `drag_source`, when the implicit grab ends
 | ||||
| 	struct wlr_drag *drag; | ||||
|  | @ -211,6 +212,7 @@ struct wlr_seat { | |||
| 
 | ||||
| 	struct wl_listener display_destroy; | ||||
| 	struct wl_listener selection_source_destroy; | ||||
| 	struct wl_listener primary_selection_source_destroy; | ||||
| 	struct wl_listener drag_source_destroy; | ||||
| 
 | ||||
| 	struct { | ||||
|  |  | |||
|  | @ -43,7 +43,6 @@ struct wlr_xwayland { | |||
| 	struct wl_display *wl_display; | ||||
| 	struct wlr_compositor *compositor; | ||||
| 	struct wlr_seat *seat; | ||||
| 	struct wlr_gtk_primary_selection_device_manager *gtk_primary_selection; | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal ready; | ||||
|  | @ -226,10 +225,6 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface, | |||
| void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, | ||||
| 	struct wlr_seat *seat); | ||||
| 
 | ||||
| void wlr_xwayland_set_gtk_primary_selection_device_manager( | ||||
| 	struct wlr_xwayland *xwayland, | ||||
| 	struct wlr_gtk_primary_selection_device_manager *manager); | ||||
| 
 | ||||
| bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface); | ||||
| 
 | ||||
| struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ | |||
| 
 | ||||
| #define XDND_VERSION 5 | ||||
| 
 | ||||
| struct wlr_primary_selection_source; | ||||
| 
 | ||||
| struct wlr_xwm_selection; | ||||
| 
 | ||||
| struct wlr_xwm_selection_transfer { | ||||
|  | @ -62,7 +64,7 @@ int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm, | |||
| 	xcb_xfixes_selection_notify_event_t *event); | ||||
| bool data_source_is_xwayland(struct wlr_data_source *wlr_source); | ||||
| bool primary_selection_source_is_xwayland( | ||||
| 	struct wlr_gtk_primary_selection_source *wlr_source); | ||||
| 	struct wlr_primary_selection_source *wlr_source); | ||||
| 
 | ||||
| void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag); | ||||
| 
 | ||||
|  |  | |||
|  | @ -957,16 +957,8 @@ struct roots_desktop *desktop_create(struct roots_server *server, | |||
| 		WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT); | ||||
| 	desktop->idle = wlr_idle_create(server->wl_display); | ||||
| 	desktop->idle_inhibit = wlr_idle_inhibit_v1_create(server->wl_display); | ||||
| 
 | ||||
| 	desktop->primary_selection_device_manager = | ||||
| 		wlr_gtk_primary_selection_device_manager_create(server->wl_display); | ||||
| #if WLR_HAS_XWAYLAND | ||||
| 	if (desktop->xwayland != NULL) { | ||||
| 		wlr_xwayland_set_gtk_primary_selection_device_manager( | ||||
| 			desktop->xwayland, desktop->primary_selection_device_manager); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	desktop->input_inhibit = | ||||
| 		wlr_input_inhibit_manager_create(server->wl_display); | ||||
| 	desktop->input_inhibit_activate.notify = input_inhibit_activate; | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ lib_wlr_types = static_library( | |||
| 		'wlr_export_dmabuf_v1.c', | ||||
| 		'wlr_gamma_control_v1.c', | ||||
| 		'wlr_gamma_control.c', | ||||
| 		'wlr_gtk_primary_selection.c', | ||||
| 		'wlr_idle_inhibit_v1.c', | ||||
| 		'wlr_idle.c', | ||||
| 		'wlr_input_device.c', | ||||
|  | @ -46,7 +47,7 @@ lib_wlr_types = static_library( | |||
| 		'wlr_pointer_constraints_v1.c', | ||||
| 		'wlr_pointer.c', | ||||
| 		'wlr_presentation_time.c', | ||||
| 		'wlr_gtk_primary_selection.c', | ||||
| 		'wlr_primary_selection.c', | ||||
| 		'wlr_region.c', | ||||
| 		'wlr_screencopy_v1.c', | ||||
| 		'wlr_screenshooter.c', | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| #include <wayland-server.h> | ||||
| #include <wlr/types/wlr_data_device.h> | ||||
| #include <wlr/types/wlr_input_device.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include <wlr/types/wlr_seat.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include "types/wlr_seat.h" | ||||
|  | @ -162,6 +163,8 @@ void wlr_seat_destroy(struct wlr_seat *seat) { | |||
| 		seat->selection_source = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_seat_set_primary_selection(seat, NULL); | ||||
| 
 | ||||
| 	struct wlr_seat_client *client, *tmp; | ||||
| 	wl_list_for_each_safe(client, tmp, &seat->clients, link) { | ||||
| 		struct wl_resource *resource, *next; | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/types/wlr_gtk_primary_selection.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include <wlr/types/wlr_seat.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include "gtk-primary-selection-protocol.h" | ||||
|  | @ -24,12 +25,13 @@ static void offer_handle_receive(struct wl_client *client, | |||
| 		struct wl_resource *resource, const char *mime_type, int32_t fd) { | ||||
| 	struct wlr_gtk_primary_selection_device *device = | ||||
| 		device_from_offer_resource(resource); | ||||
| 	if (device == NULL || device->source == NULL) { | ||||
| 	if (device == NULL || device->seat->primary_selection_source == NULL) { | ||||
| 		close(fd); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_gtk_primary_selection_source_send(device->source, mime_type, fd); | ||||
| 	wlr_primary_selection_source_send(device->seat->primary_selection_source, | ||||
| 		mime_type, fd); | ||||
| } | ||||
| 
 | ||||
| static void offer_handle_destroy(struct wl_client *client, | ||||
|  | @ -50,7 +52,7 @@ static struct wlr_gtk_primary_selection_device *device_from_resource( | |||
| 	struct wl_resource *resource); | ||||
| 
 | ||||
| static void create_offer(struct wl_resource *device_resource, | ||||
| 		struct wlr_gtk_primary_selection_source *source) { | ||||
| 		struct wlr_primary_selection_source *source) { | ||||
| 	struct wlr_gtk_primary_selection_device *device = | ||||
| 		device_from_resource(device_resource); | ||||
| 	assert(device != NULL); | ||||
|  | @ -93,12 +95,12 @@ static void destroy_offer(struct wl_resource *resource) { | |||
| 
 | ||||
| 
 | ||||
| struct client_data_source { | ||||
| 	struct wlr_gtk_primary_selection_source source; | ||||
| 	struct wlr_primary_selection_source source; | ||||
| 	struct wl_resource *resource; | ||||
| }; | ||||
| 
 | ||||
| static void client_source_send( | ||||
| 		struct wlr_gtk_primary_selection_source *wlr_source, | ||||
| 		struct wlr_primary_selection_source *wlr_source, | ||||
| 		const char *mime_type, int fd) { | ||||
| 	struct client_data_source *source = (struct client_data_source *)wlr_source; | ||||
| 	gtk_primary_selection_source_send_send(source->resource, mime_type, fd); | ||||
|  | @ -106,7 +108,7 @@ static void client_source_send( | |||
| } | ||||
| 
 | ||||
| static void client_source_destroy( | ||||
| 		struct wlr_gtk_primary_selection_source *wlr_source) { | ||||
| 		struct wlr_primary_selection_source *wlr_source) { | ||||
| 	struct client_data_source *source = (struct client_data_source *)wlr_source; | ||||
| 	gtk_primary_selection_source_send_cancelled(source->resource); | ||||
| 	// Make the source resource inert
 | ||||
|  | @ -114,7 +116,7 @@ static void client_source_destroy( | |||
| 	free(source); | ||||
| } | ||||
| 
 | ||||
| static const struct wlr_gtk_primary_selection_source_impl client_source_impl = { | ||||
| static const struct wlr_primary_selection_source_impl client_source_impl = { | ||||
| 	.send = client_source_send, | ||||
| 	.destroy = client_source_destroy, | ||||
| }; | ||||
|  | @ -136,16 +138,20 @@ static void source_handle_offer(struct wl_client *client, | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	char **p = wl_array_add(&source->source.mime_types, sizeof(*p)); | ||||
| 	if (p) { | ||||
| 		*p = strdup(mime_type); | ||||
| 	} | ||||
| 	if (p == NULL || *p == NULL) { | ||||
| 		if (p) { | ||||
| 			source->source.mime_types.size -= sizeof(*p); | ||||
| 		} | ||||
| 	char *dup_mime_type = strdup(mime_type); | ||||
| 	if (dup_mime_type == NULL) { | ||||
| 		wl_resource_post_no_memory(resource); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	char **p = wl_array_add(&source->source.mime_types, sizeof(*p)); | ||||
| 	if (p == NULL) { | ||||
| 		free(dup_mime_type); | ||||
| 		wl_resource_post_no_memory(resource); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	*p = dup_mime_type; | ||||
| } | ||||
| 
 | ||||
| static void source_handle_destroy(struct wl_client *client, | ||||
|  | @ -164,7 +170,7 @@ static void source_resource_handle_destroy(struct wl_resource *resource) { | |||
| 	if (source == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 	wlr_gtk_primary_selection_source_destroy(&source->source); | ||||
| 	wlr_primary_selection_source_destroy(&source->source); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -191,15 +197,14 @@ static void device_handle_set_selection(struct wl_client *client, | |||
| 		client_source = client_data_source_from_resource(source_resource); | ||||
| 	} | ||||
| 
 | ||||
| 	struct wlr_gtk_primary_selection_source *source = NULL; | ||||
| 	struct wlr_primary_selection_source *source = NULL; | ||||
| 	if (client_source != NULL) { | ||||
| 		source = &client_source->source; | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO: improve serial checking
 | ||||
| 	struct wlr_seat *seat = device->seat; | ||||
| 	wlr_gtk_primary_selection_device_manager_set_selection(device->manager, | ||||
| 		seat, source); | ||||
| 	// TODO: serial checking
 | ||||
| 
 | ||||
| 	wlr_seat_set_primary_selection(device->seat, source); | ||||
| } | ||||
| 
 | ||||
| static void device_handle_destroy(struct wl_client *client, | ||||
|  | @ -218,7 +223,7 @@ static void device_handle_resource_destroy(struct wl_resource *resource) { | |||
| 
 | ||||
| 
 | ||||
| static void device_resource_send_selection(struct wl_resource *resource, | ||||
| 		struct wlr_gtk_primary_selection_source *source) { | ||||
| 		struct wlr_primary_selection_source *source) { | ||||
| 	assert(device_from_resource(resource) != NULL); | ||||
| 
 | ||||
| 	if (source != NULL) { | ||||
|  | @ -239,42 +244,12 @@ static void device_send_selection( | |||
| 	struct wl_resource *resource; | ||||
| 	wl_resource_for_each(resource, &device->resources) { | ||||
| 		if (wl_resource_get_client(resource) == seat_client->client) { | ||||
| 			device_resource_send_selection(resource, device->source); | ||||
| 			device_resource_send_selection(resource, | ||||
| 				device->seat->primary_selection_source); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void device_handle_source_destroy(struct wl_listener *listener, | ||||
| 	void *data); | ||||
| 
 | ||||
| static void device_set_selection( | ||||
| 		struct wlr_gtk_primary_selection_device *device, | ||||
| 		struct wlr_gtk_primary_selection_source *source) { | ||||
| 	if (device->source != NULL) { | ||||
| 		wl_list_remove(&device->source_destroy.link); | ||||
| 		wlr_gtk_primary_selection_source_destroy(device->source); | ||||
| 		device->source = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wl_resource *resource, *tmp; | ||||
| 	wl_resource_for_each_safe(resource, tmp, &device->offers) { | ||||
| 		destroy_offer(resource); | ||||
| 	} | ||||
| 
 | ||||
| 	device->source = source; | ||||
| 	if (source != NULL) { | ||||
| 		device->source_destroy.notify = device_handle_source_destroy; | ||||
| 		wl_signal_add(&source->events.destroy, &device->source_destroy); | ||||
| 	} | ||||
| 
 | ||||
| 	device_send_selection(device); | ||||
| 
 | ||||
| 	struct wlr_seat *seat = device->seat; | ||||
| 	// TODO: remove these from wlr_seat
 | ||||
| 	seat->primary_selection_source = source; | ||||
| 	wlr_signal_emit_safe(&seat->events.primary_selection, seat); | ||||
| } | ||||
| 
 | ||||
| static void device_destroy(struct wlr_gtk_primary_selection_device *device); | ||||
| 
 | ||||
| static void device_handle_seat_destroy(struct wl_listener *listener, | ||||
|  | @ -293,12 +268,16 @@ static void device_handle_seat_focus_change(struct wl_listener *listener, | |||
| 	device_send_selection(device); | ||||
| } | ||||
| 
 | ||||
| static void device_handle_source_destroy(struct wl_listener *listener, | ||||
| static void device_handle_seat_primary_selection(struct wl_listener *listener, | ||||
| 		void *data) { | ||||
| 	struct wlr_gtk_primary_selection_device *device = | ||||
| 		wl_container_of(listener, device, source_destroy); | ||||
| 	wl_list_remove(&device->source_destroy.link); | ||||
| 	device->source = NULL; | ||||
| 		wl_container_of(listener, device, seat_primary_selection); | ||||
| 
 | ||||
| 	struct wl_resource *resource, *tmp; | ||||
| 	wl_resource_for_each_safe(resource, tmp, &device->offers) { | ||||
| 		destroy_offer(resource); | ||||
| 	} | ||||
| 
 | ||||
| 	device_send_selection(device); | ||||
| } | ||||
| 
 | ||||
|  | @ -331,6 +310,11 @@ static struct wlr_gtk_primary_selection_device *get_or_create_device( | |||
| 	wl_signal_add(&seat->keyboard_state.events.focus_change, | ||||
| 		&device->seat_focus_change); | ||||
| 
 | ||||
| 	device->seat_primary_selection.notify = | ||||
| 		device_handle_seat_primary_selection; | ||||
| 	wl_signal_add(&seat->events.primary_selection, | ||||
| 		&device->seat_primary_selection); | ||||
| 
 | ||||
| 	return device; | ||||
| } | ||||
| 
 | ||||
|  | @ -341,10 +325,7 @@ static void device_destroy(struct wlr_gtk_primary_selection_device *device) { | |||
| 	wl_list_remove(&device->link); | ||||
| 	wl_list_remove(&device->seat_destroy.link); | ||||
| 	wl_list_remove(&device->seat_focus_change.link); | ||||
| 	if (device->source != NULL) { | ||||
| 		wl_list_remove(&device->source_destroy.link); | ||||
| 		wlr_gtk_primary_selection_source_destroy(device->source); | ||||
| 	} | ||||
| 	wl_list_remove(&device->seat_primary_selection.link); | ||||
| 	struct wl_resource *resource, *resource_tmp; | ||||
| 	wl_resource_for_each_safe(resource, resource_tmp, &device->offers) { | ||||
| 		destroy_offer(resource); | ||||
|  | @ -379,7 +360,7 @@ static void device_manager_handle_create_source(struct wl_client *client, | |||
| 		wl_client_post_no_memory(client); | ||||
| 		return; | ||||
| 	} | ||||
| 	wlr_gtk_primary_selection_source_init(&source->source, &client_source_impl); | ||||
| 	wlr_primary_selection_source_init(&source->source, &client_source_impl); | ||||
| 
 | ||||
| 	uint32_t version = wl_resource_get_version(manager_resource); | ||||
| 	source->resource = wl_resource_create(client, | ||||
|  | @ -420,7 +401,8 @@ void device_manager_handle_get_device(struct wl_client *client, | |||
| 	wl_list_insert(&device->resources, wl_resource_get_link(resource)); | ||||
| 
 | ||||
| 	if (device->seat->keyboard_state.focused_client == seat_client) { | ||||
| 		device_resource_send_selection(resource, device->source); | ||||
| 		device_resource_send_selection(resource, | ||||
| 			device->seat->primary_selection_source); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -442,18 +424,6 @@ static void device_manager_handle_resource_destroy( | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_device_manager_set_selection( | ||||
| 		struct wlr_gtk_primary_selection_device_manager *manager, | ||||
| 		struct wlr_seat *seat, | ||||
| 		struct wlr_gtk_primary_selection_source *source) { | ||||
| 	struct wlr_gtk_primary_selection_device *device = | ||||
| 		get_or_create_device(manager, seat); | ||||
| 	if (device == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 	device_set_selection(device, source); | ||||
| } | ||||
| 
 | ||||
| static void primary_selection_device_manager_bind(struct wl_client *client, | ||||
| 		void *data, uint32_t version, uint32_t id) { | ||||
| 	struct wlr_gtk_primary_selection_device_manager *manager = data; | ||||
|  | @ -516,40 +486,3 @@ void wlr_gtk_primary_selection_device_manager_destroy( | |||
| 	wl_global_destroy(manager->global); | ||||
| 	free(manager); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_source_init( | ||||
| 		struct wlr_gtk_primary_selection_source *source, | ||||
| 		const struct wlr_gtk_primary_selection_source_impl *impl) { | ||||
| 	assert(impl->send); | ||||
| 	wl_array_init(&source->mime_types); | ||||
| 	wl_signal_init(&source->events.destroy); | ||||
| 	source->impl = impl; | ||||
| } | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_source_destroy( | ||||
| 		struct wlr_gtk_primary_selection_source *source) { | ||||
| 	if (source == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_signal_emit_safe(&source->events.destroy, source); | ||||
| 
 | ||||
| 	char **p; | ||||
| 	wl_array_for_each(p, &source->mime_types) { | ||||
| 		free(*p); | ||||
| 	} | ||||
| 	wl_array_release(&source->mime_types); | ||||
| 
 | ||||
| 	if (source->impl->destroy) { | ||||
| 		source->impl->destroy(source); | ||||
| 	} else { | ||||
| 		free(source); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void wlr_gtk_primary_selection_source_send( | ||||
| 		struct wlr_gtk_primary_selection_source *source, const char *mime_type, | ||||
| 		int32_t fd) { | ||||
| 	source->impl->send(source, mime_type, fd); | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,69 @@ | |||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include "util/signal.h" | ||||
| 
 | ||||
| void wlr_primary_selection_source_init( | ||||
| 		struct wlr_primary_selection_source *source, | ||||
| 		const struct wlr_primary_selection_source_impl *impl) { | ||||
| 	assert(impl->send); | ||||
| 	wl_array_init(&source->mime_types); | ||||
| 	wl_signal_init(&source->events.destroy); | ||||
| 	source->impl = impl; | ||||
| } | ||||
| 
 | ||||
| void wlr_primary_selection_source_destroy( | ||||
| 		struct wlr_primary_selection_source *source) { | ||||
| 	if (source == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_signal_emit_safe(&source->events.destroy, source); | ||||
| 
 | ||||
| 	char **p; | ||||
| 	wl_array_for_each(p, &source->mime_types) { | ||||
| 		free(*p); | ||||
| 	} | ||||
| 	wl_array_release(&source->mime_types); | ||||
| 
 | ||||
| 	if (source->impl->destroy) { | ||||
| 		source->impl->destroy(source); | ||||
| 	} else { | ||||
| 		free(source); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void wlr_primary_selection_source_send( | ||||
| 		struct wlr_primary_selection_source *source, const char *mime_type, | ||||
| 		int32_t fd) { | ||||
| 	source->impl->send(source, mime_type, fd); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void seat_handle_primary_selection_source_destroy( | ||||
| 		struct wl_listener *listener, void *data) { | ||||
| 	struct wlr_seat *seat = | ||||
| 		wl_container_of(listener, seat, primary_selection_source_destroy); | ||||
| 	wl_list_remove(&seat->primary_selection_source_destroy.link); | ||||
| 	seat->primary_selection_source = NULL; | ||||
| 	wlr_signal_emit_safe(&seat->events.primary_selection, seat); | ||||
| } | ||||
| 
 | ||||
| void wlr_seat_set_primary_selection(struct wlr_seat *seat, | ||||
| 		struct wlr_primary_selection_source *source) { | ||||
| 	if (seat->primary_selection_source != NULL) { | ||||
| 		wl_list_remove(&seat->primary_selection_source_destroy.link); | ||||
| 		wlr_primary_selection_source_destroy(seat->primary_selection_source); | ||||
| 		seat->primary_selection_source = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	seat->primary_selection_source = source; | ||||
| 	if (source != NULL) { | ||||
| 		seat->primary_selection_source_destroy.notify = | ||||
| 			seat_handle_primary_selection_source_destroy; | ||||
| 		wl_signal_add(&source->events.destroy, | ||||
| 			&seat->primary_selection_source_destroy); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_signal_emit_safe(&seat->events.primary_selection, seat); | ||||
| } | ||||
|  | @ -5,11 +5,11 @@ | |||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/types/wlr_data_device.h> | ||||
| #include <wlr/types/wlr_gtk_primary_selection.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xcb/xfixes.h> | ||||
| #include "xwayland/xwm.h" | ||||
| #include "xwayland/selection.h" | ||||
| #include "xwayland/xwm.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Write the X11 selection to a Wayland client. | ||||
|  | @ -217,21 +217,21 @@ static const struct wlr_data_source_impl data_source_impl = { | |||
| }; | ||||
| 
 | ||||
| struct x11_primary_selection_source { | ||||
| 	struct wlr_gtk_primary_selection_source base; | ||||
| 	struct wlr_primary_selection_source base; | ||||
| 	struct wlr_xwm_selection *selection; | ||||
| 	struct wl_array mime_types_atoms; | ||||
| }; | ||||
| 
 | ||||
| static const struct wlr_gtk_primary_selection_source_impl | ||||
| static const struct wlr_primary_selection_source_impl | ||||
| 	primary_selection_source_impl; | ||||
| 
 | ||||
| bool primary_selection_source_is_xwayland( | ||||
| 		struct wlr_gtk_primary_selection_source *wlr_source) { | ||||
| 		struct wlr_primary_selection_source *wlr_source) { | ||||
| 	return wlr_source->impl == &primary_selection_source_impl; | ||||
| } | ||||
| 
 | ||||
| static void primary_selection_source_send( | ||||
| 		struct wlr_gtk_primary_selection_source *wlr_source, | ||||
| 		struct wlr_primary_selection_source *wlr_source, | ||||
| 		const char *mime_type, int fd) { | ||||
| 	struct x11_primary_selection_source *source = | ||||
| 		(struct x11_primary_selection_source *)wlr_source; | ||||
|  | @ -242,14 +242,14 @@ static void primary_selection_source_send( | |||
| } | ||||
| 
 | ||||
| static void primary_selection_source_destroy( | ||||
| 		struct wlr_gtk_primary_selection_source *wlr_source) { | ||||
| 		struct wlr_primary_selection_source *wlr_source) { | ||||
| 	struct x11_primary_selection_source *source = | ||||
| 		(struct x11_primary_selection_source *)wlr_source; | ||||
| 	wl_array_release(&source->mime_types_atoms); | ||||
| 	free(source); | ||||
| } | ||||
| 
 | ||||
| static const struct wlr_gtk_primary_selection_source_impl | ||||
| static const struct wlr_primary_selection_source_impl | ||||
| 		primary_selection_source_impl = { | ||||
| 	.send = primary_selection_source_send, | ||||
| 	.destroy = primary_selection_source_destroy, | ||||
|  | @ -361,7 +361,7 @@ static void xwm_selection_get_targets(struct wlr_xwm_selection *selection) { | |||
| 		if (source == NULL) { | ||||
| 			return; | ||||
| 		} | ||||
| 		wlr_gtk_primary_selection_source_init(&source->base, | ||||
| 		wlr_primary_selection_source_init(&source->base, | ||||
| 			&primary_selection_source_impl); | ||||
| 
 | ||||
| 		source->selection = selection; | ||||
|  | @ -369,11 +369,10 @@ static void xwm_selection_get_targets(struct wlr_xwm_selection *selection) { | |||
| 
 | ||||
| 		bool ok = source_get_targets(selection, &source->base.mime_types, | ||||
| 			&source->mime_types_atoms); | ||||
| 		if (ok && xwm->xwayland->gtk_primary_selection) { | ||||
| 			wlr_gtk_primary_selection_device_manager_set_selection( | ||||
| 				xwm->xwayland->gtk_primary_selection, xwm->seat, &source->base); | ||||
| 		if (ok) { | ||||
| 			wlr_seat_set_primary_selection(xwm->seat, &source->base); | ||||
| 		} else { | ||||
| 			wlr_gtk_primary_selection_source_destroy(&source->base); | ||||
| 			wlr_primary_selection_source_destroy(&source->base); | ||||
| 		} | ||||
| 	} else if (selection == &xwm->dnd_selection) { | ||||
| 		// TODO
 | ||||
|  | @ -427,10 +426,8 @@ int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm, | |||
| 			if (selection == &xwm->clipboard_selection) { | ||||
| 				wlr_seat_set_selection(xwm->seat, NULL, | ||||
| 					wl_display_next_serial(xwm->xwayland->wl_display)); | ||||
| 			} else if (selection == &xwm->primary_selection && | ||||
| 					xwm->xwayland->gtk_primary_selection) { | ||||
| 				wlr_gtk_primary_selection_device_manager_set_selection( | ||||
| 					xwm->xwayland->gtk_primary_selection, xwm->seat, NULL); | ||||
| 			} else if (selection == &xwm->primary_selection) { | ||||
| 				wlr_seat_set_primary_selection(xwm->seat, NULL); | ||||
| 			} else if (selection == &xwm->dnd_selection) { | ||||
| 				// TODO: DND
 | ||||
| 			} else { | ||||
|  |  | |||
|  | @ -4,11 +4,11 @@ | |||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/types/wlr_data_device.h> | ||||
| #include <wlr/types/wlr_gtk_primary_selection.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xcb/xfixes.h> | ||||
| #include "xwayland/xwm.h" | ||||
| #include "xwayland/selection.h" | ||||
| #include "xwayland/xwm.h" | ||||
| 
 | ||||
| static void xwm_selection_send_notify(struct wlr_xwm *xwm, | ||||
| 		xcb_selection_request_event_t *req, bool success) { | ||||
|  | @ -195,10 +195,10 @@ static void xwm_selection_source_send(struct wlr_xwm_selection *selection, | |||
| 			return; | ||||
| 		} | ||||
| 	} else if (selection == &selection->xwm->primary_selection) { | ||||
| 		struct wlr_gtk_primary_selection_source *source = | ||||
| 		struct wlr_primary_selection_source *source = | ||||
| 			selection->xwm->seat->primary_selection_source; | ||||
| 		if (source != NULL) { | ||||
| 			wlr_gtk_primary_selection_source_send(source, mime_type, fd); | ||||
| 			wlr_primary_selection_source_send(source, mime_type, fd); | ||||
| 			return; | ||||
| 		} | ||||
| 	} else if (selection == &selection->xwm->dnd_selection) { | ||||
|  | @ -231,7 +231,7 @@ static struct wl_array *xwm_selection_source_get_mime_types( | |||
| 			return &source->mime_types; | ||||
| 		} | ||||
| 	} else if (selection == &selection->xwm->primary_selection) { | ||||
| 		struct wlr_gtk_primary_selection_source *source = | ||||
| 		struct wlr_primary_selection_source *source = | ||||
| 			selection->xwm->seat->primary_selection_source; | ||||
| 		if (source != NULL) { | ||||
| 			return &source->mime_types; | ||||
|  |  | |||
|  | @ -5,11 +5,11 @@ | |||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/types/wlr_data_device.h> | ||||
| #include <wlr/types/wlr_gtk_primary_selection.h> | ||||
| #include <wlr/types/wlr_primary_selection.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xcb/xfixes.h> | ||||
| #include "xwayland/xwm.h" | ||||
| #include "xwayland/selection.h" | ||||
| #include "xwayland/xwm.h" | ||||
| 
 | ||||
| void xwm_selection_transfer_remove_source( | ||||
| 		struct wlr_xwm_selection_transfer *transfer) { | ||||
|  | @ -228,12 +228,10 @@ void xwm_selection_finish(struct wlr_xwm *xwm) { | |||
| 			wlr_seat_set_selection(xwm->seat, NULL, | ||||
| 				wl_display_next_serial(xwm->xwayland->wl_display)); | ||||
| 		} | ||||
| 		if (xwm->xwayland->gtk_primary_selection && | ||||
| 				xwm->seat->primary_selection_source && | ||||
| 		if (xwm->seat->primary_selection_source && | ||||
| 				primary_selection_source_is_xwayland( | ||||
| 					xwm->seat->primary_selection_source)) { | ||||
| 			wlr_gtk_primary_selection_device_manager_set_selection( | ||||
| 				xwm->xwayland->gtk_primary_selection, xwm->seat, NULL); | ||||
| 			wlr_seat_set_primary_selection(xwm->seat, NULL); | ||||
| 		} | ||||
| 		wlr_xwayland_set_seat(xwm->xwayland, NULL); | ||||
| 	} | ||||
|  | @ -275,11 +273,10 @@ static void seat_handle_primary_selection(struct wl_listener *listener, | |||
| 	struct wlr_seat *seat = data; | ||||
| 	struct wlr_xwm *xwm = | ||||
| 		wl_container_of(listener, xwm, seat_primary_selection); | ||||
| 	struct wlr_gtk_primary_selection_source *source = seat->primary_selection_source; | ||||
| 	struct wlr_primary_selection_source *source = | ||||
| 		seat->primary_selection_source; | ||||
| 
 | ||||
| 	if (source != NULL && | ||||
| 			primary_selection_source_is_xwayland( | ||||
| 				source)) { | ||||
| 	if (source != NULL && primary_selection_source_is_xwayland(source)) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -505,9 +505,3 @@ void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, | |||
| 	xwayland->seat_destroy.notify = xwayland_handle_seat_destroy; | ||||
| 	wl_signal_add(&seat->events.destroy, &xwayland->seat_destroy); | ||||
| } | ||||
| 
 | ||||
| void wlr_xwayland_set_gtk_primary_selection_device_manager( | ||||
| 		struct wlr_xwayland *xwayland, | ||||
| 		struct wlr_gtk_primary_selection_device_manager *manager) { | ||||
| 	xwayland->gtk_primary_selection = manager; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue