diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-08-20 15:54:30 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-08-24 22:17:28 +1000 |
commit | b6058703fa240780d66fac8ef96982c66b2b0263 (patch) | |
tree | 5e056a7859751c68c0cfb425fc6f37599c3f7400 /sway/tree/output.c | |
parent | Merge pull request #2470 from ianyfan/completions (diff) | |
download | sway-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.c | 108 |
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 | ||
12 | static void restore_workspaces(struct sway_container *output) { | 12 | static 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 | ||
116 | static 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 | |||
150 | void 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 | |||
176 | static 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 | |||
184 | void 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 | |||
106 | void output_for_each_workspace(struct sway_container *output, | 212 | void 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")) { |