From 5794a223ce9c22cee11a395bd0aa9477939becde Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Wed, 16 Nov 2022 15:50:34 -0700 Subject: [PATCH] view: associate launch contexts with views Views now maintain a reference to a launch context which, as a last resort, is populated at map time with a context associated with its pid. This opens the possibility of populating it before map via another source, e.g. xdga-tokens or configuration. (cherry picked from commit 864b3a9a18f236f92f1898bb44ab977ceaebfd68) --- include/sway/desktop/launcher.h | 22 +++++++++++++-- include/sway/tree/view.h | 3 ++ sway/desktop/launcher.c | 50 +++++++++++---------------------- sway/tree/view.c | 28 ++++++++++++++++-- 4 files changed, 64 insertions(+), 39 deletions(-) diff --git a/include/sway/desktop/launcher.h b/include/sway/desktop/launcher.h index 7802bee15..927d7a37b 100644 --- a/include/sway/desktop/launcher.h +++ b/include/sway/desktop/launcher.h @@ -3,10 +3,26 @@ #include -struct sway_workspace *workspace_for_pid(pid_t pid); +struct launcher_ctx { + pid_t pid; + char *name; + struct wlr_xdg_activation_token_v1 *token; + struct wl_listener token_destroy; + + struct sway_node *node; + struct wl_listener node_destroy; + + struct wl_list link; // sway_server::pending_launcher_ctxs +}; + +struct launcher_ctx *launcher_ctx_find_pid(pid_t pid); + +struct sway_workspace *launcher_ctx_get_workspace(struct launcher_ctx *ctx); + +void launcher_ctx_consume(struct launcher_ctx *ctx); + +void launcher_ctx_destroy(struct launcher_ctx *ctx); void launcher_ctx_create(pid_t pid); -void remove_workspace_pid(pid_t pid); - #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 0dcbf1aa6..ca0994318 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -74,6 +74,7 @@ struct sway_view { struct sway_xdg_decoration *xdg_decoration; pid_t pid; + struct launcher_ctx *ctx; // The size the view would want to be if it weren't tiled. // Used when changing a view from tiled to floating. @@ -372,4 +373,6 @@ void view_save_buffer(struct sway_view *view); bool view_is_transient_for(struct sway_view *child, struct sway_view *ancestor); +void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx); + #endif diff --git a/sway/desktop/launcher.c b/sway/desktop/launcher.c index 337ca9755..810a04efe 100644 --- a/sway/desktop/launcher.c +++ b/sway/desktop/launcher.c @@ -13,18 +13,6 @@ static struct wl_list launcher_ctxs; -struct launcher_ctx { - pid_t pid; - char *name; - struct wlr_xdg_activation_token_v1 *token; - struct wl_listener token_destroy; - - struct sway_node *node; - struct wl_listener node_destroy; - - struct wl_list link; -}; - /** * Get the pid of a parent process given the pid of a child process. * @@ -59,7 +47,20 @@ static pid_t get_parent_pid(pid_t child) { return -1; } -static void launcher_ctx_destroy(struct launcher_ctx *ctx) { +void launcher_ctx_consume(struct launcher_ctx *ctx) { + // The view is now responsible for destroying this ctx + wl_list_remove(&ctx->token_destroy.link); + wl_list_init(&ctx->token_destroy.link); + + wlr_xdg_activation_token_v1_destroy(ctx->token); + ctx->token = NULL; + + // Prevent additional matches + wl_list_remove(&ctx->link); + wl_list_init(&ctx->link); +} + +void launcher_ctx_destroy(struct launcher_ctx *ctx) { if (ctx == NULL) { return; } @@ -71,7 +72,7 @@ static void launcher_ctx_destroy(struct launcher_ctx *ctx) { free(ctx); } -static struct launcher_ctx *launcher_ctx_find_pid(pid_t pid) { +struct launcher_ctx *launcher_ctx_find_pid(pid_t pid) { if (!launcher_ctxs.prev && !launcher_ctxs.next) { wl_list_init(&launcher_ctxs); return NULL; @@ -97,7 +98,7 @@ static struct launcher_ctx *launcher_ctx_find_pid(pid_t pid) { return ctx; } -static struct sway_workspace *launcher_ctx_get_workspace( +struct sway_workspace *launcher_ctx_get_workspace( struct launcher_ctx *ctx) { struct sway_workspace *ws = NULL; struct sway_output *output = NULL; @@ -135,16 +136,6 @@ static struct sway_workspace *launcher_ctx_get_workspace( return ws; } -struct sway_workspace *workspace_for_pid(pid_t pid) { - struct launcher_ctx *ctx = launcher_ctx_find_pid(pid); - if (ctx == NULL) { - return NULL; - } - struct sway_workspace *ws = launcher_ctx_get_workspace(ctx); - launcher_ctx_destroy(ctx); - return ws; -} - static void ctx_handle_node_destroy(struct wl_listener *listener, void *data) { struct launcher_ctx *ctx = wl_container_of(listener, ctx, node_destroy); switch (ctx->node->type) { @@ -217,12 +208,3 @@ void launcher_ctx_create(pid_t pid) { wl_list_insert(&launcher_ctxs, &ctx->link); } - -void remove_workspace_pid(pid_t pid) { - if (!launcher_ctxs.prev || !launcher_ctxs.next) { - return; - } - - struct launcher_ctx *ctx = launcher_ctx_find_pid(pid); - launcher_ctx_destroy(ctx); -} diff --git a/sway/tree/view.c b/sway/tree/view.c index 7482e7a46..31387aaa2 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -64,6 +64,8 @@ void view_destroy(struct sway_view *view) { } list_free(view->executed_criteria); + view_assign_ctx(view, NULL); + free(view->title_format); if (view->impl->destroy) { @@ -534,6 +536,20 @@ static void view_populate_pid(struct sway_view *view) { view->pid = pid; } +void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx) { + if (view->ctx) { + // This ctx has been replaced + launcher_ctx_destroy(view->ctx); + view->ctx = NULL; + } + if (ctx == NULL) { + return; + } + launcher_ctx_consume(ctx); + + view->ctx = ctx; +} + static struct sway_workspace *select_workspace(struct sway_view *view) { struct sway_seat *seat = input_manager_current_seat(); @@ -569,13 +585,14 @@ static struct sway_workspace *select_workspace(struct sway_view *view) { } list_free(criterias); if (ws) { - remove_workspace_pid(view->pid); + view_assign_ctx(view, NULL); return ws; } // Check if there's a PID mapping - ws = workspace_for_pid(view->pid); + ws = view->ctx ? launcher_ctx_get_workspace(view->ctx) : NULL; if (ws) { + view_assign_ctx(view, NULL); return ws; } @@ -718,6 +735,13 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, view_populate_pid(view); view->container = container_create(view); + if (view->ctx == NULL) { + struct launcher_ctx *ctx = launcher_ctx_find_pid(view->pid); + if (ctx != NULL) { + view_assign_ctx(view, ctx); + } + } + // If there is a request to be opened fullscreen on a specific output, try // to honor that request. Otherwise, fallback to assigns, pid mappings, // focused workspace, etc