aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r--sway/tree/container.c148
1 files changed, 107 insertions, 41 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 4e85021d..b980c5e9 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -62,8 +62,10 @@ void container_create_notify(struct sway_container *container) {
62 // TODO send ipc event type based on the container type 62 // TODO send ipc event type based on the container type
63 wl_signal_emit(&root_container.sway_root->events.new_container, container); 63 wl_signal_emit(&root_container.sway_root->events.new_container, container);
64 64
65 if (container->type == C_VIEW || container->type == C_CONTAINER) { 65 if (container->type == C_VIEW) {
66 ipc_event_window(container, "new"); 66 ipc_event_window(container, "new");
67 } else if (container->type == C_WORKSPACE) {
68 ipc_event_workspace(NULL, container, "init");
67 } 69 }
68} 70}
69 71
@@ -281,7 +283,7 @@ static struct sway_container *container_output_destroy(
281 container_remove_child(workspace); 283 container_remove_child(workspace);
282 if (!workspace_is_empty(workspace)) { 284 if (!workspace_is_empty(workspace)) {
283 container_add_child(new_output, workspace); 285 container_add_child(new_output, workspace);
284 ipc_event_workspace(workspace, NULL, "move"); 286 ipc_event_workspace(NULL, workspace, "move");
285 } else { 287 } else {
286 container_destroy(workspace); 288 container_destroy(workspace);
287 } 289 }
@@ -319,7 +321,13 @@ static struct sway_container *container_destroy_noreaping(
319 } 321 }
320 322
321 wl_signal_emit(&con->events.destroy, con); 323 wl_signal_emit(&con->events.destroy, con);
322 ipc_event_window(con, "close"); 324
325 // emit IPC event
326 if (con->type == C_VIEW) {
327 ipc_event_window(con, "close");
328 } else if (con->type == C_WORKSPACE) {
329 ipc_event_workspace(NULL, con, "empty");
330 }
323 331
324 // The below functions move their children to somewhere else. 332 // The below functions move their children to somewhere else.
325 if (con->type == C_OUTPUT) { 333 if (con->type == C_OUTPUT) {
@@ -561,10 +569,15 @@ static struct sway_container *container_at_view(struct sway_container *swayc,
561 *sx = _sx; 569 *sx = _sx;
562 *sy = _sy; 570 *sy = _sy;
563 *surface = _surface; 571 *surface = _surface;
572 return swayc;
564 } 573 }
565 return swayc; 574 return NULL;
566} 575}
567 576
577static struct sway_container *tiling_container_at(
578 struct sway_container *con, double lx, double ly,
579 struct wlr_surface **surface, double *sx, double *sy);
580
568/** 581/**
569 * container_at for a container with layout L_TABBED. 582 * container_at for a container with layout L_TABBED.
570 */ 583 */
@@ -591,7 +604,7 @@ static struct sway_container *container_at_tabbed(struct sway_container *parent,
591 // Surfaces 604 // Surfaces
592 struct sway_container *current = seat_get_active_child(seat, parent); 605 struct sway_container *current = seat_get_active_child(seat, parent);
593 606
594 return container_at(current, lx, ly, surface, sx, sy); 607 return tiling_container_at(current, lx, ly, surface, sx, sy);
595} 608}
596 609
597/** 610/**
@@ -616,7 +629,7 @@ static struct sway_container *container_at_stacked(
616 // Surfaces 629 // Surfaces
617 struct sway_container *current = seat_get_active_child(seat, parent); 630 struct sway_container *current = seat_get_active_child(seat, parent);
618 631
619 return container_at(current, lx, ly, surface, sx, sy); 632 return tiling_container_at(current, lx, ly, surface, sx, sy);
620} 633}
621 634
622/** 635/**
@@ -634,45 +647,13 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
634 .height = child->height, 647 .height = child->height,
635 }; 648 };
636 if (wlr_box_contains_point(&box, lx, ly)) { 649 if (wlr_box_contains_point(&box, lx, ly)) {
637 return container_at(child, lx, ly, surface, sx, sy); 650 return tiling_container_at(child, lx, ly, surface, sx, sy);
638 } 651 }
639 } 652 }
640 return NULL; 653 return NULL;
641} 654}
642 655
643struct sway_container *container_at(struct sway_container *parent, 656static struct sway_container *floating_container_at(double lx, double ly,
644 double lx, double ly,
645 struct wlr_surface **surface, double *sx, double *sy) {
646 if (!sway_assert(parent->type >= C_WORKSPACE,
647 "Expected workspace or deeper")) {
648 return NULL;
649 }
650 if (parent->type == C_VIEW) {
651 return container_at_view(parent, lx, ly, surface, sx, sy);
652 }
653 if (!parent->children->length) {
654 return NULL;
655 }
656
657 switch (parent->layout) {
658 case L_HORIZ:
659 case L_VERT:
660 return container_at_linear(parent, lx, ly, surface, sx, sy);
661 case L_TABBED:
662 return container_at_tabbed(parent, lx, ly, surface, sx, sy);
663 case L_STACKED:
664 return container_at_stacked(parent, lx, ly, surface, sx, sy);
665 case L_FLOATING:
666 sway_assert(false, "Didn't expect to see floating here");
667 return NULL;
668 case L_NONE:
669 return NULL;
670 }
671
672 return NULL;
673}
674
675struct sway_container *floating_container_at(double lx, double ly,
676 struct wlr_surface **surface, double *sx, double *sy) { 657 struct wlr_surface **surface, double *sx, double *sy) {
677 for (int i = 0; i < root_container.children->length; ++i) { 658 for (int i = 0; i < root_container.children->length; ++i) {
678 struct sway_container *output = root_container.children->items[i]; 659 struct sway_container *output = root_container.children->items[i];
@@ -694,7 +675,8 @@ struct sway_container *floating_container_at(double lx, double ly,
694 .height = floater->height, 675 .height = floater->height,
695 }; 676 };
696 if (wlr_box_contains_point(&box, lx, ly)) { 677 if (wlr_box_contains_point(&box, lx, ly)) {
697 return container_at(floater, lx, ly, surface, sx, sy); 678 return tiling_container_at(floater, lx, ly,
679 surface, sx, sy);
698 } 680 }
699 } 681 }
700 } 682 }
@@ -702,6 +684,90 @@ struct sway_container *floating_container_at(double lx, double ly,
702 return NULL; 684 return NULL;
703} 685}
704 686
687static struct sway_container *tiling_container_at(
688 struct sway_container *con, double lx, double ly,
689 struct wlr_surface **surface, double *sx, double *sy) {
690 if (con->type == C_VIEW) {
691 return container_at_view(con, lx, ly, surface, sx, sy);
692 }
693 if (!con->children->length) {
694 return NULL;
695 }
696
697 switch (con->layout) {
698 case L_HORIZ:
699 case L_VERT:
700 return container_at_linear(con, lx, ly, surface, sx, sy);
701 case L_TABBED:
702 return container_at_tabbed(con, lx, ly, surface, sx, sy);
703 case L_STACKED:
704 return container_at_stacked(con, lx, ly, surface, sx, sy);
705 case L_FLOATING:
706 sway_assert(false, "Didn't expect to see floating here");
707 return NULL;
708 case L_NONE:
709 return NULL;
710 }
711 return NULL;
712}
713
714static bool surface_is_popup(struct wlr_surface *surface) {
715 if (wlr_surface_is_xdg_surface(surface)) {
716 struct wlr_xdg_surface *xdg_surface =
717 wlr_xdg_surface_from_wlr_surface(surface);
718 while (xdg_surface) {
719 if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
720 return true;
721 }
722 xdg_surface = xdg_surface->toplevel->parent;
723 }
724 return false;
725 }
726
727 if (wlr_surface_is_xdg_surface_v6(surface)) {
728 struct wlr_xdg_surface_v6 *xdg_surface_v6 =
729 wlr_xdg_surface_v6_from_wlr_surface(surface);
730 while (xdg_surface_v6) {
731 if (xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
732 return true;
733 }
734 xdg_surface_v6 = xdg_surface_v6->toplevel->parent;
735 }
736 return false;
737 }
738
739 return false;
740}
741
742struct sway_container *container_at(struct sway_container *workspace,
743 double lx, double ly,
744 struct wlr_surface **surface, double *sx, double *sy) {
745 if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
746 return NULL;
747 }
748 struct sway_container *c;
749 // Focused view's popups
750 struct sway_seat *seat = input_manager_current_seat(input_manager);
751 struct sway_container *focus =
752 seat_get_focus_inactive(seat, &root_container);
753 if (focus && focus->type == C_VIEW) {
754 container_at_view(focus, lx, ly, surface, sx, sy);
755 if (*surface && surface_is_popup(*surface)) {
756 return focus;
757 }
758 *surface = NULL;
759 }
760 // Floating
761 if ((c = floating_container_at(lx, ly, surface, sx, sy))) {
762 return c;
763 }
764 // Tiling
765 if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
766 return c;
767 }
768 return NULL;
769}
770
705void container_for_each_descendant_dfs(struct sway_container *container, 771void container_for_each_descendant_dfs(struct sway_container *container,
706 void (*f)(struct sway_container *container, void *data), 772 void (*f)(struct sway_container *container, void *data),
707 void *data) { 773 void *data) {