mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	xdg-activation-v1: enable compositors to request their own tokens
These new functions allow a compositor to request new managed tokens without participating in the xdg-activation procedure as a wayland client. This enables the compositor itself to behave as a launcher application.
This commit is contained in:
		
							parent
							
								
									83090de034
								
							
						
					
					
						commit
						6ad0f819e2
					
				
					 2 changed files with 102 additions and 33 deletions
				
			
		| 
						 | 
				
			
			@ -44,6 +44,8 @@ struct wlr_xdg_activation_v1 {
 | 
			
		|||
 | 
			
		||||
	// private state
 | 
			
		||||
 | 
			
		||||
	struct wl_display *display;
 | 
			
		||||
 | 
			
		||||
	struct wl_global *global;
 | 
			
		||||
 | 
			
		||||
	struct wl_listener display_destroy;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,4 +62,17 @@ struct wlr_xdg_activation_v1_request_activate_event {
 | 
			
		|||
struct wlr_xdg_activation_v1 *wlr_xdg_activation_v1_create(
 | 
			
		||||
	struct wl_display *display);
 | 
			
		||||
 | 
			
		||||
struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_token_v1_create(
 | 
			
		||||
		struct wlr_xdg_activation_v1 *activation);
 | 
			
		||||
 | 
			
		||||
void wlr_xdg_activation_token_v1_destroy(
 | 
			
		||||
		struct wlr_xdg_activation_token_v1 *token);
 | 
			
		||||
 | 
			
		||||
struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_v1_find_token(
 | 
			
		||||
		struct wlr_xdg_activation_v1 *activation, const char *token_str);
 | 
			
		||||
 | 
			
		||||
// Get a string suitable for exporting to launched clients
 | 
			
		||||
const char *wlr_xdg_activation_token_v1_get_name(
 | 
			
		||||
		struct wlr_xdg_activation_token_v1 *token);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,8 @@ static struct wlr_xdg_activation_token_v1 *token_from_resource(
 | 
			
		|||
	return wl_resource_get_user_data(resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void token_destroy(struct wlr_xdg_activation_token_v1 *token) {
 | 
			
		||||
void wlr_xdg_activation_token_v1_destroy(
 | 
			
		||||
		struct wlr_xdg_activation_token_v1 *token) {
 | 
			
		||||
	if (token == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -42,13 +43,13 @@ static void token_destroy(struct wlr_xdg_activation_token_v1 *token) {
 | 
			
		|||
static int token_handle_timeout(void *data) {
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token = data;
 | 
			
		||||
	wlr_log(WLR_DEBUG, "Activation token '%s' has expired", token->token);
 | 
			
		||||
	token_destroy(token);
 | 
			
		||||
	wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void token_handle_resource_destroy(struct wl_resource *resource) {
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token = token_from_resource(resource);
 | 
			
		||||
	token_destroy(token);
 | 
			
		||||
	wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void token_handle_destroy(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +57,36 @@ static void token_handle_destroy(struct wl_client *client,
 | 
			
		|||
	wl_resource_destroy(token_resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool token_init( struct wlr_xdg_activation_token_v1 *token) {
 | 
			
		||||
	char token_str[TOKEN_STRLEN + 1] = {0};
 | 
			
		||||
	if (!generate_token(token_str)) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	token->token = strdup(token_str);
 | 
			
		||||
	if (token->token == NULL) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (token->activation->token_timeout_msec > 0) {
 | 
			
		||||
		// Needs wayland > 1.19
 | 
			
		||||
		// struct wl_display *display = wl_global_get_display(activation->global);
 | 
			
		||||
		struct wl_display *display = token->activation->display;
 | 
			
		||||
		struct wl_event_loop *loop = wl_display_get_event_loop(display);
 | 
			
		||||
		token->timeout =
 | 
			
		||||
			wl_event_loop_add_timer(loop, token_handle_timeout, token);
 | 
			
		||||
		if (token->timeout == NULL) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		wl_event_source_timer_update(token->timeout,
 | 
			
		||||
			token->activation->token_timeout_msec);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	assert(wl_list_empty(&token->link));
 | 
			
		||||
	wl_list_insert(&token->activation->tokens, &token->link);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void token_handle_commit(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *token_resource) {
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token =
 | 
			
		||||
| 
						 | 
				
			
			@ -71,12 +102,6 @@ static void token_handle_commit(struct wl_client *client,
 | 
			
		|||
	wl_resource_set_user_data(token->resource, NULL);
 | 
			
		||||
	token->resource = NULL;
 | 
			
		||||
 | 
			
		||||
	char token_str[TOKEN_STRLEN + 1] = {0};
 | 
			
		||||
	if (!generate_token(token_str)) {
 | 
			
		||||
		wl_client_post_no_memory(client);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (token->seat != NULL) {
 | 
			
		||||
		struct wlr_seat_client *seat_client =
 | 
			
		||||
			wlr_seat_client_for_wl_client(token->seat, client);
 | 
			
		||||
| 
						 | 
				
			
			@ -95,39 +120,28 @@ static void token_handle_commit(struct wl_client *client,
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	token->token = strdup(token_str);
 | 
			
		||||
	if (token->token == NULL) {
 | 
			
		||||
	if (!token_init(token)) {
 | 
			
		||||
		wl_client_post_no_memory(client);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (token->activation->token_timeout_msec > 0) {
 | 
			
		||||
		struct wl_display *display = wl_client_get_display(client);
 | 
			
		||||
		struct wl_event_loop *loop = wl_display_get_event_loop(display);
 | 
			
		||||
		token->timeout =
 | 
			
		||||
			wl_event_loop_add_timer(loop, token_handle_timeout, token);
 | 
			
		||||
		if (token->timeout == NULL) {
 | 
			
		||||
			wl_client_post_no_memory(client);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		wl_event_source_timer_update(token->timeout,
 | 
			
		||||
			token->activation->token_timeout_msec);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	assert(wl_list_empty(&token->link));
 | 
			
		||||
	wl_list_insert(&token->activation->tokens, &token->link);
 | 
			
		||||
 | 
			
		||||
	xdg_activation_token_v1_send_done(token_resource, token_str);
 | 
			
		||||
	xdg_activation_token_v1_send_done(token_resource, token->token);
 | 
			
		||||
 | 
			
		||||
	// TODO: consider emitting a new_token event
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	// Here we send the generated token, but it's invalid and can't be used to
 | 
			
		||||
error:;
 | 
			
		||||
	// Here we send a generated token, but it's invalid and can't be used to
 | 
			
		||||
	// request activation.
 | 
			
		||||
	char token_str[TOKEN_STRLEN + 1] = {0};
 | 
			
		||||
	if (!generate_token(token_str)) {
 | 
			
		||||
		wl_client_post_no_memory(client);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xdg_activation_token_v1_send_done(token_resource, token_str);
 | 
			
		||||
	token_destroy(token);
 | 
			
		||||
	wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void token_handle_set_app_id(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +300,7 @@ static void activation_handle_activate(struct wl_client *client,
 | 
			
		|||
	};
 | 
			
		||||
	wlr_signal_emit_safe(&activation->events.request_activate, &event);
 | 
			
		||||
 | 
			
		||||
	token_destroy(token);
 | 
			
		||||
	wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct xdg_activation_v1_interface activation_impl = {
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +329,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
			
		|||
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token, *token_tmp;
 | 
			
		||||
	wl_list_for_each_safe(token, token_tmp, &activation->tokens, link) {
 | 
			
		||||
		token_destroy(token);
 | 
			
		||||
		wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_list_remove(&activation->display_destroy.link);
 | 
			
		||||
| 
						 | 
				
			
			@ -343,8 +357,48 @@ struct wlr_xdg_activation_v1 *wlr_xdg_activation_v1_create(
 | 
			
		|||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	activation->display = display;
 | 
			
		||||
 | 
			
		||||
	activation->display_destroy.notify = handle_display_destroy;
 | 
			
		||||
	wl_display_add_destroy_listener(display, &activation->display_destroy);
 | 
			
		||||
 | 
			
		||||
	return activation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_token_v1_create(
 | 
			
		||||
		struct wlr_xdg_activation_v1 *activation) {
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token = calloc(1, sizeof(*token));
 | 
			
		||||
	if (token == NULL) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_list_init(&token->link);
 | 
			
		||||
	// Currently no way to set seat/surface
 | 
			
		||||
	wl_list_init(&token->seat_destroy.link);
 | 
			
		||||
	wl_list_init(&token->surface_destroy.link);
 | 
			
		||||
 | 
			
		||||
	token->activation = activation;
 | 
			
		||||
 | 
			
		||||
	if (!token_init(token)) {
 | 
			
		||||
		wlr_xdg_activation_token_v1_destroy(token);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return token;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_v1_find_token(
 | 
			
		||||
		struct wlr_xdg_activation_v1 *activation, const char *token_str) {
 | 
			
		||||
	struct wlr_xdg_activation_token_v1 *token;
 | 
			
		||||
	wl_list_for_each(token, &activation->tokens, link) {
 | 
			
		||||
		if (strcmp(token_str, token->token) == 0) {
 | 
			
		||||
			return token;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *wlr_xdg_activation_token_v1_get_name(
 | 
			
		||||
		struct wlr_xdg_activation_token_v1 *token) {
 | 
			
		||||
	return token->token;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue