aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ronan Pigott <ronan@rjp.ie>2022-11-16 15:50:34 -0700
committerLibravatar Simon Ser <contact@emersion.fr>2022-11-26 10:29:59 +0100
commit69abc41d25a6e0eb60e3d03b44eba1cb2f491741 (patch)
treedfa1a65e5a854742ad78581dec15f050f81afdfb
parentnode: prettify node type names (diff)
downloadsway-69abc41d25a6e0eb60e3d03b44eba1cb2f491741.tar.gz
sway-69abc41d25a6e0eb60e3d03b44eba1cb2f491741.tar.zst
sway-69abc41d25a6e0eb60e3d03b44eba1cb2f491741.zip
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)
-rw-r--r--include/sway/desktop/launcher.h2
-rw-r--r--sway/commands/rename.c2
-rw-r--r--sway/desktop/launcher.c130
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);
9 9
10void root_remove_workspace_pid(pid_t pid); 10void root_remove_workspace_pid(pid_t pid);
11 11
12void root_rename_pid_workspaces(const char *old_name, const char *new_name);
13
14#endif 12#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) {
92 92
93 sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); 93 sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name);
94 94
95 root_rename_pid_workspaces(workspace->name, new_name);
96
97 free(workspace->name); 95 free(workspace->name);
98 workspace->name = new_name; 96 workspace->name = new_name;
99 97
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 @@
4#include "sway/input/seat.h" 4#include "sway/input/seat.h"
5#include "sway/output.h" 5#include "sway/output.h"
6#include "sway/desktop/launcher.h" 6#include "sway/desktop/launcher.h"
7#include "sway/tree/node.h"
7#include "sway/tree/container.h" 8#include "sway/tree/container.h"
8#include "sway/tree/workspace.h" 9#include "sway/tree/workspace.h"
10#include "sway/tree/root.h"
9#include "log.h" 11#include "log.h"
10 12
11static struct wl_list pid_workspaces; 13static struct wl_list pid_workspaces;
12 14
13struct pid_workspace { 15struct pid_workspace {
14 pid_t pid; 16 pid_t pid;
15 char *workspace; 17 char *name;
16 struct timespec time_added; 18 struct timespec time_added;
17 19
18 struct sway_output *output; 20 struct sway_node *node;
19 struct wl_listener output_destroy; 21 struct wl_listener node_destroy;
20 22
21 struct wl_list link; 23 struct wl_list link;
22}; 24};
@@ -56,9 +58,9 @@ static pid_t get_parent_pid(pid_t child) {
56} 58}
57 59
58static void pid_workspace_destroy(struct pid_workspace *pw) { 60static void pid_workspace_destroy(struct pid_workspace *pw) {
59 wl_list_remove(&pw->output_destroy.link); 61 wl_list_remove(&pw->node_destroy.link);
60 wl_list_remove(&pw->link); 62 wl_list_remove(&pw->link);
61 free(pw->workspace); 63 free(pw->name);
62 free(pw); 64 free(pw);
63} 65}
64 66
@@ -69,6 +71,7 @@ struct sway_workspace *root_workspace_for_pid(pid_t pid) {
69 } 71 }
70 72
71 struct sway_workspace *ws = NULL; 73 struct sway_workspace *ws = NULL;
74 struct sway_output *output = NULL;
72 struct pid_workspace *pw = NULL; 75 struct pid_workspace *pw = NULL;
73 76
74 sway_log(SWAY_DEBUG, "Looking up workspace for pid %d", pid); 77 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) {
79 if (pid == _pw->pid) { 82 if (pid == _pw->pid) {
80 pw = _pw; 83 pw = _pw;
81 sway_log(SWAY_DEBUG, 84 sway_log(SWAY_DEBUG,
82 "found pid_workspace for pid %d, workspace %s", 85 "found %s match for pid %d: %s",
83 pid, pw->workspace); 86 node_type_to_str(pw->node->type), pid, node_get_name(pw->node));
84 goto found; 87 break;
85 } 88 }
86 } 89 }
87 pid = get_parent_pid(pid); 90 pid = get_parent_pid(pid);
88 } while (pid > 1); 91 } while (pid > 1);
89 92
90found: 93 if (pw) {
91 if (pw && pw->workspace) { 94 switch (pw->node->type) {
92 ws = workspace_by_name(pw->workspace); 95 case N_CONTAINER:
93 96 // Unimplemented
94 if (!ws) { 97 // TODO: add container matching?
95 sway_log(SWAY_DEBUG, 98 ws = pw->node->sway_container->pending.workspace;
96 "Creating workspace %s for pid %d because it disappeared", 99 break;
97 pw->workspace, pid); 100 case N_WORKSPACE:
98 101 ws = pw->node->sway_workspace;
99 struct sway_output *output = pw->output; 102 break;
100 if (pw->output && !pw->output->enabled) { 103 case N_OUTPUT:
104 output = pw->node->sway_output;
105 ws = workspace_by_name(pw->name);
106 if (!ws) {
101 sway_log(SWAY_DEBUG, 107 sway_log(SWAY_DEBUG,
102 "Workspace output %s is disabled, trying another one", 108 "Creating workspace %s for pid %d because it disappeared",
103 pw->output->wlr_output->name); 109 pw->name, pid);
104 output = NULL; 110 if (!output->enabled) {
111 sway_log(SWAY_DEBUG,
112 "Workspace output %s is disabled, trying another one",
113 output->wlr_output->name);
114 output = NULL;
115 }
116 ws = workspace_create(output, pw->name);
105 } 117 }
106 118 break;
107 ws = workspace_create(output, pw->workspace); 119 case N_ROOT:
120 ws = workspace_create(NULL, pw->name);
121 break;
108 } 122 }
109
110 pid_workspace_destroy(pw); 123 pid_workspace_destroy(pw);
111 } 124 }
112 125
113 return ws; 126 return ws;
114} 127}
115 128
116static void pw_handle_output_destroy(struct wl_listener *listener, void *data) { 129static void pw_handle_node_destroy(struct wl_listener *listener, void *data) {
117 struct pid_workspace *pw = wl_container_of(listener, pw, output_destroy); 130 struct pid_workspace *pw = wl_container_of(listener, pw, node_destroy);
118 pw->output = NULL; 131 switch (pw->node->type) {
119 wl_list_remove(&pw->output_destroy.link); 132 case N_CONTAINER:
120 wl_list_init(&pw->output_destroy.link); 133 // Unimplemented
134 break;
135 case N_WORKSPACE:;
136 struct sway_workspace *ws = pw->node->sway_workspace;
137 wl_list_remove(&pw->node_destroy.link);
138 wl_list_init(&pw->node_destroy.link);
139 // We want to save this ws name to recreate later, hopefully on the
140 // same output
141 free(pw->name);
142 pw->name = strdup(ws->name);
143 if (!ws->output || ws->output->node.destroying) {
144 // If the output is being destroyed it would be pointless to track
145 // If the output is being disabled, we'll find out if it's still
146 // disabled when we try to match it.
147 pw->node = &root->node;
148 break;
149 }
150 pw->node = &ws->output->node;
151 wl_signal_add(&pw->node->events.destroy, &pw->node_destroy);
152 break;
153 case N_OUTPUT:
154 wl_list_remove(&pw->node_destroy.link);
155 wl_list_init(&pw->node_destroy.link);
156 // We'll make the ws pw->name somewhere else
157 pw->node = &root->node;
158 break;
159 case N_ROOT:
160 // Unreachable
161 break;
162 }
121} 163}
122 164
123void root_record_workspace_pid(pid_t pid) { 165void root_record_workspace_pid(pid_t pid) {
@@ -132,11 +174,6 @@ void root_record_workspace_pid(pid_t pid) {
132 sway_log(SWAY_DEBUG, "Bailing out, no workspace"); 174 sway_log(SWAY_DEBUG, "Bailing out, no workspace");
133 return; 175 return;
134 } 176 }
135 struct sway_output *output = ws->output;
136 if (!output) {
137 sway_log(SWAY_DEBUG, "Bailing out, no output");
138 return;
139 }
140 177
141 struct timespec now; 178 struct timespec now;
142 clock_gettime(CLOCK_MONOTONIC, &now); 179 clock_gettime(CLOCK_MONOTONIC, &now);
@@ -151,12 +188,13 @@ void root_record_workspace_pid(pid_t pid) {
151 } 188 }
152 189
153 struct pid_workspace *pw = calloc(1, sizeof(struct pid_workspace)); 190 struct pid_workspace *pw = calloc(1, sizeof(struct pid_workspace));
154 pw->workspace = strdup(ws->name); 191 pw->name = strdup(ws->name);
155 pw->output = output; 192 pw->node = &ws->node;
156 pw->pid = pid; 193 pw->pid = pid;
194
157 memcpy(&pw->time_added, &now, sizeof(struct timespec)); 195 memcpy(&pw->time_added, &now, sizeof(struct timespec));
158 pw->output_destroy.notify = pw_handle_output_destroy; 196 pw->node_destroy.notify = pw_handle_node_destroy;
159 wl_signal_add(&output->wlr_output->events.destroy, &pw->output_destroy); 197 wl_signal_add(&pw->node->events.destroy, &pw->node_destroy);
160 wl_list_insert(&pid_workspaces, &pw->link); 198 wl_list_insert(&pid_workspaces, &pw->link);
161} 199}
162 200
@@ -173,17 +211,3 @@ void root_remove_workspace_pid(pid_t pid) {
173 } 211 }
174 } 212 }
175} 213}
176
177void root_rename_pid_workspaces(const char *old_name, const char *new_name) {
178 if (!pid_workspaces.prev && !pid_workspaces.next) {
179 wl_list_init(&pid_workspaces);
180 }
181
182 struct pid_workspace *pw = NULL;
183 wl_list_for_each(pw, &pid_workspaces, link) {
184 if (strcmp(pw->workspace, old_name) == 0) {
185 free(pw->workspace);
186 pw->workspace = strdup(new_name);
187 }
188 }
189}