diff options
Diffstat (limited to 'sway/tree/output.c')
-rw-r--r-- | sway/tree/output.c | 126 |
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 | ||
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,120 @@ 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 | 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 | |||
155 | void 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 | |||
181 | static 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 | |||
189 | void 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 | |||
217 | struct 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 | |||
106 | void output_for_each_workspace(struct sway_container *output, | 230 | void 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")) { |