summaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c182
1 files changed, 72 insertions, 110 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index c30e52a1..c182bad6 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -28,10 +28,10 @@
28#include "sway/tree/view.h" 28#include "sway/tree/view.h"
29#include "sway/tree/workspace.h" 29#include "sway/tree/workspace.h"
30 30
31struct sway_container *output_by_name(const char *name) { 31struct sway_output *output_by_name(const char *name) {
32 for (int i = 0; i < root_container.children->length; ++i) { 32 for (int i = 0; i < root->outputs->length; ++i) {
33 struct sway_container *output = root_container.children->items[i]; 33 struct sway_output *output = root->outputs->items[i];
34 if (strcasecmp(output->name, name) == 0) { 34 if (strcasecmp(output->wlr_output->name, name) == 0) {
35 return output; 35 return output;
36 } 36 }
37 } 37 }
@@ -98,8 +98,8 @@ static bool get_surface_box(struct surface_iterator_data *data,
98 wlr_box_rotated_bounds(&box, data->rotation, &rotated_box); 98 wlr_box_rotated_bounds(&box, data->rotation, &rotated_box);
99 99
100 struct wlr_box output_box = { 100 struct wlr_box output_box = {
101 .width = output->swayc->current.swayc_width, 101 .width = output->wlr_output->width,
102 .height = output->swayc->current.swayc_height, 102 .height = output->wlr_output->height,
103 }; 103 };
104 104
105 struct wlr_box intersection; 105 struct wlr_box intersection;
@@ -145,12 +145,12 @@ void output_view_for_each_surface(struct sway_output *output,
145 .user_iterator = iterator, 145 .user_iterator = iterator,
146 .user_data = user_data, 146 .user_data = user_data,
147 .output = output, 147 .output = output,
148 .ox = view->swayc->current.view_x - output->swayc->current.swayc_x 148 .ox = view->container->current.view_x - output->wlr_output->lx
149 - view->geometry.x, 149 - view->geometry.x,
150 .oy = view->swayc->current.view_y - output->swayc->current.swayc_y 150 .oy = view->container->current.view_y - output->wlr_output->ly
151 - view->geometry.y, 151 - view->geometry.y,
152 .width = view->swayc->current.view_width, 152 .width = view->container->current.view_width,
153 .height = view->swayc->current.view_height, 153 .height = view->container->current.view_height,
154 .rotation = 0, // TODO 154 .rotation = 0, // TODO
155 }; 155 };
156 156
@@ -164,12 +164,12 @@ void output_view_for_each_popup(struct sway_output *output,
164 .user_iterator = iterator, 164 .user_iterator = iterator,
165 .user_data = user_data, 165 .user_data = user_data,
166 .output = output, 166 .output = output,
167 .ox = view->swayc->current.view_x - output->swayc->current.swayc_x 167 .ox = view->container->current.view_x - output->wlr_output->lx
168 - view->geometry.x, 168 - view->geometry.x,
169 .oy = view->swayc->current.view_y - output->swayc->current.swayc_y 169 .oy = view->container->current.view_y - output->wlr_output->ly
170 - view->geometry.y, 170 - view->geometry.y,
171 .width = view->swayc->current.view_width, 171 .width = view->container->current.view_width,
172 .height = view->swayc->current.view_height, 172 .height = view->container->current.view_height,
173 .rotation = 0, // TODO 173 .rotation = 0, // TODO
174 }; 174 };
175 175
@@ -197,8 +197,8 @@ void output_unmanaged_for_each_surface(struct sway_output *output,
197 wl_list_for_each(unmanaged_surface, unmanaged, link) { 197 wl_list_for_each(unmanaged_surface, unmanaged, link) {
198 struct wlr_xwayland_surface *xsurface = 198 struct wlr_xwayland_surface *xsurface =
199 unmanaged_surface->wlr_xwayland_surface; 199 unmanaged_surface->wlr_xwayland_surface;
200 double ox = unmanaged_surface->lx - output->swayc->current.swayc_x; 200 double ox = unmanaged_surface->lx - output->wlr_output->lx;
201 double oy = unmanaged_surface->ly - output->swayc->current.swayc_y; 201 double oy = unmanaged_surface->ly - output->wlr_output->ly;
202 202
203 output_surface_for_each_surface(output, xsurface->surface, ox, oy, 203 output_surface_for_each_surface(output, xsurface->surface, ox, oy,
204 iterator, user_data); 204 iterator, user_data);
@@ -211,8 +211,8 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
211 void *user_data) { 211 void *user_data) {
212 struct sway_drag_icon *drag_icon; 212 struct sway_drag_icon *drag_icon;
213 wl_list_for_each(drag_icon, drag_icons, link) { 213 wl_list_for_each(drag_icon, drag_icons, link) {
214 double ox = drag_icon->x - output->swayc->x; 214 double ox = drag_icon->x - output->wlr_output->lx;
215 double oy = drag_icon->y - output->swayc->y; 215 double oy = drag_icon->y - output->wlr_output->ly;
216 216
217 if (drag_icon->wlr_drag_icon->mapped) { 217 if (drag_icon->wlr_drag_icon->mapped) {
218 output_surface_for_each_surface(output, 218 output_surface_for_each_surface(output,
@@ -229,19 +229,13 @@ static void scale_box(struct wlr_box *box, float scale) {
229 box->height *= scale; 229 box->height *= scale;
230} 230}
231 231
232struct sway_container *output_get_active_workspace(struct sway_output *output) { 232struct sway_workspace *output_get_active_workspace(struct sway_output *output) {
233 struct sway_seat *seat = input_manager_current_seat(input_manager); 233 struct sway_seat *seat = input_manager_current_seat(input_manager);
234 struct sway_container *focus = 234 struct sway_node *focus = seat_get_active_child(seat, &output->node);
235 seat_get_focus_inactive(seat, output->swayc);
236 if (!focus) { 235 if (!focus) {
237 // We've never been to this output before 236 return output->workspaces->items[0];
238 focus = output->swayc->current.children->items[0];
239 } 237 }
240 struct sway_container *workspace = focus; 238 return focus->sway_workspace;
241 if (workspace->type != C_WORKSPACE) {
242 workspace = container_parent(workspace, C_WORKSPACE);
243 }
244 return workspace;
245} 239}
246 240
247bool output_has_opaque_overlay_layer_surface(struct sway_output *output) { 241bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
@@ -255,8 +249,8 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
255 struct sway_layer_surface *sway_layer_surface = 249 struct sway_layer_surface *sway_layer_surface =
256 layer_from_wlr_layer_surface(wlr_layer_surface); 250 layer_from_wlr_layer_surface(wlr_layer_surface);
257 pixman_box32_t output_box = { 251 pixman_box32_t output_box = {
258 .x2 = output->swayc->current.swayc_width, 252 .x2 = output->wlr_output->width,
259 .y2 = output->swayc->current.swayc_height, 253 .y2 = output->wlr_output->height,
260 }; 254 };
261 pixman_region32_t surface_opaque_box; 255 pixman_region32_t surface_opaque_box;
262 pixman_region32_init(&surface_opaque_box); 256 pixman_region32_init(&surface_opaque_box);
@@ -307,15 +301,15 @@ struct send_frame_done_data {
307 301
308static void send_frame_done_container_iterator(struct sway_container *con, 302static void send_frame_done_container_iterator(struct sway_container *con,
309 void *_data) { 303 void *_data) {
310 if (con->type != C_VIEW) { 304 if (!con->view) {
311 return; 305 return;
312 } 306 }
313 if (!view_is_visible(con->sway_view)) { 307 if (!view_is_visible(con->view)) {
314 return; 308 return;
315 } 309 }
316 310
317 struct send_frame_done_data *data = _data; 311 struct send_frame_done_data *data = _data;
318 output_view_for_each_surface(data->output, con->sway_view, 312 output_view_for_each_surface(data->output, con->view,
319 send_frame_done_iterator, data->when); 313 send_frame_done_iterator, data->when);
320} 314}
321 315
@@ -328,15 +322,14 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
328 .output = output, 322 .output = output,
329 .when = when, 323 .when = when,
330 }; 324 };
331 struct sway_container *workspace = output_get_active_workspace(output); 325 struct sway_workspace *workspace = output_get_active_workspace(output);
332 if (workspace->current.ws_fullscreen) { 326 if (workspace->current.fullscreen) {
333 send_frame_done_container_iterator( 327 send_frame_done_container_iterator(
334 workspace->current.ws_fullscreen, &data); 328 workspace->current.fullscreen, &data);
335 container_for_each_child(workspace->current.ws_fullscreen, 329 container_for_each_child(workspace->current.fullscreen,
336 send_frame_done_container_iterator, &data); 330 send_frame_done_container_iterator, &data);
337#ifdef HAVE_XWAYLAND 331#ifdef HAVE_XWAYLAND
338 send_frame_done_unmanaged(output, 332 send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when);
339 &root_container.sway_root->xwayland_unmanaged, when);
340#endif 333#endif
341 } else { 334 } else {
342 send_frame_done_layer(output, 335 send_frame_done_layer(output,
@@ -348,8 +341,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
348 send_frame_done_container_iterator, &data); 341 send_frame_done_container_iterator, &data);
349 342
350#ifdef HAVE_XWAYLAND 343#ifdef HAVE_XWAYLAND
351 send_frame_done_unmanaged(output, 344 send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when);
352 &root_container.sway_root->xwayland_unmanaged, when);
353#endif 345#endif
354 send_frame_done_layer(output, 346 send_frame_done_layer(output,
355 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when); 347 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], when);
@@ -358,8 +350,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) {
358send_frame_overlay: 350send_frame_overlay:
359 send_frame_done_layer(output, 351 send_frame_done_layer(output,
360 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when); 352 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], when);
361 send_frame_done_drag_icons(output, &root_container.sway_root->drag_icons, 353 send_frame_done_drag_icons(output, &root->drag_icons, when);
362 when);
363} 354}
364 355
365static void damage_handle_frame(struct wl_listener *listener, void *data) { 356static void damage_handle_frame(struct wl_listener *listener, void *data) {
@@ -391,7 +382,11 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) {
391} 382}
392 383
393void output_damage_whole(struct sway_output *output) { 384void output_damage_whole(struct sway_output *output) {
394 wlr_output_damage_add_whole(output->damage); 385 // The output can exist with no wlr_output if it's just been disconnected
386 // and the transaction to evacuate it has't completed yet.
387 if (output && output->wlr_output) {
388 wlr_output_damage_add_whole(output->damage);
389 }
395} 390}
396 391
397static void damage_surface_iterator(struct sway_output *output, 392static void damage_surface_iterator(struct sway_output *output,
@@ -446,14 +441,9 @@ void output_damage_surface(struct sway_output *output, double ox, double oy,
446 441
447static void output_damage_view(struct sway_output *output, 442static void output_damage_view(struct sway_output *output,
448 struct sway_view *view, bool whole) { 443 struct sway_view *view, bool whole) {
449 if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) {
450 return;
451 }
452
453 if (!view_is_visible(view)) { 444 if (!view_is_visible(view)) {
454 return; 445 return;
455 } 446 }
456
457 output_view_for_each_surface(output, view, damage_surface_iterator, &whole); 447 output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
458} 448}
459 449
@@ -466,31 +456,29 @@ void output_damage_from_view(struct sway_output *output,
466void output_damage_box(struct sway_output *output, struct wlr_box *_box) { 456void output_damage_box(struct sway_output *output, struct wlr_box *_box) {
467 struct wlr_box box; 457 struct wlr_box box;
468 memcpy(&box, _box, sizeof(struct wlr_box)); 458 memcpy(&box, _box, sizeof(struct wlr_box));
469 box.x -= output->swayc->current.swayc_x; 459 box.x -= output->wlr_output->lx;
470 box.y -= output->swayc->current.swayc_y; 460 box.y -= output->wlr_output->ly;
471 scale_box(&box, output->wlr_output->scale); 461 scale_box(&box, output->wlr_output->scale);
472 wlr_output_damage_add_box(output->damage, &box); 462 wlr_output_damage_add_box(output->damage, &box);
473} 463}
474 464
475static void output_damage_whole_container_iterator(struct sway_container *con, 465static void output_damage_whole_container_iterator(struct sway_container *con,
476 void *data) { 466 void *data) {
477 struct sway_output *output = data; 467 if (!sway_assert(con->view, "expected a view")) {
478
479 if (!sway_assert(con->type == C_VIEW, "expected a view")) {
480 return; 468 return;
481 } 469 }
482 470 struct sway_output *output = data;
483 output_damage_view(output, con->sway_view, true); 471 output_damage_view(output, con->view, true);
484} 472}
485 473
486void output_damage_whole_container(struct sway_output *output, 474void output_damage_whole_container(struct sway_output *output,
487 struct sway_container *con) { 475 struct sway_container *con) {
488 // Pad the box by 1px, because the width is a double and might be a fraction 476 // Pad the box by 1px, because the width is a double and might be a fraction
489 struct wlr_box box = { 477 struct wlr_box box = {
490 .x = con->current.swayc_x - output->wlr_output->lx - 1, 478 .x = con->current.con_x - output->wlr_output->lx - 1,
491 .y = con->current.swayc_y - output->wlr_output->ly - 1, 479 .y = con->current.con_y - output->wlr_output->ly - 1,
492 .width = con->current.swayc_width + 2, 480 .width = con->current.con_width + 2,
493 .height = con->current.swayc_height + 2, 481 .height = con->current.con_height + 2,
494 }; 482 };
495 scale_box(&box, output->wlr_output->scale); 483 scale_box(&box, output->wlr_output->scale);
496 wlr_output_damage_add_box(output->damage, &box); 484 wlr_output_damage_add_box(output->damage, &box);
@@ -499,44 +487,48 @@ void output_damage_whole_container(struct sway_output *output,
499static void damage_handle_destroy(struct wl_listener *listener, void *data) { 487static void damage_handle_destroy(struct wl_listener *listener, void *data) {
500 struct sway_output *output = 488 struct sway_output *output =
501 wl_container_of(listener, output, damage_destroy); 489 wl_container_of(listener, output, damage_destroy);
502 output_begin_destroy(output->swayc); 490 output_disable(output);
491 transaction_commit_dirty();
503} 492}
504 493
505static void handle_destroy(struct wl_listener *listener, void *data) { 494static void handle_destroy(struct wl_listener *listener, void *data) {
506 struct sway_output *output = wl_container_of(listener, output, destroy); 495 struct sway_output *output = wl_container_of(listener, output, destroy);
507 wl_signal_emit(&output->events.destroy, output); 496 wl_signal_emit(&output->events.destroy, output);
508 497
509 if (output->swayc) { 498 if (output->enabled) {
510 output_begin_destroy(output->swayc); 499 output_disable(output);
511 } 500 }
501 output_begin_destroy(output);
512 502
513 wl_list_remove(&output->link); 503 transaction_commit_dirty();
514 wl_list_remove(&output->destroy.link);
515 output->wlr_output->data = NULL;
516 free(output);
517
518 arrange_windows(&root_container);
519} 504}
520 505
521static void handle_mode(struct wl_listener *listener, void *data) { 506static void handle_mode(struct wl_listener *listener, void *data) {
522 struct sway_output *output = wl_container_of(listener, output, mode); 507 struct sway_output *output = wl_container_of(listener, output, mode);
523 arrange_layers(output); 508 arrange_layers(output);
524 arrange_windows(output->swayc); 509 arrange_output(output);
525 transaction_commit_dirty(); 510 transaction_commit_dirty();
526} 511}
527 512
528static void handle_transform(struct wl_listener *listener, void *data) { 513static void handle_transform(struct wl_listener *listener, void *data) {
529 struct sway_output *output = wl_container_of(listener, output, transform); 514 struct sway_output *output = wl_container_of(listener, output, transform);
530 arrange_layers(output); 515 arrange_layers(output);
531 arrange_windows(output->swayc); 516 arrange_output(output);
532 transaction_commit_dirty(); 517 transaction_commit_dirty();
533} 518}
534 519
520static void update_textures(struct sway_container *con, void *data) {
521 container_update_title_textures(con);
522 if (con->view) {
523 view_update_marks_textures(con->view);
524 }
525}
526
535static void handle_scale(struct wl_listener *listener, void *data) { 527static void handle_scale(struct wl_listener *listener, void *data) {
536 struct sway_output *output = wl_container_of(listener, output, scale); 528 struct sway_output *output = wl_container_of(listener, output, scale);
537 arrange_layers(output); 529 arrange_layers(output);
538 container_update_textures_recursive(output->swayc); 530 output_for_each_container(output, update_textures, NULL);
539 arrange_windows(output->swayc); 531 arrange_output(output);
540 transaction_commit_dirty(); 532 transaction_commit_dirty();
541} 533}
542 534
@@ -545,57 +537,27 @@ void handle_new_output(struct wl_listener *listener, void *data) {
545 struct wlr_output *wlr_output = data; 537 struct wlr_output *wlr_output = data;
546 wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); 538 wlr_log(WLR_DEBUG, "New output %p: %s", wlr_output, wlr_output->name);
547 539
548 struct sway_output *output = calloc(1, sizeof(struct sway_output)); 540 struct sway_output *output = output_create(wlr_output);
549 if (!output) { 541 if (!output) {
550 return; 542 return;
551 } 543 }
552 output->wlr_output = wlr_output;
553 wlr_output->data = output;
554 output->server = server; 544 output->server = server;
555 output->damage = wlr_output_damage_create(wlr_output); 545 output->damage = wlr_output_damage_create(wlr_output);
556
557 wl_signal_add(&wlr_output->events.destroy, &output->destroy);
558 output->destroy.notify = handle_destroy; 546 output->destroy.notify = handle_destroy;
559 547
560 wl_list_insert(&root_container.sway_root->all_outputs, &output->link); 548 struct output_config *oc = output_find_config(output);
561
562 output_enable(output);
563}
564
565void output_enable(struct sway_output *output) {
566 struct wlr_output *wlr_output = output->wlr_output;
567
568 if (!sway_assert(output->swayc == NULL, "output is already enabled")) {
569 return;
570 }
571
572 output->swayc = output_create(output);
573 if (!output->swayc) {
574 // Output is disabled
575 return;
576 }
577 549
578 size_t len = sizeof(output->layers) / sizeof(output->layers[0]); 550 if (oc && oc->enabled) {
579 for (size_t i = 0; i < len; ++i) { 551 output_enable(output, oc);
580 wl_list_init(&output->layers[i]);
581 } 552 }
582 wl_signal_init(&output->events.destroy);
583 553
584 input_manager_configure_xcursor(input_manager); 554 transaction_commit_dirty();
555}
585 556
586 wl_signal_add(&wlr_output->events.mode, &output->mode); 557void output_add_listeners(struct sway_output *output) {
587 output->mode.notify = handle_mode; 558 output->mode.notify = handle_mode;
588 wl_signal_add(&wlr_output->events.transform, &output->transform);
589 output->transform.notify = handle_transform; 559 output->transform.notify = handle_transform;
590 wl_signal_add(&wlr_output->events.scale, &output->scale);
591 output->scale.notify = handle_scale; 560 output->scale.notify = handle_scale;
592
593 wl_signal_add(&output->damage->events.frame, &output->damage_frame);
594 output->damage_frame.notify = damage_handle_frame; 561 output->damage_frame.notify = damage_handle_frame;
595 wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
596 output->damage_destroy.notify = damage_handle_destroy; 562 output->damage_destroy.notify = damage_handle_destroy;
597
598 arrange_layers(output);
599 arrange_windows(&root_container);
600 transaction_commit_dirty();
601} 563}