aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/output.c')
-rw-r--r--sway/tree/output.c126
1 files changed, 125 insertions, 1 deletions
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 6da63064..6601220b 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,120 @@ 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 container_remove_child(workspace);
132
133 if (workspace_is_empty(workspace)) {
134 workspace_begin_destroy(workspace);
135 continue;
136 }
137
138 struct sway_container *new_output =
139 workspace_output_get_highest_available(workspace, output);
140 if (!new_output) {
141 new_output = fallback_output;
142 }
143
144 if (new_output) {
145 workspace_output_add_priority(workspace, new_output);
146 container_add_child(new_output, workspace);
147 output_sort_workspaces(new_output);
148 ipc_event_workspace(NULL, workspace, "move");
149 } else {
150 list_add(root_container.sway_root->saved_workspaces, workspace);
151 }
152 }
153}
154
155void output_destroy(struct sway_container *output) {
156 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
157 return;
158 }
159 if (!sway_assert(output->destroying,
160 "Tried to free output which wasn't marked as destroying")) {
161 return;
162 }
163 if (!sway_assert(output->ntxnrefs == 0, "Tried to free output "
164 "which is still referenced by transactions")) {
165 return;
166 }
167 free(output->name);
168 free(output->formatted_title);
169 wlr_texture_destroy(output->title_focused);
170 wlr_texture_destroy(output->title_focused_inactive);
171 wlr_texture_destroy(output->title_unfocused);
172 wlr_texture_destroy(output->title_urgent);
173 list_free(output->children);
174 list_free(output->current.children);
175 list_free(output->outputs);
176 free(output);
177
178 // NOTE: We don't actually destroy the sway_output here
179}
180
181static void untrack_output(struct sway_container *con, void *data) {
182 struct sway_output *output = data;
183 int index = list_find(con->outputs, output);
184 if (index != -1) {
185 list_del(con->outputs, index);
186 }
187}
188
189void output_begin_destroy(struct sway_container *output) {
190 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
191 return;
192 }
193 wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
194 wl_signal_emit(&output->events.destroy, output);
195
196 output_evacuate(output);
197
198 output->destroying = true;
199 container_set_dirty(output);
200
201 root_for_each_container(untrack_output, output->sway_output);
202
203 wl_list_remove(&output->sway_output->mode.link);
204 wl_list_remove(&output->sway_output->transform.link);
205 wl_list_remove(&output->sway_output->scale.link);
206 wl_list_remove(&output->sway_output->damage_destroy.link);
207 wl_list_remove(&output->sway_output->damage_frame.link);
208
209 output->sway_output->swayc = NULL;
210 output->sway_output = NULL;
211
212 if (output->parent) {
213 container_remove_child(output);
214 }
215}
216
217struct sway_container *output_from_wlr_output(struct wlr_output *output) {
218 if (output == NULL) {
219 return NULL;
220 }
221 for (int i = 0; i < root_container.children->length; ++i) {
222 struct sway_container *o = root_container.children->items[i];
223 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) {
224 return o;
225 }
226 }
227 return NULL;
228}
229
106void output_for_each_workspace(struct sway_container *output, 230void output_for_each_workspace(struct sway_container *output,
107 void (*f)(struct sway_container *con, void *data), void *data) { 231 void (*f)(struct sway_container *con, void *data), void *data) {
108 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { 232 if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {