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