aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/output.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-20 15:54:30 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-24 22:17:28 +1000
commitb6058703fa240780d66fac8ef96982c66b2b0263 (patch)
tree5e056a7859751c68c0cfb425fc6f37599c3f7400 /sway/tree/output.c
parentMerge pull request #2470 from ianyfan/completions (diff)
downloadsway-b6058703fa240780d66fac8ef96982c66b2b0263.tar.gz
sway-b6058703fa240780d66fac8ef96982c66b2b0263.tar.zst
sway-b6058703fa240780d66fac8ef96982c66b2b0263.zip
Refactor destroy functions and save workspaces when there's no outputs
This changes the destroy functions to the following: * output_begin_destroy * output_destroy * workspace_begin_destroy * workspace_destroy * container_begin_destroy * container_destroy * view_begin_destroy * view_destroy The terminology was `destroy` and `free`, and it has been changed to `begin_destroy` and `destroy` respectively. When the last output is disconnected, its workspaces will now be stashed in the root. Upon connection of a new output they will be restored. There is a new function `workspace_consider_destroy` which decides whether the given workspace should be destroyed or not (ie. empty and not visible). Calling container_begin_destroy will no longer automatically reap the parents. In some places we want to reap the parents and in some we don't, so this is left to the caller. container_reap_empty_recursive and container_reap_empty have been combined into one function and it will recurse up the tree.
Diffstat (limited to 'sway/tree/output.c')
-rw-r--r--sway/tree/output.c108
1 files changed, 107 insertions, 1 deletions
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 6da63064..80636c11 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -10,6 +10,7 @@
10#include "log.h" 10#include "log.h"
11 11
12static void restore_workspaces(struct sway_container *output) { 12static void restore_workspaces(struct sway_container *output) {
13 // Workspace output priority
13 for (int i = 0; i < root_container.children->length; i++) { 14 for (int i = 0; i < root_container.children->length; i++) {
14 struct sway_container *other = root_container.children->items[i]; 15 struct sway_container *other = root_container.children->items[i];
15 if (other == output) { 16 if (other == output) {
@@ -29,6 +30,15 @@ static void restore_workspaces(struct sway_container *output) {
29 } 30 }
30 } 31 }
31 32
33 // Saved workspaces
34 list_t *saved = root_container.sway_root->saved_workspaces;
35 for (int i = 0; i < saved->length; ++i) {
36 struct sway_container *ws = saved->items[i];
37 container_add_child(output, ws);
38 ipc_event_workspace(NULL, ws, "move");
39 }
40 saved->length = 0;
41
32 output_sort_workspaces(output); 42 output_sort_workspaces(output);
33} 43}
34 44
@@ -68,7 +78,7 @@ struct sway_container *output_create(
68 output->sway_output = sway_output; 78 output->sway_output = sway_output;
69 output->name = strdup(name); 79 output->name = strdup(name);
70 if (output->name == NULL) { 80 if (output->name == NULL) {
71 container_destroy(output); 81 output_begin_destroy(output);
72 return NULL; 82 return NULL;
73 } 83 }
74 84
@@ -103,6 +113,102 @@ struct sway_container *output_create(
103 return output; 113 return output;
104} 114}
105 115
116static void output_evacuate(struct sway_container *output) {
117 if (!output->children->length) {
118 return;
119 }
120 struct sway_container *fallback_output = NULL;
121 if (root_container.children->length > 1) {
122 fallback_output = root_container.children->items[0];
123 if (fallback_output == output) {
124 fallback_output = root_container.children->items[1];
125 }
126 }
127
128 while (output->children->length) {
129 struct sway_container *workspace = output->children->items[0];
130
131 struct sway_container *new_output =
132 workspace_output_get_highest_available(workspace, output);
133 if (!new_output) {
134 new_output = fallback_output;
135 }
136
137 container_remove_child(workspace);
138
139 if (new_output) {
140 workspace_output_add_priority(workspace, new_output);
141 container_add_child(new_output, workspace);
142 output_sort_workspaces(new_output);
143 ipc_event_workspace(NULL, workspace, "move");
144 } else {
145 list_add(root_container.sway_root->saved_workspaces, workspace);
146 }
147 }
148}
149
150void output_destroy(struct sway_container *output) {
151 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
152 return;
153 }
154 if (!sway_assert(output->destroying,
155 "Tried to free output which wasn't marked as destroying")) {
156 return;
157 }
158 if (!sway_assert(output->ntxnrefs == 0, "Tried to free output "
159 "which is still referenced by transactions")) {
160 return;
161 }
162 free(output->name);
163 free(output->formatted_title);
164 wlr_texture_destroy(output->title_focused);
165 wlr_texture_destroy(output->title_focused_inactive);
166 wlr_texture_destroy(output->title_unfocused);
167 wlr_texture_destroy(output->title_urgent);
168 list_free(output->children);
169 list_free(output->current.children);
170 list_free(output->outputs);
171 free(output);
172
173 // NOTE: We don't actually destroy the sway_output here
174}
175
176static void untrack_output(struct sway_container *con, void *data) {
177 struct sway_output *output = data;
178 int index = list_find(con->outputs, output);
179 if (index != -1) {
180 list_del(con->outputs, index);
181 }
182}
183
184void output_begin_destroy(struct sway_container *output) {
185 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
186 return;
187 }
188 wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
189 wl_signal_emit(&output->events.destroy, output);
190
191 output_evacuate(output);
192
193 output->destroying = true;
194 container_set_dirty(output);
195
196 root_for_each_container(untrack_output, output->sway_output);
197
198 wl_list_remove(&output->sway_output->mode.link);
199 wl_list_remove(&output->sway_output->transform.link);
200 wl_list_remove(&output->sway_output->scale.link);
201 wl_list_remove(&output->sway_output->damage_destroy.link);
202 wl_list_remove(&output->sway_output->damage_frame.link);
203
204 output->sway_output->swayc = NULL;
205 output->sway_output = NULL;
206
207 if (output->parent) {
208 container_remove_child(output);
209 }
210}
211
106void output_for_each_workspace(struct sway_container *output, 212void output_for_each_workspace(struct sway_container *output,
107 void (*f)(struct sway_container *con, void *data), void *data) { 213 void (*f)(struct sway_container *con, void *data), void *data) {
108 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { 214 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {