diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-09-05 09:33:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-05 09:33:27 -0400 |
commit | 610eb946171f782165a20614b2d3318b89273990 (patch) | |
tree | 05eec1df1ef48e05b23d273d31143ad32e7632d2 /sway/tree/output.c | |
parent | Merge pull request #2574 from ammgws/block-bg-fix (diff) | |
parent | Allow marked containers to be moved out of the scratchpad via move command (diff) | |
download | sway-610eb946171f782165a20614b2d3318b89273990.tar.gz sway-610eb946171f782165a20614b2d3318b89273990.tar.zst sway-610eb946171f782165a20614b2d3318b89273990.zip |
Merge pull request #2540 from RyanDwyer/typesafety
Implement type safe arguments and demote sway_container
Diffstat (limited to 'sway/tree/output.c')
-rw-r--r-- | sway/tree/output.c | 348 |
1 files changed, 209 insertions, 139 deletions
diff --git a/sway/tree/output.c b/sway/tree/output.c index 6601220b..35589032 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -2,28 +2,31 @@ | |||
2 | #include <ctype.h> | 2 | #include <ctype.h> |
3 | #include <string.h> | 3 | #include <string.h> |
4 | #include <strings.h> | 4 | #include <strings.h> |
5 | #include <wlr/types/wlr_output_damage.h> | ||
5 | #include "sway/ipc-server.h" | 6 | #include "sway/ipc-server.h" |
7 | #include "sway/layers.h" | ||
6 | #include "sway/output.h" | 8 | #include "sway/output.h" |
7 | #include "sway/tree/arrange.h" | 9 | #include "sway/tree/arrange.h" |
8 | #include "sway/tree/output.h" | 10 | #include "sway/tree/output.h" |
9 | #include "sway/tree/workspace.h" | 11 | #include "sway/tree/workspace.h" |
10 | #include "log.h" | 12 | #include "log.h" |
13 | #include "util.h" | ||
11 | 14 | ||
12 | static void restore_workspaces(struct sway_container *output) { | 15 | static void restore_workspaces(struct sway_output *output) { |
13 | // Workspace output priority | 16 | // Workspace output priority |
14 | for (int i = 0; i < root_container.children->length; i++) { | 17 | for (int i = 0; i < root->outputs->length; i++) { |
15 | struct sway_container *other = root_container.children->items[i]; | 18 | struct sway_output *other = root->outputs->items[i]; |
16 | if (other == output) { | 19 | if (other == output) { |
17 | continue; | 20 | continue; |
18 | } | 21 | } |
19 | 22 | ||
20 | for (int j = 0; j < other->children->length; j++) { | 23 | for (int j = 0; j < other->workspaces->length; j++) { |
21 | struct sway_container *ws = other->children->items[j]; | 24 | struct sway_workspace *ws = other->workspaces->items[j]; |
22 | struct sway_container *highest = | 25 | struct sway_output *highest = |
23 | workspace_output_get_highest_available(ws, NULL); | 26 | workspace_output_get_highest_available(ws, NULL); |
24 | if (highest == output) { | 27 | if (highest == output) { |
25 | container_remove_child(ws); | 28 | workspace_detach(ws); |
26 | container_add_child(output, ws); | 29 | output_add_workspace(output, ws); |
27 | ipc_event_workspace(NULL, ws, "move"); | 30 | ipc_event_workspace(NULL, ws, "move"); |
28 | j--; | 31 | j--; |
29 | } | 32 | } |
@@ -31,111 +34,116 @@ static void restore_workspaces(struct sway_container *output) { | |||
31 | } | 34 | } |
32 | 35 | ||
33 | // Saved workspaces | 36 | // Saved workspaces |
34 | list_t *saved = root_container.sway_root->saved_workspaces; | 37 | for (int i = 0; i < root->saved_workspaces->length; ++i) { |
35 | for (int i = 0; i < saved->length; ++i) { | 38 | struct sway_workspace *ws = root->saved_workspaces->items[i]; |
36 | struct sway_container *ws = saved->items[i]; | 39 | output_add_workspace(output, ws); |
37 | container_add_child(output, ws); | ||
38 | ipc_event_workspace(NULL, ws, "move"); | 40 | ipc_event_workspace(NULL, ws, "move"); |
39 | } | 41 | } |
40 | saved->length = 0; | 42 | root->saved_workspaces->length = 0; |
41 | 43 | ||
42 | output_sort_workspaces(output); | 44 | output_sort_workspaces(output); |
43 | } | 45 | } |
44 | 46 | ||
45 | struct sway_container *output_create( | 47 | struct sway_output *output_create(struct wlr_output *wlr_output) { |
46 | struct sway_output *sway_output) { | 48 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); |
47 | const char *name = sway_output->wlr_output->name; | 49 | node_init(&output->node, N_OUTPUT, output); |
48 | char identifier[128]; | 50 | output->wlr_output = wlr_output; |
49 | output_get_identifier(identifier, sizeof(identifier), sway_output); | 51 | wlr_output->data = output; |
50 | 52 | ||
51 | struct output_config *oc = NULL, *all = NULL; | 53 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); |
52 | for (int i = 0; i < config->output_configs->length; ++i) { | ||
53 | struct output_config *cur = config->output_configs->items[i]; | ||
54 | 54 | ||
55 | if (strcasecmp(name, cur->name) == 0 || | 55 | wl_list_insert(&root->all_outputs, &output->link); |
56 | strcasecmp(identifier, cur->name) == 0) { | ||
57 | wlr_log(WLR_DEBUG, "Matched output config for %s", name); | ||
58 | oc = cur; | ||
59 | } | ||
60 | if (strcasecmp("*", cur->name) == 0) { | ||
61 | wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name); | ||
62 | all = cur; | ||
63 | } | ||
64 | 56 | ||
65 | if (oc && all) { | 57 | if (!wl_list_empty(&wlr_output->modes)) { |
66 | break; | 58 | struct wlr_output_mode *mode = |
67 | } | 59 | wl_container_of(wlr_output->modes.prev, mode, link); |
68 | } | 60 | wlr_output_set_mode(wlr_output, mode); |
69 | if (!oc) { | ||
70 | oc = all; | ||
71 | } | 61 | } |
72 | 62 | ||
73 | if (oc && !oc->enabled) { | 63 | output->workspaces = create_list(); |
74 | return NULL; | 64 | output->current.workspaces = create_list(); |
75 | } | ||
76 | 65 | ||
77 | struct sway_container *output = container_create(C_OUTPUT); | 66 | return output; |
78 | output->sway_output = sway_output; | 67 | } |
79 | output->name = strdup(name); | ||
80 | if (output->name == NULL) { | ||
81 | output_begin_destroy(output); | ||
82 | return NULL; | ||
83 | } | ||
84 | 68 | ||
69 | void output_enable(struct sway_output *output, struct output_config *oc) { | ||
70 | if (!sway_assert(!output->enabled, "output is already enabled")) { | ||
71 | return; | ||
72 | } | ||
73 | struct wlr_output *wlr_output = output->wlr_output; | ||
74 | output->enabled = true; | ||
85 | apply_output_config(oc, output); | 75 | apply_output_config(oc, output); |
86 | container_add_child(&root_container, output); | 76 | list_add(root->outputs, output); |
87 | load_swaybars(); | ||
88 | 77 | ||
89 | struct wlr_box size; | 78 | output->lx = wlr_output->lx; |
90 | wlr_output_effective_resolution(sway_output->wlr_output, &size.width, | 79 | output->ly = wlr_output->ly; |
91 | &size.height); | 80 | wlr_output_transformed_resolution(wlr_output, |
92 | output->width = size.width; | 81 | &output->width, &output->height); |
93 | output->height = size.height; | ||
94 | 82 | ||
95 | restore_workspaces(output); | 83 | restore_workspaces(output); |
96 | 84 | ||
97 | if (!output->children->length) { | 85 | if (!output->workspaces->length) { |
98 | // Create workspace | 86 | // Create workspace |
99 | char *ws_name = workspace_next_name(output->name); | 87 | char *ws_name = workspace_next_name(wlr_output->name); |
100 | wlr_log(WLR_DEBUG, "Creating default workspace %s", ws_name); | 88 | wlr_log(WLR_DEBUG, "Creating default workspace %s", ws_name); |
101 | struct sway_container *ws = workspace_create(output, ws_name); | 89 | struct sway_workspace *ws = workspace_create(output, ws_name); |
102 | // Set each seat's focus if not already set | 90 | // Set each seat's focus if not already set |
103 | struct sway_seat *seat = NULL; | 91 | struct sway_seat *seat = NULL; |
104 | wl_list_for_each(seat, &input_manager->seats, link) { | 92 | wl_list_for_each(seat, &input_manager->seats, link) { |
105 | if (!seat->has_focus) { | 93 | if (!seat->has_focus) { |
106 | seat_set_focus(seat, ws); | 94 | seat_set_focus(seat, &ws->node); |
107 | } | 95 | } |
108 | } | 96 | } |
109 | free(ws_name); | 97 | free(ws_name); |
110 | } | 98 | } |
111 | 99 | ||
112 | container_create_notify(output); | 100 | size_t len = sizeof(output->layers) / sizeof(output->layers[0]); |
113 | return output; | 101 | for (size_t i = 0; i < len; ++i) { |
102 | wl_list_init(&output->layers[i]); | ||
103 | } | ||
104 | wl_signal_init(&output->events.destroy); | ||
105 | |||
106 | input_manager_configure_xcursor(input_manager); | ||
107 | |||
108 | wl_signal_add(&wlr_output->events.mode, &output->mode); | ||
109 | wl_signal_add(&wlr_output->events.transform, &output->transform); | ||
110 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
111 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
112 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
113 | |||
114 | output_add_listeners(output); | ||
115 | |||
116 | wl_signal_emit(&root->events.new_node, &output->node); | ||
117 | |||
118 | load_swaybars(); | ||
119 | |||
120 | arrange_layers(output); | ||
121 | arrange_root(); | ||
114 | } | 122 | } |
115 | 123 | ||
116 | static void output_evacuate(struct sway_container *output) { | 124 | static void output_evacuate(struct sway_output *output) { |
117 | if (!output->children->length) { | 125 | if (!output->workspaces->length) { |
118 | return; | 126 | return; |
119 | } | 127 | } |
120 | struct sway_container *fallback_output = NULL; | 128 | struct sway_output *fallback_output = NULL; |
121 | if (root_container.children->length > 1) { | 129 | if (root->outputs->length > 1) { |
122 | fallback_output = root_container.children->items[0]; | 130 | fallback_output = root->outputs->items[0]; |
123 | if (fallback_output == output) { | 131 | if (fallback_output == output) { |
124 | fallback_output = root_container.children->items[1]; | 132 | fallback_output = root->outputs->items[1]; |
125 | } | 133 | } |
126 | } | 134 | } |
127 | 135 | ||
128 | while (output->children->length) { | 136 | while (output->workspaces->length) { |
129 | struct sway_container *workspace = output->children->items[0]; | 137 | struct sway_workspace *workspace = output->workspaces->items[0]; |
130 | 138 | ||
131 | container_remove_child(workspace); | 139 | workspace_detach(workspace); |
132 | 140 | ||
133 | if (workspace_is_empty(workspace)) { | 141 | if (workspace_is_empty(workspace)) { |
134 | workspace_begin_destroy(workspace); | 142 | workspace_begin_destroy(workspace); |
135 | continue; | 143 | continue; |
136 | } | 144 | } |
137 | 145 | ||
138 | struct sway_container *new_output = | 146 | struct sway_output *new_output = |
139 | workspace_output_get_highest_available(workspace, output); | 147 | workspace_output_get_highest_available(workspace, output); |
140 | if (!new_output) { | 148 | if (!new_output) { |
141 | new_output = fallback_output; | 149 | new_output = fallback_output; |
@@ -143,39 +151,31 @@ static void output_evacuate(struct sway_container *output) { | |||
143 | 151 | ||
144 | if (new_output) { | 152 | if (new_output) { |
145 | workspace_output_add_priority(workspace, new_output); | 153 | workspace_output_add_priority(workspace, new_output); |
146 | container_add_child(new_output, workspace); | 154 | output_add_workspace(new_output, workspace); |
147 | output_sort_workspaces(new_output); | 155 | output_sort_workspaces(new_output); |
148 | ipc_event_workspace(NULL, workspace, "move"); | 156 | ipc_event_workspace(NULL, workspace, "move"); |
149 | } else { | 157 | } else { |
150 | list_add(root_container.sway_root->saved_workspaces, workspace); | 158 | list_add(root->saved_workspaces, workspace); |
151 | } | 159 | } |
152 | } | 160 | } |
153 | } | 161 | } |
154 | 162 | ||
155 | void output_destroy(struct sway_container *output) { | 163 | void output_destroy(struct sway_output *output) { |
156 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | 164 | if (!sway_assert(output->node.destroying, |
165 | "Tried to free output which wasn't marked as destroying")) { | ||
157 | return; | 166 | return; |
158 | } | 167 | } |
159 | if (!sway_assert(output->destroying, | 168 | if (!sway_assert(output->wlr_output == NULL, |
160 | "Tried to free output which wasn't marked as destroying")) { | 169 | "Tried to free output which still had a wlr_output")) { |
161 | return; | 170 | return; |
162 | } | 171 | } |
163 | if (!sway_assert(output->ntxnrefs == 0, "Tried to free output " | 172 | if (!sway_assert(output->node.ntxnrefs == 0, "Tried to free output " |
164 | "which is still referenced by transactions")) { | 173 | "which is still referenced by transactions")) { |
165 | return; | 174 | return; |
166 | } | 175 | } |
167 | free(output->name); | 176 | list_free(output->workspaces); |
168 | free(output->formatted_title); | 177 | list_free(output->current.workspaces); |
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); | 178 | free(output); |
177 | |||
178 | // NOTE: We don't actually destroy the sway_output here | ||
179 | } | 179 | } |
180 | 180 | ||
181 | static void untrack_output(struct sway_container *con, void *data) { | 181 | static void untrack_output(struct sway_container *con, void *data) { |
@@ -186,76 +186,128 @@ static void untrack_output(struct sway_container *con, void *data) { | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | 188 | ||
189 | void output_begin_destroy(struct sway_container *output) { | 189 | void output_disable(struct sway_output *output) { |
190 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | 190 | if (!sway_assert(output->enabled, "Expected an enabled output")) { |
191 | return; | 191 | return; |
192 | } | 192 | } |
193 | wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 193 | wlr_log(WLR_DEBUG, "Disabling output '%s'", output->wlr_output->name); |
194 | wl_signal_emit(&output->events.destroy, output); | 194 | wl_signal_emit(&output->events.destroy, output); |
195 | 195 | ||
196 | output_evacuate(output); | 196 | output_evacuate(output); |
197 | 197 | ||
198 | output->destroying = true; | 198 | root_for_each_container(untrack_output, output); |
199 | container_set_dirty(output); | 199 | |
200 | int index = list_find(root->outputs, output); | ||
201 | list_del(root->outputs, index); | ||
202 | |||
203 | wl_list_remove(&output->mode.link); | ||
204 | wl_list_remove(&output->transform.link); | ||
205 | wl_list_remove(&output->scale.link); | ||
206 | wl_list_remove(&output->damage_destroy.link); | ||
207 | wl_list_remove(&output->damage_frame.link); | ||
208 | |||
209 | output->enabled = false; | ||
210 | |||
211 | arrange_root(); | ||
212 | } | ||
213 | |||
214 | void output_begin_destroy(struct sway_output *output) { | ||
215 | if (!sway_assert(!output->enabled, "Expected a disabled output")) { | ||
216 | return; | ||
217 | } | ||
218 | wlr_log(WLR_DEBUG, "Destroying output '%s'", output->wlr_output->name); | ||
219 | |||
220 | output->node.destroying = true; | ||
221 | node_set_dirty(&output->node); | ||
222 | |||
223 | wl_list_remove(&output->link); | ||
224 | wl_list_remove(&output->destroy.link); | ||
225 | output->wlr_output->data = NULL; | ||
226 | output->wlr_output = NULL; | ||
227 | } | ||
200 | 228 | ||
201 | root_for_each_container(untrack_output, output->sway_output); | 229 | struct output_config *output_find_config(struct sway_output *output) { |
230 | const char *name = output->wlr_output->name; | ||
231 | char identifier[128]; | ||
232 | output_get_identifier(identifier, sizeof(identifier), output); | ||
202 | 233 | ||
203 | wl_list_remove(&output->sway_output->mode.link); | 234 | struct output_config *oc = NULL, *all = NULL; |
204 | wl_list_remove(&output->sway_output->transform.link); | 235 | for (int i = 0; i < config->output_configs->length; ++i) { |
205 | wl_list_remove(&output->sway_output->scale.link); | 236 | struct output_config *cur = config->output_configs->items[i]; |
206 | wl_list_remove(&output->sway_output->damage_destroy.link); | ||
207 | wl_list_remove(&output->sway_output->damage_frame.link); | ||
208 | 237 | ||
209 | output->sway_output->swayc = NULL; | 238 | if (strcasecmp(name, cur->name) == 0 || |
210 | output->sway_output = NULL; | 239 | strcasecmp(identifier, cur->name) == 0) { |
240 | wlr_log(WLR_DEBUG, "Matched output config for %s", name); | ||
241 | oc = cur; | ||
242 | } | ||
243 | if (strcasecmp("*", cur->name) == 0) { | ||
244 | wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name); | ||
245 | all = cur; | ||
246 | } | ||
211 | 247 | ||
212 | if (output->parent) { | 248 | if (oc && all) { |
213 | container_remove_child(output); | 249 | break; |
250 | } | ||
251 | } | ||
252 | if (!oc) { | ||
253 | oc = all; | ||
214 | } | 254 | } |
255 | |||
256 | return oc; | ||
215 | } | 257 | } |
216 | 258 | ||
217 | struct sway_container *output_from_wlr_output(struct wlr_output *output) { | 259 | struct sway_output *output_from_wlr_output(struct wlr_output *output) { |
218 | if (output == NULL) { | 260 | return output->data; |
261 | } | ||
262 | |||
263 | struct sway_output *output_get_in_direction(struct sway_output *reference, | ||
264 | enum movement_direction direction) { | ||
265 | enum wlr_direction wlr_dir = 0; | ||
266 | if (!sway_assert(sway_dir_to_wlr(direction, &wlr_dir), | ||
267 | "got invalid direction: %d", direction)) { | ||
219 | return NULL; | 268 | return NULL; |
220 | } | 269 | } |
221 | for (int i = 0; i < root_container.children->length; ++i) { | 270 | int lx = reference->wlr_output->lx + reference->width / 2; |
222 | struct sway_container *o = root_container.children->items[i]; | 271 | int ly = reference->wlr_output->ly + reference->height / 2; |
223 | if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) { | 272 | struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output( |
224 | return o; | 273 | root->output_layout, wlr_dir, reference->wlr_output, lx, ly); |
225 | } | 274 | if (!wlr_adjacent) { |
275 | return NULL; | ||
226 | } | 276 | } |
227 | return NULL; | 277 | return output_from_wlr_output(wlr_adjacent); |
228 | } | 278 | } |
229 | 279 | ||
230 | void output_for_each_workspace(struct sway_container *output, | 280 | void output_add_workspace(struct sway_output *output, |
231 | void (*f)(struct sway_container *con, void *data), void *data) { | 281 | struct sway_workspace *workspace) { |
232 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | 282 | if (workspace->output) { |
233 | return; | 283 | workspace_detach(workspace); |
234 | } | 284 | } |
235 | for (int i = 0; i < output->children->length; ++i) { | 285 | list_add(output->workspaces, workspace); |
236 | struct sway_container *workspace = output->children->items[i]; | 286 | workspace->output = output; |
287 | node_set_dirty(&output->node); | ||
288 | node_set_dirty(&workspace->node); | ||
289 | } | ||
290 | |||
291 | void output_for_each_workspace(struct sway_output *output, | ||
292 | void (*f)(struct sway_workspace *ws, void *data), void *data) { | ||
293 | for (int i = 0; i < output->workspaces->length; ++i) { | ||
294 | struct sway_workspace *workspace = output->workspaces->items[i]; | ||
237 | f(workspace, data); | 295 | f(workspace, data); |
238 | } | 296 | } |
239 | } | 297 | } |
240 | 298 | ||
241 | void output_for_each_container(struct sway_container *output, | 299 | void output_for_each_container(struct sway_output *output, |
242 | void (*f)(struct sway_container *con, void *data), void *data) { | 300 | void (*f)(struct sway_container *con, void *data), void *data) { |
243 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | 301 | for (int i = 0; i < output->workspaces->length; ++i) { |
244 | return; | 302 | struct sway_workspace *workspace = output->workspaces->items[i]; |
245 | } | ||
246 | for (int i = 0; i < output->children->length; ++i) { | ||
247 | struct sway_container *workspace = output->children->items[i]; | ||
248 | workspace_for_each_container(workspace, f, data); | 303 | workspace_for_each_container(workspace, f, data); |
249 | } | 304 | } |
250 | } | 305 | } |
251 | 306 | ||
252 | struct sway_container *output_find_workspace(struct sway_container *output, | 307 | struct sway_workspace *output_find_workspace(struct sway_output *output, |
253 | bool (*test)(struct sway_container *con, void *data), void *data) { | 308 | bool (*test)(struct sway_workspace *ws, void *data), void *data) { |
254 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | 309 | for (int i = 0; i < output->workspaces->length; ++i) { |
255 | return NULL; | 310 | struct sway_workspace *workspace = output->workspaces->items[i]; |
256 | } | ||
257 | for (int i = 0; i < output->children->length; ++i) { | ||
258 | struct sway_container *workspace = output->children->items[i]; | ||
259 | if (test(workspace, data)) { | 311 | if (test(workspace, data)) { |
260 | return workspace; | 312 | return workspace; |
261 | } | 313 | } |
@@ -263,14 +315,11 @@ struct sway_container *output_find_workspace(struct sway_container *output, | |||
263 | return NULL; | 315 | return NULL; |
264 | } | 316 | } |
265 | 317 | ||
266 | struct sway_container *output_find_container(struct sway_container *output, | 318 | struct sway_container *output_find_container(struct sway_output *output, |
267 | bool (*test)(struct sway_container *con, void *data), void *data) { | 319 | bool (*test)(struct sway_container *con, void *data), void *data) { |
268 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | ||
269 | return NULL; | ||
270 | } | ||
271 | struct sway_container *result = NULL; | 320 | struct sway_container *result = NULL; |
272 | for (int i = 0; i < output->children->length; ++i) { | 321 | for (int i = 0; i < output->workspaces->length; ++i) { |
273 | struct sway_container *workspace = output->children->items[i]; | 322 | struct sway_workspace *workspace = output->workspaces->items[i]; |
274 | if ((result = workspace_find_container(workspace, test, data))) { | 323 | if ((result = workspace_find_container(workspace, test, data))) { |
275 | return result; | 324 | return result; |
276 | } | 325 | } |
@@ -279,8 +328,8 @@ struct sway_container *output_find_container(struct sway_container *output, | |||
279 | } | 328 | } |
280 | 329 | ||
281 | static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | 330 | static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { |
282 | struct sway_container *a = *(void **)_a; | 331 | struct sway_workspace *a = *(void **)_a; |
283 | struct sway_container *b = *(void **)_b; | 332 | struct sway_workspace *b = *(void **)_b; |
284 | 333 | ||
285 | if (isdigit(a->name[0]) && isdigit(b->name[0])) { | 334 | if (isdigit(a->name[0]) && isdigit(b->name[0])) { |
286 | int a_num = strtol(a->name, NULL, 10); | 335 | int a_num = strtol(a->name, NULL, 10); |
@@ -294,6 +343,27 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | |||
294 | return 0; | 343 | return 0; |
295 | } | 344 | } |
296 | 345 | ||
297 | void output_sort_workspaces(struct sway_container *output) { | 346 | void output_sort_workspaces(struct sway_output *output) { |
298 | list_stable_sort(output->children, sort_workspace_cmp_qsort); | 347 | list_stable_sort(output->workspaces, sort_workspace_cmp_qsort); |
348 | } | ||
349 | |||
350 | void output_get_box(struct sway_output *output, struct wlr_box *box) { | ||
351 | box->x = output->lx; | ||
352 | box->y = output->ly; | ||
353 | box->width = output->width; | ||
354 | box->height = output->height; | ||
355 | } | ||
356 | |||
357 | enum sway_container_layout output_get_default_layout( | ||
358 | struct sway_output *output) { | ||
359 | if (config->default_layout != L_NONE) { | ||
360 | return config->default_layout; | ||
361 | } | ||
362 | if (config->default_orientation != L_NONE) { | ||
363 | return config->default_orientation; | ||
364 | } | ||
365 | if (output->height > output->width) { | ||
366 | return L_VERT; | ||
367 | } | ||
368 | return L_HORIZ; | ||
299 | } | 369 | } |