summaryrefslogtreecommitdiffstats
path: root/sway/desktop/render.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-30 21:00:10 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-09-05 18:01:43 +1000
commit7586f150c058997d9dde387ea7c091ffa7a3c3c7 (patch)
tree63d19027974c1db62ce3a74ca1d2314eb6d5049b /sway/desktop/render.c
parentMerge pull request #2569 from RyanDwyer/deny-reload-repeat (diff)
downloadsway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.gz
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.zst
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.zip
Implement type safe arguments and demote sway_container
This commit changes the meaning of sway_container so that it only refers to layout containers and view containers. Workspaces, outputs and the root are no longer known as containers. Instead, root, outputs, workspaces and containers are all a type of node, and containers come in two types: layout containers and view containers. In addition to the above, this implements type safe variables. This means we use specific types such as sway_output and sway_workspace instead of generic containers or nodes. However, it's worth noting that in a few places places (eg. seat focus and transactions) referring to them in a generic way is unavoidable which is why we still use nodes in some places. If you want a TL;DR, look at node.h, as well as the struct definitions for root, output, workspace and container. Note that sway_output now contains a workspaces list, and workspaces now contain a tiling and floating list, and containers now contain a pointer back to the workspace. There are now functions for seat_get_focused_workspace and seat_get_focused_container. The latter will return NULL if a workspace itself is focused. Most other seat functions like seat_get_focus and seat_set_focus now accept and return nodes. In the config->handler_context struct, current_container has been replaced with three pointers: node, container and workspace. node is the same as what current_container was, while workspace is the workspace that the node resides on and container is the actual container, which may be NULL if a workspace itself is focused. The global root_container variable has been replaced with one simply called root, which is a pointer to the sway_root instance. The way outputs are created, enabled, disabled and destroyed has changed. Previously we'd wrap the sway_output in a container when it is enabled, but as we don't have containers any more it needs a different approach. The output_create and output_destroy functions previously created/destroyed the container, but now they create/destroy the sway_output. There is a new function output_disable to disable an output without destroying it. Containers have a new view property. If this is populated then the container is a view container, otherwise it's a layout container. Like before, this property is immutable for the life of the container. Containers have both a `sway_container *parent` and `sway_workspace *workspace`. As we use specific types now, parent cannot point to a workspace so it'll be NULL for containers which are direct children of the workspace. The workspace property is set for all containers, except those which are hidden in the scratchpad as they have no workspace. In some cases we need to refer to workspaces in a container-like way. For example, workspaces have layout and children, but when using specific types this makes it difficult. Likewise, it's difficult for a container to get its parent's layout when the parent could be another container or a workspace. To make it easier, some helper functions have been created: container_parent_layout and container_get_siblings. container_remove_child has been renamed to container_detach and container_replace_child has been renamed to container_replace. `container_handle_fullscreen_reparent(con, old_parent)` has had the old_parent removed. We now unfullscreen the workspace when detaching the container, so this function is simplified and only needs one argument now. container_notify_subtree_changed has been renamed to container_update_representation. This is more descriptive of its purpose. I also wanted to be able to call it with whatever container was changed rather than the container's parent, which makes bubbling up to the workspace easier. There are now state structs per node thing. ie. sway_output_state, sway_workspace_state and sway_container_state. The focus, move and layout commands have been completely refactored to work with the specific types. I considered making these a separate PR, but I'd be backporting my changes only to replace them again, and it's easier just to test everything at once.
Diffstat (limited to 'sway/desktop/render.c')
-rw-r--r--sway/desktop/render.c259
1 files changed, 145 insertions, 114 deletions
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index 695213eb..99b2cf3d 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -193,10 +193,10 @@ static void render_view_toplevels(struct sway_view *view,
193 .alpha = alpha, 193 .alpha = alpha,
194 }; 194 };
195 // Render all toplevels without descending into popups 195 // Render all toplevels without descending into popups
196 double ox = 196 double ox = view->container->current.view_x -
197 view->swayc->current.view_x - output->wlr_output->lx - view->geometry.x; 197 output->wlr_output->lx - view->geometry.x;
198 double oy = 198 double oy = view->container->current.view_y -
199 view->swayc->current.view_y - output->wlr_output->ly - view->geometry.y; 199 output->wlr_output->ly - view->geometry.y;
200 output_surface_for_each_surface(output, view->surface, ox, oy, 200 output_surface_for_each_surface(output, view->surface, ox, oy,
201 render_surface_iterator, &data); 201 render_surface_iterator, &data);
202} 202}
@@ -229,17 +229,17 @@ static void render_saved_view(struct sway_view *view,
229 return; 229 return;
230 } 230 }
231 struct wlr_box box = { 231 struct wlr_box box = {
232 .x = view->swayc->current.view_x - output->swayc->current.swayc_x - 232 .x = view->container->current.view_x - output->wlr_output->lx -
233 view->saved_geometry.x, 233 view->saved_geometry.x,
234 .y = view->swayc->current.view_y - output->swayc->current.swayc_y - 234 .y = view->container->current.view_y - output->wlr_output->ly -
235 view->saved_geometry.y, 235 view->saved_geometry.y,
236 .width = view->saved_buffer_width, 236 .width = view->saved_buffer_width,
237 .height = view->saved_buffer_height, 237 .height = view->saved_buffer_height,
238 }; 238 };
239 239
240 struct wlr_box output_box = { 240 struct wlr_box output_box = {
241 .width = output->swayc->current.swayc_width, 241 .width = output->wlr_output->width,
242 .height = output->swayc->current.swayc_height, 242 .height = output->wlr_output->height,
243 }; 243 };
244 244
245 struct wlr_box intersection; 245 struct wlr_box intersection;
@@ -263,14 +263,14 @@ static void render_saved_view(struct sway_view *view,
263 */ 263 */
264static void render_view(struct sway_output *output, pixman_region32_t *damage, 264static void render_view(struct sway_output *output, pixman_region32_t *damage,
265 struct sway_container *con, struct border_colors *colors) { 265 struct sway_container *con, struct border_colors *colors) {
266 struct sway_view *view = con->sway_view; 266 struct sway_view *view = con->view;
267 if (view->saved_buffer) { 267 if (view->saved_buffer) {
268 render_saved_view(view, output, damage, view->swayc->alpha); 268 render_saved_view(view, output, damage, view->container->alpha);
269 } else { 269 } else {
270 render_view_toplevels(view, output, damage, view->swayc->alpha); 270 render_view_toplevels(view, output, damage, view->container->alpha);
271 } 271 }
272 272
273 if (view->swayc->current.using_csd) { 273 if (view->container->current.using_csd) {
274 return; 274 return;
275 } 275 }
276 276
@@ -283,7 +283,7 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
283 if (state->border_left) { 283 if (state->border_left) {
284 memcpy(&color, colors->child_border, sizeof(float) * 4); 284 memcpy(&color, colors->child_border, sizeof(float) * 4);
285 premultiply_alpha(color, con->alpha); 285 premultiply_alpha(color, con->alpha);
286 box.x = state->swayc_x; 286 box.x = state->con_x;
287 box.y = state->view_y; 287 box.y = state->view_y;
288 box.width = state->border_thickness; 288 box.width = state->border_thickness;
289 box.height = state->view_height; 289 box.height = state->view_height;
@@ -291,9 +291,12 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
291 render_rect(output->wlr_output, damage, &box, color); 291 render_rect(output->wlr_output, damage, &box, color);
292 } 292 }
293 293
294 list_t *siblings = container_get_current_siblings(con);
295 enum sway_container_layout layout =
296 container_current_parent_layout(con);
297
294 if (state->border_right) { 298 if (state->border_right) {
295 if (state->parent->current.children->length == 1 299 if (siblings->length == 1 && layout == L_HORIZ) {
296 && state->parent->current.layout == L_HORIZ) {
297 memcpy(&color, colors->indicator, sizeof(float) * 4); 300 memcpy(&color, colors->indicator, sizeof(float) * 4);
298 } else { 301 } else {
299 memcpy(&color, colors->child_border, sizeof(float) * 4); 302 memcpy(&color, colors->child_border, sizeof(float) * 4);
@@ -308,16 +311,15 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
308 } 311 }
309 312
310 if (state->border_bottom) { 313 if (state->border_bottom) {
311 if (state->parent->current.children->length == 1 314 if (siblings->length == 1 && layout == L_VERT) {
312 && con->current.parent->current.layout == L_VERT) {
313 memcpy(&color, colors->indicator, sizeof(float) * 4); 315 memcpy(&color, colors->indicator, sizeof(float) * 4);
314 } else { 316 } else {
315 memcpy(&color, colors->child_border, sizeof(float) * 4); 317 memcpy(&color, colors->child_border, sizeof(float) * 4);
316 } 318 }
317 premultiply_alpha(color, con->alpha); 319 premultiply_alpha(color, con->alpha);
318 box.x = state->swayc_x; 320 box.x = state->con_x;
319 box.y = state->view_y + state->view_height; 321 box.y = state->view_y + state->view_height;
320 box.width = state->swayc_width; 322 box.width = state->con_width;
321 box.height = state->border_thickness; 323 box.height = state->border_thickness;
322 scale_box(&box, output_scale); 324 scale_box(&box, output_scale);
323 render_rect(output->wlr_output, damage, &box, color); 325 render_rect(output->wlr_output, damage, &box, color);
@@ -344,12 +346,12 @@ static void render_titlebar(struct sway_output *output,
344 float color[4]; 346 float color[4];
345 struct sway_container_state *state = &con->current; 347 struct sway_container_state *state = &con->current;
346 float output_scale = output->wlr_output->scale; 348 float output_scale = output->wlr_output->scale;
347 enum sway_container_layout layout = state->parent->current.layout; 349 enum sway_container_layout layout = container_current_parent_layout(con);
348 list_t *children = state->parent->current.children; 350 list_t *children = container_get_current_siblings(con);
349 bool is_last_child = children->length == 0 || 351 bool is_last_child = children->length == 0 ||
350 children->items[children->length - 1] == con; 352 children->items[children->length - 1] == con;
351 double output_x = output->swayc->current.swayc_x; 353 double output_x = output->wlr_output->lx;
352 double output_y = output->swayc->current.swayc_y; 354 double output_y = output->wlr_output->ly;
353 355
354 // Single pixel bar above title 356 // Single pixel bar above title
355 memcpy(&color, colors->border, sizeof(float) * 4); 357 memcpy(&color, colors->border, sizeof(float) * 4);
@@ -366,7 +368,7 @@ static void render_titlebar(struct sway_output *output,
366 bool connects_sides = false; 368 bool connects_sides = false;
367 if (layout == L_HORIZ || layout == L_VERT || 369 if (layout == L_HORIZ || layout == L_VERT ||
368 (layout == L_STACKED && is_last_child)) { 370 (layout == L_STACKED && is_last_child)) {
369 if (con->type == C_VIEW) { 371 if (con->view) {
370 left_offset = state->border_left * state->border_thickness; 372 left_offset = state->border_left * state->border_thickness;
371 right_offset = state->border_right * state->border_thickness; 373 right_offset = state->border_right * state->border_thickness;
372 connects_sides = true; 374 connects_sides = true;
@@ -542,14 +544,22 @@ static void render_top_border(struct sway_output *output,
542 // Child border - top edge 544 // Child border - top edge
543 memcpy(&color, colors->child_border, sizeof(float) * 4); 545 memcpy(&color, colors->child_border, sizeof(float) * 4);
544 premultiply_alpha(color, con->alpha); 546 premultiply_alpha(color, con->alpha);
545 box.x = state->swayc_x; 547 box.x = state->con_x;
546 box.y = state->swayc_y; 548 box.y = state->con_y;
547 box.width = state->swayc_width; 549 box.width = state->con_width;
548 box.height = state->border_thickness; 550 box.height = state->border_thickness;
549 scale_box(&box, output_scale); 551 scale_box(&box, output_scale);
550 render_rect(output->wlr_output, output_damage, &box, color); 552 render_rect(output->wlr_output, output_damage, &box, color);
551} 553}
552 554
555struct parent_data {
556 enum sway_container_layout layout;
557 struct wlr_box box;
558 list_t *children;
559 bool focused;
560 struct sway_container *active_child;
561};
562
553static void render_container(struct sway_output *output, 563static void render_container(struct sway_output *output,
554 pixman_region32_t *damage, struct sway_container *con, bool parent_focused); 564 pixman_region32_t *damage, struct sway_container *con, bool parent_focused);
555 565
@@ -559,14 +569,13 @@ static void render_container(struct sway_output *output,
559 * Wrap child views in borders and leave child containers borderless because 569 * Wrap child views in borders and leave child containers borderless because
560 * they'll apply their own borders to their children. 570 * they'll apply their own borders to their children.
561 */ 571 */
562static void render_container_simple(struct sway_output *output, 572static void render_containers_linear(struct sway_output *output,
563 pixman_region32_t *damage, struct sway_container *con, 573 pixman_region32_t *damage, struct parent_data *parent) {
564 bool parent_focused) { 574 for (int i = 0; i < parent->children->length; ++i) {
565 for (int i = 0; i < con->current.children->length; ++i) { 575 struct sway_container *child = parent->children->items[i];
566 struct sway_container *child = con->current.children->items[i]; 576
567 577 if (child->view) {
568 if (child->type == C_VIEW) { 578 struct sway_view *view = child->view;
569 struct sway_view *view = child->sway_view;
570 struct border_colors *colors; 579 struct border_colors *colors;
571 struct wlr_texture *title_texture; 580 struct wlr_texture *title_texture;
572 struct wlr_texture *marks_texture; 581 struct wlr_texture *marks_texture;
@@ -576,11 +585,11 @@ static void render_container_simple(struct sway_output *output,
576 colors = &config->border_colors.urgent; 585 colors = &config->border_colors.urgent;
577 title_texture = child->title_urgent; 586 title_texture = child->title_urgent;
578 marks_texture = view->marks_urgent; 587 marks_texture = view->marks_urgent;
579 } else if (state->focused || parent_focused) { 588 } else if (state->focused || parent->focused) {
580 colors = &config->border_colors.focused; 589 colors = &config->border_colors.focused;
581 title_texture = child->title_focused; 590 title_texture = child->title_focused;
582 marks_texture = view->marks_focused; 591 marks_texture = view->marks_focused;
583 } else if (con->current.focused_inactive_child == child) { 592 } else if (child == parent->active_child) {
584 colors = &config->border_colors.focused_inactive; 593 colors = &config->border_colors.focused_inactive;
585 title_texture = child->title_focused_inactive; 594 title_texture = child->title_focused_inactive;
586 marks_texture = view->marks_focused_inactive; 595 marks_texture = view->marks_focused_inactive;
@@ -590,10 +599,10 @@ static void render_container_simple(struct sway_output *output,
590 marks_texture = view->marks_unfocused; 599 marks_texture = view->marks_unfocused;
591 } 600 }
592 601
593 if (!view->swayc->current.using_csd) { 602 if (!view->container->current.using_csd) {
594 if (state->border == B_NORMAL) { 603 if (state->border == B_NORMAL) {
595 render_titlebar(output, damage, child, state->swayc_x, 604 render_titlebar(output, damage, child, state->con_x,
596 state->swayc_y, state->swayc_width, colors, 605 state->con_y, state->con_width, colors,
597 title_texture, marks_texture); 606 title_texture, marks_texture);
598 } else { 607 } else {
599 render_top_border(output, damage, child, colors); 608 render_top_border(output, damage, child, colors);
@@ -602,7 +611,7 @@ static void render_container_simple(struct sway_output *output,
602 render_view(output, damage, child, colors); 611 render_view(output, damage, child, colors);
603 } else { 612 } else {
604 render_container(output, damage, child, 613 render_container(output, damage, child,
605 parent_focused || child->current.focused); 614 parent->focused || child->current.focused);
606 } 615 }
607 } 616 }
608} 617}
@@ -610,22 +619,19 @@ static void render_container_simple(struct sway_output *output,
610/** 619/**
611 * Render a container's children using the L_TABBED layout. 620 * Render a container's children using the L_TABBED layout.
612 */ 621 */
613static void render_container_tabbed(struct sway_output *output, 622static void render_containers_tabbed(struct sway_output *output,
614 pixman_region32_t *damage, struct sway_container *con, 623 pixman_region32_t *damage, struct parent_data *parent) {
615 bool parent_focused) { 624 if (!parent->children->length) {
616 if (!con->current.children->length) {
617 return; 625 return;
618 } 626 }
619 struct sway_container_state *pstate = &con->current; 627 struct sway_container *current = parent->active_child;
620 struct sway_container *current = pstate->focused_inactive_child;
621 struct border_colors *current_colors = &config->border_colors.unfocused; 628 struct border_colors *current_colors = &config->border_colors.unfocused;
622 629 int tab_width = parent->box.width / parent->children->length;
623 int tab_width = (pstate->swayc_width) / pstate->children->length;
624 630
625 // Render tabs 631 // Render tabs
626 for (int i = 0; i < pstate->children->length; ++i) { 632 for (int i = 0; i < parent->children->length; ++i) {
627 struct sway_container *child = pstate->children->items[i]; 633 struct sway_container *child = parent->children->items[i];
628 struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; 634 struct sway_view *view = child->view;
629 struct sway_container_state *cstate = &child->current; 635 struct sway_container_state *cstate = &child->current;
630 struct border_colors *colors; 636 struct border_colors *colors;
631 struct wlr_texture *title_texture; 637 struct wlr_texture *title_texture;
@@ -637,11 +643,11 @@ static void render_container_tabbed(struct sway_output *output,
637 colors = &config->border_colors.urgent; 643 colors = &config->border_colors.urgent;
638 title_texture = child->title_urgent; 644 title_texture = child->title_urgent;
639 marks_texture = view ? view->marks_urgent : NULL; 645 marks_texture = view ? view->marks_urgent : NULL;
640 } else if (cstate->focused || parent_focused) { 646 } else if (cstate->focused || parent->focused) {
641 colors = &config->border_colors.focused; 647 colors = &config->border_colors.focused;
642 title_texture = child->title_focused; 648 title_texture = child->title_focused;
643 marks_texture = view ? view->marks_focused : NULL; 649 marks_texture = view ? view->marks_focused : NULL;
644 } else if (child == pstate->focused_inactive_child) { 650 } else if (child == parent->active_child) {
645 colors = &config->border_colors.focused_inactive; 651 colors = &config->border_colors.focused_inactive;
646 title_texture = child->title_focused_inactive; 652 title_texture = child->title_focused_inactive;
647 marks_texture = view ? view->marks_focused_inactive : NULL; 653 marks_texture = view ? view->marks_focused_inactive : NULL;
@@ -651,14 +657,14 @@ static void render_container_tabbed(struct sway_output *output,
651 marks_texture = view ? view->marks_unfocused : NULL; 657 marks_texture = view ? view->marks_unfocused : NULL;
652 } 658 }
653 659
654 int x = cstate->swayc_x + tab_width * i; 660 int x = cstate->con_x + tab_width * i;
655 661
656 // Make last tab use the remaining width of the parent 662 // Make last tab use the remaining width of the parent
657 if (i == pstate->children->length - 1) { 663 if (i == parent->children->length - 1) {
658 tab_width = pstate->swayc_width - tab_width * i; 664 tab_width = parent->box.width - tab_width * i;
659 } 665 }
660 666
661 render_titlebar(output, damage, child, x, pstate->swayc_y, tab_width, 667 render_titlebar(output, damage, child, x, parent->box.y, tab_width,
662 colors, title_texture, marks_texture); 668 colors, title_texture, marks_texture);
663 669
664 if (child == current) { 670 if (child == current) {
@@ -667,33 +673,30 @@ static void render_container_tabbed(struct sway_output *output,
667 } 673 }
668 674
669 // Render surface and left/right/bottom borders 675 // Render surface and left/right/bottom borders
670 if (current->type == C_VIEW) { 676 if (current->view) {
671 render_view(output, damage, current, current_colors); 677 render_view(output, damage, current, current_colors);
672 } else { 678 } else {
673 render_container(output, damage, current, 679 render_container(output, damage, current,
674 parent_focused || current->current.focused); 680 parent->focused || current->current.focused);
675 } 681 }
676} 682}
677 683
678/** 684/**
679 * Render a container's children using the L_STACKED layout. 685 * Render a container's children using the L_STACKED layout.
680 */ 686 */
681static void render_container_stacked(struct sway_output *output, 687static void render_containers_stacked(struct sway_output *output,
682 pixman_region32_t *damage, struct sway_container *con, 688 pixman_region32_t *damage, struct parent_data *parent) {
683 bool parent_focused) { 689 if (!parent->children->length) {
684 if (!con->current.children->length) {
685 return; 690 return;
686 } 691 }
687 struct sway_container_state *pstate = &con->current; 692 struct sway_container *current = parent->active_child;
688 struct sway_container *current = pstate->focused_inactive_child;
689 struct border_colors *current_colors = &config->border_colors.unfocused; 693 struct border_colors *current_colors = &config->border_colors.unfocused;
690
691 size_t titlebar_height = container_titlebar_height(); 694 size_t titlebar_height = container_titlebar_height();
692 695
693 // Render titles 696 // Render titles
694 for (int i = 0; i < pstate->children->length; ++i) { 697 for (int i = 0; i < parent->children->length; ++i) {
695 struct sway_container *child = pstate->children->items[i]; 698 struct sway_container *child = parent->children->items[i];
696 struct sway_view *view = child->type == C_VIEW ? child->sway_view : NULL; 699 struct sway_view *view = child->view;
697 struct sway_container_state *cstate = &child->current; 700 struct sway_container_state *cstate = &child->current;
698 struct border_colors *colors; 701 struct border_colors *colors;
699 struct wlr_texture *title_texture; 702 struct wlr_texture *title_texture;
@@ -705,11 +708,11 @@ static void render_container_stacked(struct sway_output *output,
705 colors = &config->border_colors.urgent; 708 colors = &config->border_colors.urgent;
706 title_texture = child->title_urgent; 709 title_texture = child->title_urgent;
707 marks_texture = view ? view->marks_urgent : NULL; 710 marks_texture = view ? view->marks_urgent : NULL;
708 } else if (cstate->focused || parent_focused) { 711 } else if (cstate->focused || parent->focused) {
709 colors = &config->border_colors.focused; 712 colors = &config->border_colors.focused;
710 title_texture = child->title_focused; 713 title_texture = child->title_focused;
711 marks_texture = view ? view->marks_focused : NULL; 714 marks_texture = view ? view->marks_focused : NULL;
712 } else if (child == pstate->focused_inactive_child) { 715 } else if (child == parent->active_child) {
713 colors = &config->border_colors.focused_inactive; 716 colors = &config->border_colors.focused_inactive;
714 title_texture = child->title_focused_inactive; 717 title_texture = child->title_focused_inactive;
715 marks_texture = view ? view->marks_focused_inactive : NULL; 718 marks_texture = view ? view->marks_focused_inactive : NULL;
@@ -719,9 +722,9 @@ static void render_container_stacked(struct sway_output *output,
719 marks_texture = view ? view->marks_unfocused : NULL; 722 marks_texture = view ? view->marks_unfocused : NULL;
720 } 723 }
721 724
722 int y = pstate->swayc_y + titlebar_height * i; 725 int y = parent->box.y + titlebar_height * i;
723 render_titlebar(output, damage, child, pstate->swayc_x, y, 726 render_titlebar(output, damage, child, parent->box.x, y,
724 pstate->swayc_width, colors, title_texture, marks_texture); 727 parent->box.width, colors, title_texture, marks_texture);
725 728
726 if (child == current) { 729 if (child == current) {
727 current_colors = colors; 730 current_colors = colors;
@@ -729,36 +732,69 @@ static void render_container_stacked(struct sway_output *output,
729 } 732 }
730 733
731 // Render surface and left/right/bottom borders 734 // Render surface and left/right/bottom borders
732 if (current->type == C_VIEW) { 735 if (current->view) {
733 render_view(output, damage, current, current_colors); 736 render_view(output, damage, current, current_colors);
734 } else { 737 } else {
735 render_container(output, damage, current, 738 render_container(output, damage, current,
736 parent_focused || current->current.focused); 739 parent->focused || current->current.focused);
737 } 740 }
738} 741}
739 742
740static void render_container(struct sway_output *output, 743static void render_containers(struct sway_output *output,
741 pixman_region32_t *damage, struct sway_container *con, 744 pixman_region32_t *damage, struct parent_data *parent) {
742 bool parent_focused) { 745 switch (parent->layout) {
743 switch (con->current.layout) {
744 case L_NONE: 746 case L_NONE:
745 case L_HORIZ: 747 case L_HORIZ:
746 case L_VERT: 748 case L_VERT:
747 render_container_simple(output, damage, con, parent_focused); 749 render_containers_linear(output, damage, parent);
748 break; 750 break;
749 case L_STACKED: 751 case L_STACKED:
750 render_container_stacked(output, damage, con, parent_focused); 752 render_containers_stacked(output, damage, parent);
751 break; 753 break;
752 case L_TABBED: 754 case L_TABBED:
753 render_container_tabbed(output, damage, con, parent_focused); 755 render_containers_tabbed(output, damage, parent);
754 break; 756 break;
755 } 757 }
756} 758}
757 759
760static void render_container(struct sway_output *output,
761 pixman_region32_t *damage, struct sway_container *con, bool focused) {
762 struct parent_data data = {
763 .layout = con->current.layout,
764 .box = {
765 .x = con->current.con_x,
766 .y = con->current.con_y,
767 .width = con->current.con_width,
768 .height = con->current.con_height,
769 },
770 .children = con->current.children,
771 .focused = focused,
772 .active_child = con->current.focused_inactive_child,
773 };
774 render_containers(output, damage, &data);
775}
776
777static void render_workspace(struct sway_output *output,
778 pixman_region32_t *damage, struct sway_workspace *ws, bool focused) {
779 struct parent_data data = {
780 .layout = ws->current.layout,
781 .box = {
782 .x = ws->current.x,
783 .y = ws->current.y,
784 .width = ws->current.width,
785 .height = ws->current.height,
786 },
787 .children = ws->current.tiling,
788 .focused = focused,
789 .active_child = ws->current.focused_inactive_child,
790 };
791 render_containers(output, damage, &data);
792}
793
758static void render_floating_container(struct sway_output *soutput, 794static void render_floating_container(struct sway_output *soutput,
759 pixman_region32_t *damage, struct sway_container *con) { 795 pixman_region32_t *damage, struct sway_container *con) {
760 if (con->type == C_VIEW) { 796 if (con->view) {
761 struct sway_view *view = con->sway_view; 797 struct sway_view *view = con->view;
762 struct border_colors *colors; 798 struct border_colors *colors;
763 struct wlr_texture *title_texture; 799 struct wlr_texture *title_texture;
764 struct wlr_texture *marks_texture; 800 struct wlr_texture *marks_texture;
@@ -777,10 +813,10 @@ static void render_floating_container(struct sway_output *soutput,
777 marks_texture = view->marks_unfocused; 813 marks_texture = view->marks_unfocused;
778 } 814 }
779 815
780 if (!view->swayc->current.using_csd) { 816 if (!view->container->current.using_csd) {
781 if (con->current.border == B_NORMAL) { 817 if (con->current.border == B_NORMAL) {
782 render_titlebar(soutput, damage, con, con->current.swayc_x, 818 render_titlebar(soutput, damage, con, con->current.con_x,
783 con->current.swayc_y, con->current.swayc_width, colors, 819 con->current.con_y, con->current.con_width, colors,
784 title_texture, marks_texture); 820 title_texture, marks_texture);
785 } else if (con->current.border != B_NONE) { 821 } else if (con->current.border != B_NONE) {
786 render_top_border(soutput, damage, con, colors); 822 render_top_border(soutput, damage, con, colors);
@@ -794,17 +830,15 @@ static void render_floating_container(struct sway_output *soutput,
794 830
795static void render_floating(struct sway_output *soutput, 831static void render_floating(struct sway_output *soutput,
796 pixman_region32_t *damage) { 832 pixman_region32_t *damage) {
797 for (int i = 0; i < root_container.current.children->length; ++i) { 833 for (int i = 0; i < root->outputs->length; ++i) {
798 struct sway_container *output = 834 struct sway_output *output = root->outputs->items[i];
799 root_container.current.children->items[i]; 835 for (int j = 0; j < output->current.workspaces->length; ++j) {
800 for (int j = 0; j < output->current.children->length; ++j) { 836 struct sway_workspace *ws = output->current.workspaces->items[j];
801 struct sway_container *ws = output->current.children->items[j];
802 if (!workspace_is_visible(ws)) { 837 if (!workspace_is_visible(ws)) {
803 continue; 838 continue;
804 } 839 }
805 list_t *floating = ws->current.ws_floating; 840 for (int k = 0; k < ws->current.floating->length; ++k) {
806 for (int k = 0; k < floating->length; ++k) { 841 struct sway_container *floater = ws->current.floating->items[k];
807 struct sway_container *floater = floating->items[k];
808 render_floating_container(soutput, damage, floater); 842 render_floating_container(soutput, damage, floater);
809 } 843 }
810 } 844 }
@@ -837,8 +871,8 @@ void output_render(struct sway_output *output, struct timespec *when,
837 pixman_region32_union_rect(damage, damage, 0, 0, width, height); 871 pixman_region32_union_rect(damage, damage, 0, 0, width, height);
838 } 872 }
839 873
840 struct sway_container *workspace = output_get_active_workspace(output); 874 struct sway_workspace *workspace = output_get_active_workspace(output);
841 struct sway_container *fullscreen_con = workspace->current.ws_fullscreen; 875 struct sway_container *fullscreen_con = workspace->current.fullscreen;
842 876
843 if (output_has_opaque_overlay_layer_surface(output)) { 877 if (output_has_opaque_overlay_layer_surface(output)) {
844 goto render_overlay; 878 goto render_overlay;
@@ -855,12 +889,11 @@ void output_render(struct sway_output *output, struct timespec *when,
855 } 889 }
856 890
857 // TODO: handle views smaller than the output 891 // TODO: handle views smaller than the output
858 if (fullscreen_con->type == C_VIEW) { 892 if (fullscreen_con->view) {
859 if (fullscreen_con->sway_view->saved_buffer) { 893 if (fullscreen_con->view->saved_buffer) {
860 render_saved_view(fullscreen_con->sway_view, 894 render_saved_view(fullscreen_con->view, output, damage, 1.0f);
861 output, damage, 1.0f);
862 } else { 895 } else {
863 render_view_toplevels(fullscreen_con->sway_view, 896 render_view_toplevels(fullscreen_con->view,
864 output, damage, 1.0f); 897 output, damage, 1.0f);
865 } 898 }
866 } else { 899 } else {
@@ -868,8 +901,7 @@ void output_render(struct sway_output *output, struct timespec *when,
868 fullscreen_con->current.focused); 901 fullscreen_con->current.focused);
869 } 902 }
870#ifdef HAVE_XWAYLAND 903#ifdef HAVE_XWAYLAND
871 render_unmanaged(output, damage, 904 render_unmanaged(output, damage, &root->xwayland_unmanaged);
872 &root_container.sway_root->xwayland_unmanaged);
873#endif 905#endif
874 } else { 906 } else {
875 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 907 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
@@ -886,31 +918,30 @@ void output_render(struct sway_output *output, struct timespec *when,
886 render_layer(output, damage, 918 render_layer(output, damage,
887 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); 919 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
888 920
889 render_container(output, damage, workspace, workspace->current.focused); 921 render_workspace(output, damage, workspace, workspace->current.focused);
890 render_floating(output, damage); 922 render_floating(output, damage);
891#ifdef HAVE_XWAYLAND 923#ifdef HAVE_XWAYLAND
892 render_unmanaged(output, damage, 924 render_unmanaged(output, damage, &root->xwayland_unmanaged);
893 &root_container.sway_root->xwayland_unmanaged);
894#endif 925#endif
895 render_layer(output, damage, 926 render_layer(output, damage,
896 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); 927 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
897 } 928 }
898 929
899 struct sway_seat *seat = input_manager_current_seat(input_manager); 930 struct sway_seat *seat = input_manager_current_seat(input_manager);
900 struct sway_container *focus = seat_get_focus(seat); 931 struct sway_container *focus = seat_get_focused_container(seat);
901 if (focus && focus->type == C_VIEW) { 932 if (focus && focus->view) {
902 render_view_popups(focus->sway_view, output, damage, focus->alpha); 933 render_view_popups(focus->view, output, damage, focus->alpha);
903 } 934 }
904 935
905render_overlay: 936render_overlay:
906 render_layer(output, damage, 937 render_layer(output, damage,
907 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); 938 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
908 render_drag_icons(output, damage, &root_container.sway_root->drag_icons); 939 render_drag_icons(output, damage, &root->drag_icons);
909 940
910renderer_end: 941renderer_end:
911 if (debug.render_tree) { 942 if (debug.render_tree) {
912 wlr_renderer_scissor(renderer, NULL); 943 wlr_renderer_scissor(renderer, NULL);
913 wlr_render_texture(renderer, root_container.sway_root->debug_tree, 944 wlr_render_texture(renderer, root->debug_tree,
914 wlr_output->transform_matrix, 0, 40, 1); 945 wlr_output->transform_matrix, 0, 40, 1);
915 } 946 }
916 if (debug.damage == DAMAGE_HIGHLIGHT) { 947 if (debug.damage == DAMAGE_HIGHLIGHT) {