summaryrefslogtreecommitdiffstats
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c148
-rw-r--r--sway/tree/layout.c14
-rw-r--r--sway/tree/output.c2
-rw-r--r--sway/tree/view.c31
4 files changed, 145 insertions, 50 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) {
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index a0764a54..1f82e534 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -217,7 +217,9 @@ void container_move_to(struct sway_container *container,
217 container_sort_workspaces(new_parent); 217 container_sort_workspaces(new_parent);
218 seat_set_focus(seat, new_parent); 218 seat_set_focus(seat, new_parent);
219 workspace_output_raise_priority(container, old_parent, new_parent); 219 workspace_output_raise_priority(container, old_parent, new_parent);
220 ipc_event_workspace(container, NULL, "move"); 220 ipc_event_workspace(NULL, container, "move");
221 } else if (container->type == C_VIEW) {
222 ipc_event_window(container, "move");
221 } 223 }
222 container_notify_subtree_changed(old_parent); 224 container_notify_subtree_changed(old_parent);
223 container_notify_subtree_changed(new_parent); 225 container_notify_subtree_changed(new_parent);
@@ -578,6 +580,10 @@ void container_move(struct sway_container *container,
578 container_notify_subtree_changed(old_parent); 580 container_notify_subtree_changed(old_parent);
579 container_notify_subtree_changed(container->parent); 581 container_notify_subtree_changed(container->parent);
580 582
583 if (container->type == C_VIEW) {
584 ipc_event_window(container, "move");
585 }
586
581 if (old_parent) { 587 if (old_parent) {
582 seat_set_focus(config->handler_context.seat, old_parent); 588 seat_set_focus(config->handler_context.seat, old_parent);
583 seat_set_focus(config->handler_context.seat, container); 589 seat_set_focus(config->handler_context.seat, container);
@@ -592,7 +598,7 @@ void container_move(struct sway_container *container,
592 next_ws = container_parent(next_ws, C_WORKSPACE); 598 next_ws = container_parent(next_ws, C_WORKSPACE);
593 } 599 }
594 if (last_ws && next_ws && last_ws != next_ws) { 600 if (last_ws && next_ws && last_ws != next_ws) {
595 ipc_event_workspace(last_ws, container, "focus"); 601 ipc_event_workspace(last_ws, next_ws, "focus");
596 workspace_detect_urgent(last_ws); 602 workspace_detect_urgent(last_ws);
597 workspace_detect_urgent(next_ws); 603 workspace_detect_urgent(next_ws);
598 } 604 }
@@ -995,13 +1001,13 @@ static void swap_focus(struct sway_container *con1,
995 if (focus == con1 && (con2->parent->layout == L_TABBED 1001 if (focus == con1 && (con2->parent->layout == L_TABBED
996 || con2->parent->layout == L_STACKED)) { 1002 || con2->parent->layout == L_STACKED)) {
997 if (workspace_is_visible(ws2)) { 1003 if (workspace_is_visible(ws2)) {
998 seat_set_focus_warp(seat, con2, false); 1004 seat_set_focus_warp(seat, con2, false, true);
999 } 1005 }
1000 seat_set_focus(seat, ws1 != ws2 ? con2 : con1); 1006 seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
1001 } else if (focus == con2 && (con1->parent->layout == L_TABBED 1007 } else if (focus == con2 && (con1->parent->layout == L_TABBED
1002 || con1->parent->layout == L_STACKED)) { 1008 || con1->parent->layout == L_STACKED)) {
1003 if (workspace_is_visible(ws1)) { 1009 if (workspace_is_visible(ws1)) {
1004 seat_set_focus_warp(seat, con1, false); 1010 seat_set_focus_warp(seat, con1, false, true);
1005 } 1011 }
1006 seat_set_focus(seat, ws1 != ws2 ? con1 : con2); 1012 seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
1007 } else if (ws1 != ws2) { 1013 } else if (ws1 != ws2) {
diff --git a/sway/tree/output.c b/sway/tree/output.c
index da535c18..31e3bf9b 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -22,7 +22,7 @@ static void restore_workspaces(struct sway_container *output) {
22 if (highest == output) { 22 if (highest == output) {
23 container_remove_child(ws); 23 container_remove_child(ws);
24 container_add_child(output, ws); 24 container_add_child(output, ws);
25 ipc_event_workspace(ws, NULL, "move"); 25 ipc_event_workspace(NULL, ws, "move");
26 j--; 26 j--;
27 } 27 }
28 } 28 }
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 0dbd3812..051b93ce 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -303,6 +303,12 @@ void view_close(struct sway_view *view) {
303 } 303 }
304} 304}
305 305
306void view_close_popups(struct sway_view *view) {
307 if (view->impl->close_popups) {
308 view->impl->close_popups(view);
309 }
310}
311
306void view_damage_from(struct sway_view *view) { 312void view_damage_from(struct sway_view *view) {
307 for (int i = 0; i < root_container.children->length; ++i) { 313 for (int i = 0; i < root_container.children->length; ++i) {
308 struct sway_container *cont = root_container.children->items[i]; 314 struct sway_container *cont = root_container.children->items[i];
@@ -333,6 +339,16 @@ void view_for_each_surface(struct sway_view *view,
333 } 339 }
334} 340}
335 341
342void view_for_each_popup(struct sway_view *view,
343 wlr_surface_iterator_func_t iterator, void *user_data) {
344 if (!view->surface) {
345 return;
346 }
347 if (view->impl->for_each_popup) {
348 view->impl->for_each_popup(view, iterator, user_data);
349 }
350}
351
336static void view_subsurface_create(struct sway_view *view, 352static void view_subsurface_create(struct sway_view *view,
337 struct wlr_subsurface *subsurface); 353 struct wlr_subsurface *subsurface);
338 354
@@ -865,6 +881,8 @@ void view_update_title(struct sway_view *view, bool force) {
865 881
866 // Update title after the global font height is updated 882 // Update title after the global font height is updated
867 container_update_title_textures(view->swayc); 883 container_update_title_textures(view->swayc);
884
885 ipc_event_window(view->swayc, "title");
868} 886}
869 887
870static bool find_by_mark_iterator(struct sway_container *con, 888static bool find_by_mark_iterator(struct sway_container *con,
@@ -887,6 +905,7 @@ bool view_find_and_unmark(char *mark) {
887 free(view_mark); 905 free(view_mark);
888 list_del(view->marks, i); 906 list_del(view->marks, i);
889 view_update_marks_textures(view); 907 view_update_marks_textures(view);
908 ipc_event_window(container, "mark");
890 return true; 909 return true;
891 } 910 }
892 } 911 }
@@ -894,11 +913,10 @@ bool view_find_and_unmark(char *mark) {
894} 913}
895 914
896void view_clear_marks(struct sway_view *view) { 915void view_clear_marks(struct sway_view *view) {
897 for (int i = 0; i < view->marks->length; ++i) { 916 while (view->marks->length) {
898 free(view->marks->items[i]); 917 list_del(view->marks, 0);
918 ipc_event_window(view->swayc, "mark");
899 } 919 }
900 list_free(view->marks);
901 view->marks = create_list();
902} 920}
903 921
904bool view_has_mark(struct sway_view *view, char *mark) { 922bool view_has_mark(struct sway_view *view, char *mark) {
@@ -911,6 +929,11 @@ bool view_has_mark(struct sway_view *view, char *mark) {
911 return false; 929 return false;
912} 930}
913 931
932void view_add_mark(struct sway_view *view, char *mark) {
933 list_add(view->marks, strdup(mark));
934 ipc_event_window(view->swayc, "mark");
935}
936
914static void update_marks_texture(struct sway_view *view, 937static void update_marks_texture(struct sway_view *view,
915 struct wlr_texture **texture, struct border_colors *class) { 938 struct wlr_texture **texture, struct border_colors *class) {
916 struct sway_container *output = container_parent(view->swayc, C_OUTPUT); 939 struct sway_container *output = container_parent(view->swayc, C_OUTPUT);