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.c130
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
90static 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
90struct sway_output *output_create(struct wlr_output *wlr_output) { 105struct 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
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) { 286void 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
284void output_begin_destroy(struct sway_output *output) { 312void 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
298struct sway_output *output_from_wlr_output(struct wlr_output *output) { 323struct 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
421static 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
435struct 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
396enum sway_container_layout output_get_default_layout( 448enum 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) {