From 69abc41d25a6e0eb60e3d03b44eba1cb2f491741 Mon Sep 17 00:00:00 2001 From: Ronan Pigott Date: Wed, 16 Nov 2022 15:50:34 -0700 Subject: [PATCH] launcher: track workspaces by node This removes the need to rename the pid_workspaces when a workspace is renamed. It also opens the possibility of tracking other node types. Tracking containers would allow application to be placed correctly in the container tree even if the user has moved their focus elsewhere since it was launched. (cherry picked from commit 3b49f2782e8faf68766269b9c7390b16e25ae824) --- include/sway/desktop/launcher.h | 2 - sway/commands/rename.c | 2 - sway/desktop/launcher.c | 130 +++++++++++++++++++------------- 3 files changed, 77 insertions(+), 57 deletions(-) diff --git a/include/sway/desktop/launcher.h b/include/sway/desktop/launcher.h index cb22eb98..bbc4a2c3 100644 --- a/include/sway/desktop/launcher.h +++ b/include/sway/desktop/launcher.h @@ -9,6 +9,4 @@ void root_record_workspace_pid(pid_t pid); void root_remove_workspace_pid(pid_t pid); -void root_rename_pid_workspaces(const char *old_name, const char *new_name); - #endif diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 4656a410..60a66d58 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -92,8 +92,6 @@ struct cmd_results *cmd_rename(int argc, char **argv) { sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); - root_rename_pid_workspaces(workspace->name, new_name); - free(workspace->name); workspace->name = new_name; diff --git a/sway/desktop/launcher.c b/sway/desktop/launcher.c index 4e0d9dc1..dd81e23d 100644 --- a/sway/desktop/launcher.c +++ b/sway/desktop/launcher.c @@ -4,19 +4,21 @@ #include "sway/input/seat.h" #include "sway/output.h" #include "sway/desktop/launcher.h" +#include "sway/tree/node.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" +#include "sway/tree/root.h" #include "log.h" static struct wl_list pid_workspaces; struct pid_workspace { pid_t pid; - char *workspace; + char *name; struct timespec time_added; - struct sway_output *output; - struct wl_listener output_destroy; + struct sway_node *node; + struct wl_listener node_destroy; struct wl_list link; }; @@ -56,9 +58,9 @@ static pid_t get_parent_pid(pid_t child) { } static void pid_workspace_destroy(struct pid_workspace *pw) { - wl_list_remove(&pw->output_destroy.link); + wl_list_remove(&pw->node_destroy.link); wl_list_remove(&pw->link); - free(pw->workspace); + free(pw->name); free(pw); } @@ -69,6 +71,7 @@ struct sway_workspace *root_workspace_for_pid(pid_t pid) { } struct sway_workspace *ws = NULL; + struct sway_output *output = NULL; struct pid_workspace *pw = NULL; sway_log(SWAY_DEBUG, "Looking up workspace for pid %d", pid); @@ -79,45 +82,84 @@ struct sway_workspace *root_workspace_for_pid(pid_t pid) { if (pid == _pw->pid) { pw = _pw; sway_log(SWAY_DEBUG, - "found pid_workspace for pid %d, workspace %s", - pid, pw->workspace); - goto found; + "found %s match for pid %d: %s", + node_type_to_str(pw->node->type), pid, node_get_name(pw->node)); + break; } } pid = get_parent_pid(pid); } while (pid > 1); -found: - if (pw && pw->workspace) { - ws = workspace_by_name(pw->workspace); - - if (!ws) { - sway_log(SWAY_DEBUG, - "Creating workspace %s for pid %d because it disappeared", - pw->workspace, pid); - - struct sway_output *output = pw->output; - if (pw->output && !pw->output->enabled) { + if (pw) { + switch (pw->node->type) { + case N_CONTAINER: + // Unimplemented + // TODO: add container matching? + ws = pw->node->sway_container->pending.workspace; + break; + case N_WORKSPACE: + ws = pw->node->sway_workspace; + break; + case N_OUTPUT: + output = pw->node->sway_output; + ws = workspace_by_name(pw->name); + if (!ws) { sway_log(SWAY_DEBUG, - "Workspace output %s is disabled, trying another one", - pw->output->wlr_output->name); - output = NULL; + "Creating workspace %s for pid %d because it disappeared", + pw->name, pid); + if (!output->enabled) { + sway_log(SWAY_DEBUG, + "Workspace output %s is disabled, trying another one", + output->wlr_output->name); + output = NULL; + } + ws = workspace_create(output, pw->name); } - - ws = workspace_create(output, pw->workspace); + break; + case N_ROOT: + ws = workspace_create(NULL, pw->name); + break; } - pid_workspace_destroy(pw); } return ws; } -static void pw_handle_output_destroy(struct wl_listener *listener, void *data) { - struct pid_workspace *pw = wl_container_of(listener, pw, output_destroy); - pw->output = NULL; - wl_list_remove(&pw->output_destroy.link); - wl_list_init(&pw->output_destroy.link); +static void pw_handle_node_destroy(struct wl_listener *listener, void *data) { + struct pid_workspace *pw = wl_container_of(listener, pw, node_destroy); + switch (pw->node->type) { + case N_CONTAINER: + // Unimplemented + break; + case N_WORKSPACE:; + struct sway_workspace *ws = pw->node->sway_workspace; + wl_list_remove(&pw->node_destroy.link); + wl_list_init(&pw->node_destroy.link); + // We want to save this ws name to recreate later, hopefully on the + // same output + free(pw->name); + pw->name = strdup(ws->name); + if (!ws->output || ws->output->node.destroying) { + // If the output is being destroyed it would be pointless to track + // If the output is being disabled, we'll find out if it's still + // disabled when we try to match it. + pw->node = &root->node; + break; + } + pw->node = &ws->output->node; + wl_signal_add(&pw->node->events.destroy, &pw->node_destroy); + break; + case N_OUTPUT: + wl_list_remove(&pw->node_destroy.link); + wl_list_init(&pw->node_destroy.link); + // We'll make the ws pw->name somewhere else + pw->node = &root->node; + break; + case N_ROOT: + // Unreachable + break; + } } void root_record_workspace_pid(pid_t pid) { @@ -132,11 +174,6 @@ void root_record_workspace_pid(pid_t pid) { sway_log(SWAY_DEBUG, "Bailing out, no workspace"); return; } - struct sway_output *output = ws->output; - if (!output) { - sway_log(SWAY_DEBUG, "Bailing out, no output"); - return; - } struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -151,12 +188,13 @@ void root_record_workspace_pid(pid_t pid) { } struct pid_workspace *pw = calloc(1, sizeof(struct pid_workspace)); - pw->workspace = strdup(ws->name); - pw->output = output; + pw->name = strdup(ws->name); + pw->node = &ws->node; pw->pid = pid; + memcpy(&pw->time_added, &now, sizeof(struct timespec)); - pw->output_destroy.notify = pw_handle_output_destroy; - wl_signal_add(&output->wlr_output->events.destroy, &pw->output_destroy); + pw->node_destroy.notify = pw_handle_node_destroy; + wl_signal_add(&pw->node->events.destroy, &pw->node_destroy); wl_list_insert(&pid_workspaces, &pw->link); } @@ -173,17 +211,3 @@ void root_remove_workspace_pid(pid_t pid) { } } } - -void root_rename_pid_workspaces(const char *old_name, const char *new_name) { - if (!pid_workspaces.prev && !pid_workspaces.next) { - wl_list_init(&pid_workspaces); - } - - struct pid_workspace *pw = NULL; - wl_list_for_each(pw, &pid_workspaces, link) { - if (strcmp(pw->workspace, old_name) == 0) { - free(pw->workspace); - pw->workspace = strdup(new_name); - } - } -}