diff options
Diffstat (limited to 'sway/tree/output.c')
-rw-r--r-- | sway/tree/output.c | 130 |
1 files changed, 91 insertions, 39 deletions
diff --git a/sway/tree/output.c b/sway/tree/output.c index a8ae30f7..cd7bf0c2 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -3,12 +3,12 @@ | |||
3 | #include <ctype.h> | 3 | #include <ctype.h> |
4 | #include <string.h> | 4 | #include <string.h> |
5 | #include <strings.h> | 5 | #include <strings.h> |
6 | #include <wlr/types/wlr_output_damage.h> | ||
7 | #include "sway/ipc-server.h" | 6 | #include "sway/ipc-server.h" |
8 | #include "sway/layers.h" | 7 | #include "sway/layers.h" |
9 | #include "sway/output.h" | 8 | #include "sway/output.h" |
10 | #include "sway/tree/arrange.h" | 9 | #include "sway/tree/arrange.h" |
11 | #include "sway/tree/workspace.h" | 10 | #include "sway/tree/workspace.h" |
11 | #include "sway/server.h" | ||
12 | #include "log.h" | 12 | #include "log.h" |
13 | #include "util.h" | 13 | #include "util.h" |
14 | 14 | ||
@@ -56,8 +56,8 @@ static void restore_workspaces(struct sway_output *output) { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | // Saved workspaces | 58 | // Saved workspaces |
59 | while (root->noop_output->workspaces->length) { | 59 | while (root->fallback_output->workspaces->length) { |
60 | struct sway_workspace *ws = root->noop_output->workspaces->items[0]; | 60 | struct sway_workspace *ws = root->fallback_output->workspaces->items[0]; |
61 | workspace_detach(ws); | 61 | workspace_detach(ws); |
62 | output_add_workspace(output, ws); | 62 | output_add_workspace(output, ws); |
63 | 63 | ||
@@ -70,13 +70,13 @@ static void restore_workspaces(struct sway_output *output) { | |||
70 | // floater re-centered | 70 | // floater re-centered |
71 | for (int i = 0; i < ws->floating->length; i++) { | 71 | for (int i = 0; i < ws->floating->length; i++) { |
72 | struct sway_container *floater = ws->floating->items[i]; | 72 | struct sway_container *floater = ws->floating->items[i]; |
73 | if (floater->width == 0 || floater->height == 0 || | 73 | if (floater->pending.width == 0 || floater->pending.height == 0 || |
74 | floater->width > output->width || | 74 | floater->pending.width > output->width || |
75 | floater->height > output->height || | 75 | floater->pending.height > output->height || |
76 | floater->x > output->lx + output->width || | 76 | floater->pending.x > output->lx + output->width || |
77 | floater->y > output->ly + output->height || | 77 | floater->pending.y > output->ly + output->height || |
78 | floater->x + floater->width < output->lx || | 78 | floater->pending.x + floater->pending.width < output->lx || |
79 | floater->y + floater->height < output->ly) { | 79 | floater->pending.y + floater->pending.height < output->ly) { |
80 | container_floating_resize_and_center(floater); | 80 | container_floating_resize_and_center(floater); |
81 | } | 81 | } |
82 | } | 82 | } |
@@ -87,26 +87,63 @@ static void restore_workspaces(struct sway_output *output) { | |||
87 | output_sort_workspaces(output); | 87 | output_sort_workspaces(output); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void destroy_scene_layers(struct sway_output *output) { | ||
91 | wlr_scene_node_destroy(&output->fullscreen_background->node); | ||
92 | |||
93 | scene_node_disown_children(output->layers.tiling); | ||
94 | scene_node_disown_children(output->layers.fullscreen); | ||
95 | |||
96 | wlr_scene_node_destroy(&output->layers.shell_background->node); | ||
97 | wlr_scene_node_destroy(&output->layers.shell_bottom->node); | ||
98 | wlr_scene_node_destroy(&output->layers.tiling->node); | ||
99 | wlr_scene_node_destroy(&output->layers.fullscreen->node); | ||
100 | wlr_scene_node_destroy(&output->layers.shell_top->node); | ||
101 | wlr_scene_node_destroy(&output->layers.shell_overlay->node); | ||
102 | wlr_scene_node_destroy(&output->layers.session_lock->node); | ||
103 | } | ||
104 | |||
90 | struct sway_output *output_create(struct wlr_output *wlr_output) { | 105 | struct sway_output *output_create(struct wlr_output *wlr_output) { |
91 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); | 106 | struct sway_output *output = calloc(1, sizeof(struct sway_output)); |
92 | node_init(&output->node, N_OUTPUT, output); | 107 | node_init(&output->node, N_OUTPUT, output); |
108 | |||
109 | bool failed = false; | ||
110 | output->layers.shell_background = alloc_scene_tree(root->staging, &failed); | ||
111 | output->layers.shell_bottom = alloc_scene_tree(root->staging, &failed); | ||
112 | output->layers.tiling = alloc_scene_tree(root->staging, &failed); | ||
113 | output->layers.fullscreen = alloc_scene_tree(root->staging, &failed); | ||
114 | output->layers.shell_top = alloc_scene_tree(root->staging, &failed); | ||
115 | output->layers.shell_overlay = alloc_scene_tree(root->staging, &failed); | ||
116 | output->layers.session_lock = alloc_scene_tree(root->staging, &failed); | ||
117 | |||
118 | if (!failed) { | ||
119 | output->fullscreen_background = wlr_scene_rect_create( | ||
120 | output->layers.fullscreen, 0, 0, (float[4]){0.f, 0.f, 0.f, 1.f}); | ||
121 | |||
122 | if (!output->fullscreen_background) { | ||
123 | sway_log(SWAY_ERROR, "Unable to allocate a background rect"); | ||
124 | failed = true; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (failed) { | ||
129 | destroy_scene_layers(output); | ||
130 | wlr_scene_output_destroy(output->scene_output); | ||
131 | free(output); | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
93 | output->wlr_output = wlr_output; | 135 | output->wlr_output = wlr_output; |
94 | wlr_output->data = output; | 136 | wlr_output->data = output; |
95 | output->detected_subpixel = wlr_output->subpixel; | 137 | output->detected_subpixel = wlr_output->subpixel; |
96 | output->scale_filter = SCALE_FILTER_NEAREST; | 138 | output->scale_filter = SCALE_FILTER_NEAREST; |
97 | 139 | ||
98 | wl_signal_init(&output->events.destroy); | 140 | wl_signal_init(&output->events.disable); |
99 | 141 | ||
100 | wl_list_insert(&root->all_outputs, &output->link); | 142 | wl_list_insert(&root->all_outputs, &output->link); |
101 | 143 | ||
102 | output->workspaces = create_list(); | 144 | output->workspaces = create_list(); |
103 | output->current.workspaces = create_list(); | 145 | output->current.workspaces = create_list(); |
104 | 146 | ||
105 | size_t len = sizeof(output->layers) / sizeof(output->layers[0]); | ||
106 | for (size_t i = 0; i < len; ++i) { | ||
107 | wl_list_init(&output->layers[i]); | ||
108 | } | ||
109 | |||
110 | return output; | 147 | return output; |
111 | } | 148 | } |
112 | 149 | ||
@@ -146,7 +183,7 @@ void output_enable(struct sway_output *output) { | |||
146 | 183 | ||
147 | input_manager_configure_xcursor(); | 184 | input_manager_configure_xcursor(); |
148 | 185 | ||
149 | wl_signal_emit(&root->events.new_node, &output->node); | 186 | wl_signal_emit_mutable(&root->events.new_node, &output->node); |
150 | 187 | ||
151 | arrange_layers(output); | 188 | arrange_layers(output); |
152 | arrange_root(); | 189 | arrange_root(); |
@@ -192,7 +229,7 @@ static void output_evacuate(struct sway_output *output) { | |||
192 | new_output = fallback_output; | 229 | new_output = fallback_output; |
193 | } | 230 | } |
194 | if (!new_output) { | 231 | if (!new_output) { |
195 | new_output = root->noop_output; | 232 | new_output = root->fallback_output; |
196 | } | 233 | } |
197 | 234 | ||
198 | struct sway_workspace *new_output_ws = | 235 | struct sway_workspace *new_output_ws = |
@@ -238,20 +275,14 @@ void output_destroy(struct sway_output *output) { | |||
238 | "which is still referenced by transactions")) { | 275 | "which is still referenced by transactions")) { |
239 | return; | 276 | return; |
240 | } | 277 | } |
278 | |||
279 | destroy_scene_layers(output); | ||
241 | list_free(output->workspaces); | 280 | list_free(output->workspaces); |
242 | list_free(output->current.workspaces); | 281 | list_free(output->current.workspaces); |
243 | wl_event_source_remove(output->repaint_timer); | 282 | wl_event_source_remove(output->repaint_timer); |
244 | free(output); | 283 | free(output); |
245 | } | 284 | } |
246 | 285 | ||
247 | static void untrack_output(struct sway_container *con, void *data) { | ||
248 | struct sway_output *output = data; | ||
249 | int index = list_find(con->outputs, output); | ||
250 | if (index != -1) { | ||
251 | list_del(con->outputs, index); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | void output_disable(struct sway_output *output) { | 286 | void output_disable(struct sway_output *output) { |
256 | if (!sway_assert(output->enabled, "Expected an enabled output")) { | 287 | if (!sway_assert(output->enabled, "Expected an enabled output")) { |
257 | return; | 288 | return; |
@@ -262,23 +293,20 @@ void output_disable(struct sway_output *output) { | |||
262 | } | 293 | } |
263 | 294 | ||
264 | sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); | 295 | sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); |
265 | wl_signal_emit(&output->events.destroy, output); | 296 | wl_signal_emit_mutable(&output->events.disable, output); |
266 | 297 | ||
267 | output_evacuate(output); | 298 | output_evacuate(output); |
268 | 299 | ||
269 | root_for_each_container(untrack_output, output); | ||
270 | |||
271 | list_del(root->outputs, index); | 300 | list_del(root->outputs, index); |
272 | 301 | ||
273 | output->enabled = false; | 302 | output->enabled = false; |
274 | output->current_mode = NULL; | ||
275 | 303 | ||
276 | arrange_root(); | 304 | arrange_root(); |
277 | 305 | ||
278 | // Reconfigure all devices, since devices with map_to_output directives for | 306 | // Reconfigure all devices, since devices with map_to_output directives for |
279 | // an output that goes offline should stop sending events as long as the | 307 | // an output that goes offline should stop sending events as long as the |
280 | // output remains offline. | 308 | // output remains offline. |
281 | input_manager_configure_all_inputs(); | 309 | input_manager_configure_all_input_mappings(); |
282 | } | 310 | } |
283 | 311 | ||
284 | void output_begin_destroy(struct sway_output *output) { | 312 | void output_begin_destroy(struct sway_output *output) { |
@@ -286,13 +314,10 @@ void output_begin_destroy(struct sway_output *output) { | |||
286 | return; | 314 | return; |
287 | } | 315 | } |
288 | sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); | 316 | sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); |
317 | wl_signal_emit_mutable(&output->node.events.destroy, &output->node); | ||
289 | 318 | ||
290 | output->node.destroying = true; | 319 | output->node.destroying = true; |
291 | node_set_dirty(&output->node); | 320 | node_set_dirty(&output->node); |
292 | |||
293 | wl_list_remove(&output->link); | ||
294 | output->wlr_output->data = NULL; | ||
295 | output->wlr_output = NULL; | ||
296 | } | 321 | } |
297 | 322 | ||
298 | struct sway_output *output_from_wlr_output(struct wlr_output *output) { | 323 | struct sway_output *output_from_wlr_output(struct wlr_output *output) { |
@@ -304,10 +329,10 @@ struct sway_output *output_get_in_direction(struct sway_output *reference, | |||
304 | if (!sway_assert(direction, "got invalid direction: %d", direction)) { | 329 | if (!sway_assert(direction, "got invalid direction: %d", direction)) { |
305 | return NULL; | 330 | return NULL; |
306 | } | 331 | } |
307 | struct wlr_box *output_box = | 332 | struct wlr_box output_box; |
308 | wlr_output_layout_get_box(root->output_layout, reference->wlr_output); | 333 | wlr_output_layout_get_box(root->output_layout, reference->wlr_output, &output_box); |
309 | int lx = output_box->x + output_box->width / 2; | 334 | int lx = output_box.x + output_box.width / 2; |
310 | int ly = output_box->y + output_box->height / 2; | 335 | int ly = output_box.y + output_box.height / 2; |
311 | struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output( | 336 | struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output( |
312 | root->output_layout, direction, reference->wlr_output, lx, ly); | 337 | root->output_layout, direction, reference->wlr_output, lx, ly); |
313 | if (!wlr_adjacent) { | 338 | if (!wlr_adjacent) { |
@@ -393,6 +418,33 @@ void output_get_box(struct sway_output *output, struct wlr_box *box) { | |||
393 | box->height = output->height; | 418 | box->height = output->height; |
394 | } | 419 | } |
395 | 420 | ||
421 | static void handle_destroy_non_desktop(struct wl_listener *listener, void *data) { | ||
422 | struct sway_output_non_desktop *output = | ||
423 | wl_container_of(listener, output, destroy); | ||
424 | |||
425 | sway_log(SWAY_DEBUG, "Destroying non-desktop output '%s'", output->wlr_output->name); | ||
426 | |||
427 | int index = list_find(root->non_desktop_outputs, output); | ||
428 | list_del(root->non_desktop_outputs, index); | ||
429 | |||
430 | wl_list_remove(&output->destroy.link); | ||
431 | |||
432 | free(output); | ||
433 | } | ||
434 | |||
435 | struct sway_output_non_desktop *output_non_desktop_create( | ||
436 | struct wlr_output *wlr_output) { | ||
437 | struct sway_output_non_desktop *output = | ||
438 | calloc(1, sizeof(struct sway_output_non_desktop)); | ||
439 | |||
440 | output->wlr_output = wlr_output; | ||
441 | |||
442 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | ||
443 | output->destroy.notify = handle_destroy_non_desktop; | ||
444 | |||
445 | return output; | ||
446 | } | ||
447 | |||
396 | enum sway_container_layout output_get_default_layout( | 448 | enum sway_container_layout output_get_default_layout( |
397 | struct sway_output *output) { | 449 | struct sway_output *output) { |
398 | if (config->default_orientation != L_NONE) { | 450 | if (config->default_orientation != L_NONE) { |