diff options
| author | emersion <contact@emersion.fr> | 2018-03-29 17:53:13 -0400 | 
|---|---|---|
| committer | emersion <contact@emersion.fr> | 2018-03-29 17:53:13 -0400 | 
| commit | d5f46f4db4b646faad33f91b1677e46665871e6e (patch) | |
| tree | 42d1b0120a0189c05c238df1c8d696033c258534 | |
| parent | 79dd4a0ff98f6467c414903fc14112ab73345389 (diff) | |
| download | wlroots-d5f46f4db4b646faad33f91b1677e46665871e6e.tar.xz | |
data-device: redesign wlr_data_source
| -rw-r--r-- | include/wlr/types/wlr_data_device.h | 82 | ||||
| -rw-r--r-- | types/wlr_data_device.c | 180 | ||||
| -rw-r--r-- | types/wlr_seat.c | 4 | 
3 files changed, 193 insertions, 73 deletions
| diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index 6733980a..6fb41c29 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -30,23 +30,29 @@ struct wlr_data_offer {  	struct wl_listener source_destroy;  }; -struct wlr_data_source { -	// source metadata -	struct wl_array mime_types; -	int32_t actions; - -	// source implementation +/** + * A data source implementation. Only the `send` function is mandatory. Refer to + * the matching wl_data_source_* functions documentation to know what they do. + */ +struct wlr_data_source_impl {  	void (*send)(struct wlr_data_source *source, const char *mime_type,  		int32_t fd);  	void (*accept)(struct wlr_data_source *source, uint32_t serial,  		const char *mime_type);  	void (*cancel)(struct wlr_data_source *source); -	// drag'n'drop implementation  	void (*dnd_drop)(struct wlr_data_source *source);  	void (*dnd_finish)(struct wlr_data_source *source);  	void (*dnd_action)(struct wlr_data_source *source,  		enum wl_data_device_manager_dnd_action action); +}; + +struct wlr_data_source { +	const struct wlr_data_source_impl *impl; + +	// source metadata +	struct wl_array mime_types; +	int32_t actions;  	// source status  	bool accepted; @@ -128,7 +134,7 @@ struct wlr_drag_drop_event {   * Create a wl data device manager global for this display.   */  struct wlr_data_device_manager *wlr_data_device_manager_create( -		struct wl_display *display); +	struct wl_display *display);  /**   * Destroys a wlr_data_device_manager and removes its wl_data_device_manager global. @@ -144,11 +150,67 @@ void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager);   */  void wlr_seat_client_send_selection(struct wlr_seat_client *seat_client); +/** + * Sets the current selection for the seat. This removes the previous one if + * there was any. + */  void wlr_seat_set_selection(struct wlr_seat *seat, -		struct wlr_data_source *source, uint32_t serial); +	struct wlr_data_source *source, uint32_t serial); -void wlr_data_source_init(struct wlr_data_source *source); +/** + * Initializes the data source with the provided implementation. + */ +void wlr_data_source_init(struct wlr_data_source *source, +	const struct wlr_data_source_impl *impl); +/** + * Finishes the data source. + */  void wlr_data_source_finish(struct wlr_data_source *source); +/** + * Sends the data as the specified MIME type over the passed file descriptor, + * then close it. + */ +void wlr_data_source_send(struct wlr_data_source *source, const char *mime_type, +	int32_t fd); + +/** + * Notifies the data source that a target accepts one of the offered MIME types. + * If a target doesn't accept any of the offered types, `mime_type` is NULL. + */ +void wlr_data_source_accept(struct wlr_data_source *source, uint32_t serial, +	const char *mime_type); + +/** + * Notifies the data source it is no longer valid and should be destroyed. That + * potentially destroys immediately the data source. + */ +void wlr_data_source_cancel(struct wlr_data_source *source); + +/** + * Notifies the data source that the drop operation was performed. This does not + * indicate acceptance. + * + * The data source may still be used in the future and should not be destroyed + * here. + */ +void wlr_data_source_dnd_drop(struct wlr_data_source *source); + +/** + * Notifies the data source that the drag-and-drop operation concluded. That + * potentially destroys immediately the data source. + */ +void wlr_data_source_dnd_finish(struct wlr_data_source *source); + +/** + * Notifies the data source that a target accepts the drag with the specified + * action. + * + * This shouldn't be called after `wlr_data_source_dnd_drop` unless the + * drag-and-drop operation ended in an "ask" action. + */ +void wlr_data_source_dnd_action(struct wlr_data_source *source, +	enum wl_data_device_manager_dnd_action action); +  #endif diff --git a/types/wlr_data_device.c b/types/wlr_data_device.c index 3e78760b..13b1d08a 100644 --- a/types/wlr_data_device.c +++ b/types/wlr_data_device.c @@ -84,9 +84,7 @@ static void data_offer_update_action(struct wlr_data_offer *offer) {  		return;  	} -	if (offer->source->dnd_action) { -		offer->source->dnd_action(offer->source, action); -	} +	wlr_data_source_dnd_action(offer->source, action);  	if (wl_resource_get_version(offer->resource) >=  			WL_DATA_OFFER_ACTION_SINCE_VERSION) { @@ -104,10 +102,7 @@ static void data_offer_accept(struct wl_client *client,  	// TODO check that client is currently focused by the input device -	if (offer->source->accept) { -		offer->source->accept(offer->source, serial, mime_type); -	} -	offer->source->accepted = (mime_type != NULL); +	wlr_data_source_accept(offer->source, serial, mime_type);  }  static void data_offer_receive(struct wl_client *client, @@ -115,7 +110,7 @@ static void data_offer_receive(struct wl_client *client,  	struct wlr_data_offer *offer = data_offer_from_resource(resource);  	if (offer->source && offer == offer->source->offer) { -		offer->source->send(offer->source, mime_type, fd); +		wlr_data_source_send(offer->source, mime_type, fd);  	} else {  		close(fd);  	} @@ -131,15 +126,12 @@ static void data_source_notify_finish(struct wlr_data_source *source) {  		return;  	} -	if (source->offer->in_ask && source->dnd_action) { -		source->dnd_action(source, source->current_dnd_action); -	} - -	if (source->dnd_finish) { -		source->dnd_finish(source); +	if (source->offer->in_ask) { +		wlr_data_source_dnd_action(source, source->current_dnd_action);  	}  	source->offer = NULL; +	wlr_data_source_dnd_finish(source);  }  static void data_offer_finish(struct wl_client *client, @@ -199,10 +191,10 @@ static void data_offer_resource_destroy(struct wl_resource *resource) {  			WL_DATA_OFFER_ACTION_SINCE_VERSION) {  		data_source_notify_finish(offer->source);  		offer->source->offer = NULL; -	} else if (offer->source->dnd_finish) { +	} else if (offer->source->impl->dnd_finish) {  		// source->cancel can free the source  		offer->source->offer = NULL; -		offer->source->cancel(offer->source); +		wlr_data_source_cancel(offer->source);  	} else {  		offer->source->offer = NULL;  	} @@ -314,20 +306,15 @@ static void seat_client_selection_source_destroy(  void wlr_seat_set_selection(struct wlr_seat *seat,  		struct wlr_data_source *source, uint32_t serial) { -	if (source) { -		assert(source->send); -		assert(source->cancel); -	} -  	if (seat->selection_source &&  			seat->selection_serial - serial < UINT32_MAX / 2) {  		return;  	}  	if (seat->selection_source) { -		seat->selection_source->cancel(seat->selection_source); -		seat->selection_source = NULL;  		wl_list_remove(&seat->selection_source_destroy.link); +		wlr_data_source_cancel(seat->selection_source); +		seat->selection_source = NULL;  	}  	seat->selection_source = source; @@ -533,9 +520,7 @@ static uint32_t pointer_drag_button(struct wlr_seat_pointer_grab *grab,  			wl_resource_for_each(resource, &drag->focus_client->data_devices) {  				wl_data_device_send_drop(resource);  			} -			if (drag->source->dnd_drop) { -				drag->source->dnd_drop(drag->source); -			} +			wlr_data_source_dnd_drop(drag->source);  			if (drag->source->offer != NULL) {  				drag->source->offer->in_ask = @@ -548,8 +533,8 @@ static uint32_t pointer_drag_button(struct wlr_seat_pointer_grab *grab,  				.time = time,  			};  			wlr_signal_emit_safe(&drag->events.drop, &event); -		} else if (drag->source->dnd_finish) { -			drag->source->cancel(drag->source); +		} else if (drag->source->impl->dnd_finish) { +			wlr_data_source_cancel(drag->source);  		}  	} @@ -899,36 +884,51 @@ static void data_device_destroy(struct wl_resource *resource) {  struct client_data_source {  	struct wlr_data_source source; +	struct wlr_data_source_impl impl;  	struct wl_resource *resource;  };  static void client_data_source_accept(struct wlr_data_source *wlr_source, +	uint32_t serial, const char *mime_type); + +static struct client_data_source *client_data_source_from_wlr_data_source( +		struct wlr_data_source *wlr_source) { +	assert(wlr_source->impl->accept == client_data_source_accept); +	return (struct client_data_source *)wlr_source; +} + +static void client_data_source_accept(struct wlr_data_source *wlr_source,  		uint32_t serial, const char *mime_type) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	wl_data_source_send_target(source->resource, mime_type);  }  static void client_data_source_send(struct wlr_data_source *wlr_source,  		const char *mime_type, int32_t fd) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	wl_data_source_send_send(source->resource, mime_type, fd);  	close(fd);  }  static void client_data_source_cancel(struct wlr_data_source *wlr_source) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	wl_data_source_send_cancelled(source->resource);  }  static void client_data_source_dnd_drop(struct wlr_data_source *wlr_source) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	assert(wl_resource_get_version(source->resource) >=  		WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION);  	wl_data_source_send_dnd_drop_performed(source->resource);  }  static void client_data_source_dnd_finish(struct wlr_data_source *wlr_source) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	assert(wl_resource_get_version(source->resource) >=  		WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION);  	wl_data_source_send_dnd_finished(source->resource); @@ -936,7 +936,8 @@ static void client_data_source_dnd_finish(struct wlr_data_source *wlr_source) {  static void client_data_source_dnd_action(struct wlr_data_source *wlr_source,  		enum wl_data_device_manager_dnd_action action) { -	struct client_data_source *source = (struct client_data_source *)wlr_source; +	struct client_data_source *source = +		client_data_source_from_wlr_data_source(wlr_source);  	assert(wl_resource_get_version(source->resource) >=  		WL_DATA_SOURCE_ACTION_SINCE_VERSION);  	wl_data_source_send_action(source->resource, action); @@ -947,6 +948,37 @@ static void data_source_destroy(struct wl_client *client,  	wl_resource_destroy(resource);  } +static struct client_data_source *client_data_source_create( +		struct wl_resource *source_resource) { +	struct client_data_source *source = +		calloc(1, sizeof(struct client_data_source)); +	if (source == NULL) { +		return NULL; +	} + +	source->resource = source_resource; + +	source->impl.accept = client_data_source_accept; +	source->impl.send = client_data_source_send; +	source->impl.cancel = client_data_source_cancel; + +	if (wl_resource_get_version(source->resource) >= +			WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) { +		source->impl.dnd_drop = client_data_source_dnd_drop; +	} +	if (wl_resource_get_version(source->resource) >= +			WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) { +		source->impl.dnd_finish = client_data_source_dnd_finish; +	} +	if (wl_resource_get_version(source->resource) >= +			WL_DATA_SOURCE_ACTION_SINCE_VERSION) { +		source->impl.dnd_action = client_data_source_dnd_action; +	} + +	wlr_data_source_init(&source->source, &source->impl); +	return source; +} +  static void data_source_set_actions(struct wl_client *client,  		struct wl_resource *resource, uint32_t dnd_actions) {  	struct client_data_source *source = @@ -1007,7 +1039,11 @@ static void data_source_resource_handle_destroy(struct wl_resource *resource) {  	free(source);  } -void wlr_data_source_init(struct wlr_data_source *source) { +void wlr_data_source_init(struct wlr_data_source *source, +		const struct wlr_data_source_impl *impl) { +	assert(impl->send); + +	source->impl = impl;  	wl_array_init(&source->mime_types);  	wl_signal_init(&source->events.destroy);  	source->actions = -1; @@ -1027,6 +1063,45 @@ void wlr_data_source_finish(struct wlr_data_source *source) {  	wl_array_release(&source->mime_types);  } +void wlr_data_source_send(struct wlr_data_source *source, const char *mime_type, +		int32_t fd) { +	source->impl->send(source, mime_type, fd); +} + +void wlr_data_source_accept(struct wlr_data_source *source, uint32_t serial, +		const char *mime_type) { +	source->accepted = (mime_type != NULL); +	if (source->impl->accept) { +		source->impl->accept(source, serial, mime_type); +	} +} + +void wlr_data_source_cancel(struct wlr_data_source *source) { +	if (source->impl->cancel) { +		source->impl->cancel(source); +	} +} + +void wlr_data_source_dnd_drop(struct wlr_data_source *source) { +	if (source->impl->dnd_drop) { +		source->impl->dnd_drop(source); +	} +} + +void wlr_data_source_dnd_finish(struct wlr_data_source *source) { +	if (source->impl->dnd_finish) { +		source->impl->dnd_finish(source); +	} +} + +void wlr_data_source_dnd_action(struct wlr_data_source *source, +		enum wl_data_device_manager_dnd_action action) { +	source->current_dnd_action = action; +	if (source->impl->dnd_action) { +		source->impl->dnd_action(source, action); +	} +} +  void data_device_manager_get_data_device(struct wl_client *client,  		struct wl_resource *manager_resource, uint32_t id, @@ -1048,40 +1123,23 @@ void data_device_manager_get_data_device(struct wl_client *client,  static void data_device_manager_create_data_source(struct wl_client *client,  		struct wl_resource *resource, uint32_t id) { -	struct client_data_source *source = -		calloc(1, sizeof(struct client_data_source)); -	if (source == NULL) { +	struct wl_resource *source_resource = wl_resource_create(client, +		&wl_data_source_interface, wl_resource_get_version(resource), id); +	if (source_resource == NULL) {  		wl_resource_post_no_memory(resource);  		return;  	} -	wlr_data_source_init(&source->source); -	source->resource = wl_resource_create(client, &wl_data_source_interface, -		wl_resource_get_version(resource), id); -	if (source->resource == NULL) { -		free(source); +	struct client_data_source *source = +		client_data_source_create(source_resource); +	if (source == NULL) { +		wl_resource_destroy(source_resource);  		wl_resource_post_no_memory(resource);  		return;  	} -	wl_resource_set_implementation(source->resource, &data_source_impl, -		source, data_source_resource_handle_destroy); -	source->source.accept = client_data_source_accept; -	source->source.send = client_data_source_send; -	source->source.cancel = client_data_source_cancel; - -	if (wl_resource_get_version(source->resource) >= -			WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) { -		source->source.dnd_drop = client_data_source_dnd_drop; -	} -	if (wl_resource_get_version(source->resource) >= -			WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) { -		source->source.dnd_finish = client_data_source_dnd_finish; -	} -	if (wl_resource_get_version(source->resource) >= -			WL_DATA_SOURCE_ACTION_SINCE_VERSION) { -		source->source.dnd_action = client_data_source_dnd_action; -	} +	wl_resource_set_implementation(source_resource, &data_source_impl, +		source, data_source_resource_handle_destroy);  }  static const struct wl_data_device_manager_interface diff --git a/types/wlr_seat.c b/types/wlr_seat.c index ed7fb470..3c1f17fa 100644 --- a/types/wlr_seat.c +++ b/types/wlr_seat.c @@ -366,9 +366,9 @@ void wlr_seat_destroy(struct wlr_seat *seat) {  	wl_list_remove(&seat->display_destroy.link);  	if (seat->selection_source) { -		seat->selection_source->cancel(seat->selection_source); -		seat->selection_source = NULL;  		wl_list_remove(&seat->selection_source_destroy.link); +		wlr_data_source_cancel(seat->selection_source); +		seat->selection_source = NULL;  	}  	if (seat->primary_selection_source) {  		seat->primary_selection_source->cancel(seat->primary_selection_source); | 
