diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-05-24 22:30:44 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-01 23:14:58 +1000 |
commit | 1f2e399ade77070a2d0b82856ad9a3eef96b8676 (patch) | |
tree | c469197e140051aea912cb173723c7e55ce1e410 /sway/tree/container.c | |
parent | Send frame done to floating views (diff) | |
download | sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.tar.gz sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.tar.zst sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.zip |
Implement floating
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 133 |
1 files changed, 122 insertions, 11 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index 33d88d7f..f9a0474c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -123,6 +123,7 @@ struct sway_container *container_create(enum sway_container_type type) { | |||
123 | c->layout = L_NONE; | 123 | c->layout = L_NONE; |
124 | c->type = type; | 124 | c->type = type; |
125 | c->alpha = 1.0f; | 125 | c->alpha = 1.0f; |
126 | c->reapable = true; | ||
126 | 127 | ||
127 | if (type != C_VIEW) { | 128 | if (type != C_VIEW) { |
128 | c->children = create_list(); | 129 | c->children = create_list(); |
@@ -189,14 +190,13 @@ static struct sway_container *container_workspace_destroy( | |||
189 | } | 190 | } |
190 | 191 | ||
191 | struct sway_container *parent = workspace->parent; | 192 | struct sway_container *parent = workspace->parent; |
192 | if (workspace->children->length == 0) { | 193 | if (workspace_is_empty(workspace)) { |
193 | // destroy the WS if there are no children (TODO check for floating) | 194 | // destroy the WS if there are no children |
194 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | 195 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); |
195 | ipc_event_workspace(workspace, NULL, "empty"); | 196 | ipc_event_workspace(workspace, NULL, "empty"); |
196 | } else if (output) { | 197 | } else if (output) { |
197 | // Move children to a different workspace on this output | 198 | // Move children to a different workspace on this output |
198 | struct sway_container *new_workspace = NULL; | 199 | struct sway_container *new_workspace = NULL; |
199 | // TODO move floating | ||
200 | for (int i = 0; i < output->children->length; i++) { | 200 | for (int i = 0; i < output->children->length; i++) { |
201 | if (output->children->items[i] != workspace) { | 201 | if (output->children->items[i] != workspace) { |
202 | new_workspace = output->children->items[i]; | 202 | new_workspace = output->children->items[i]; |
@@ -209,6 +209,11 @@ static struct sway_container *container_workspace_destroy( | |||
209 | for (int i = 0; i < workspace->children->length; i++) { | 209 | for (int i = 0; i < workspace->children->length; i++) { |
210 | container_move_to(workspace->children->items[i], new_workspace); | 210 | container_move_to(workspace->children->items[i], new_workspace); |
211 | } | 211 | } |
212 | struct sway_container *floating = workspace->sway_workspace->floating; | ||
213 | for (int i = 0; i < floating->children->length; i++) { | ||
214 | container_move_to(floating->children->items[i], | ||
215 | new_workspace->sway_workspace->floating); | ||
216 | } | ||
212 | } | 217 | } |
213 | 218 | ||
214 | free(workspace->sway_workspace); | 219 | free(workspace->sway_workspace); |
@@ -275,13 +280,16 @@ static void container_root_finish(struct sway_container *con) { | |||
275 | } | 280 | } |
276 | 281 | ||
277 | bool container_reap_empty(struct sway_container *con) { | 282 | bool container_reap_empty(struct sway_container *con) { |
283 | if (!con->reapable) { | ||
284 | return false; | ||
285 | } | ||
278 | switch (con->type) { | 286 | switch (con->type) { |
279 | case C_ROOT: | 287 | case C_ROOT: |
280 | case C_OUTPUT: | 288 | case C_OUTPUT: |
281 | // dont reap these | 289 | // dont reap these |
282 | break; | 290 | break; |
283 | case C_WORKSPACE: | 291 | case C_WORKSPACE: |
284 | if (!workspace_is_visible(con) && con->children->length == 0) { | 292 | if (!workspace_is_visible(con) && workspace_is_empty(con)) { |
285 | wlr_log(L_DEBUG, "Destroying workspace via reaper"); | 293 | wlr_log(L_DEBUG, "Destroying workspace via reaper"); |
286 | container_workspace_destroy(con); | 294 | container_workspace_destroy(con); |
287 | return true; | 295 | return true; |
@@ -436,7 +444,6 @@ struct sway_container *container_find(struct sway_container *container, | |||
436 | if (!container->children) { | 444 | if (!container->children) { |
437 | return NULL; | 445 | return NULL; |
438 | } | 446 | } |
439 | // TODO: floating windows | ||
440 | for (int i = 0; i < container->children->length; ++i) { | 447 | for (int i = 0; i < container->children->length; ++i) { |
441 | struct sway_container *child = container->children->items[i]; | 448 | struct sway_container *child = container->children->items[i]; |
442 | if (test(child, data)) { | 449 | if (test(child, data)) { |
@@ -448,6 +455,9 @@ struct sway_container *container_find(struct sway_container *container, | |||
448 | } | 455 | } |
449 | } | 456 | } |
450 | } | 457 | } |
458 | if (container->type == C_WORKSPACE) { | ||
459 | return container_find(container->sway_workspace->floating, test, data); | ||
460 | } | ||
451 | return NULL; | 461 | return NULL; |
452 | } | 462 | } |
453 | 463 | ||
@@ -608,8 +618,6 @@ struct sway_container *container_at(struct sway_container *parent, | |||
608 | return container_at_tabbed(parent, ox, oy, surface, sx, sy); | 618 | return container_at_tabbed(parent, ox, oy, surface, sx, sy); |
609 | case L_STACKED: | 619 | case L_STACKED: |
610 | return container_at_stacked(parent, ox, oy, surface, sx, sy); | 620 | return container_at_stacked(parent, ox, oy, surface, sx, sy); |
611 | case L_FLOATING: | ||
612 | return NULL; // TODO | ||
613 | case L_NONE: | 621 | case L_NONE: |
614 | return NULL; | 622 | return NULL; |
615 | } | 623 | } |
@@ -617,6 +625,34 @@ struct sway_container *container_at(struct sway_container *parent, | |||
617 | return NULL; | 625 | return NULL; |
618 | } | 626 | } |
619 | 627 | ||
628 | struct sway_container *floating_container_at(double lx, double ly, | ||
629 | struct wlr_surface **surface, double *sx, double *sy) { | ||
630 | for (int i = 0; i < root_container.children->length; ++i) { | ||
631 | struct sway_container *output = root_container.children->items[i]; | ||
632 | for (int j = 0; j < output->children->length; ++j) { | ||
633 | struct sway_container *workspace = output->children->items[j]; | ||
634 | struct sway_workspace *ws = workspace->sway_workspace; | ||
635 | bool ws_is_visible = workspace_is_visible(workspace); | ||
636 | for (int k = 0; k < ws->floating->children->length; ++k) { | ||
637 | struct sway_container *floater = | ||
638 | ws->floating->children->items[k]; | ||
639 | if (ws_is_visible || floater->is_sticky) { | ||
640 | struct wlr_box box = { | ||
641 | .x = floater->x, | ||
642 | .y = floater->y, | ||
643 | .width = floater->width, | ||
644 | .height = floater->height, | ||
645 | }; | ||
646 | if (wlr_box_contains_point(&box, lx, ly)) { | ||
647 | return container_at(floater, lx, ly, surface, sx, sy); | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | return NULL; | ||
654 | } | ||
655 | |||
620 | void container_for_each_descendant_dfs(struct sway_container *container, | 656 | void container_for_each_descendant_dfs(struct sway_container *container, |
621 | void (*f)(struct sway_container *container, void *data), | 657 | void (*f)(struct sway_container *container, void *data), |
622 | void *data) { | 658 | void *data) { |
@@ -674,7 +710,7 @@ static bool find_child_func(struct sway_container *con, void *data) { | |||
674 | 710 | ||
675 | bool container_has_child(struct sway_container *con, | 711 | bool container_has_child(struct sway_container *con, |
676 | struct sway_container *child) { | 712 | struct sway_container *child) { |
677 | if (con == NULL || con->type == C_VIEW || con->children->length == 0) { | 713 | if (con == NULL || con->type == C_VIEW) { |
678 | return false; | 714 | return false; |
679 | } | 715 | } |
680 | return container_find(con, find_child_func, child); | 716 | return container_find(con, find_child_func, child); |
@@ -806,9 +842,6 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe | |||
806 | case L_STACKED: | 842 | case L_STACKED: |
807 | lenient_strcat(buffer, "S["); | 843 | lenient_strcat(buffer, "S["); |
808 | break; | 844 | break; |
809 | case L_FLOATING: | ||
810 | lenient_strcat(buffer, "F["); | ||
811 | break; | ||
812 | case L_NONE: | 845 | case L_NONE: |
813 | lenient_strcat(buffer, "D["); | 846 | lenient_strcat(buffer, "D["); |
814 | break; | 847 | break; |
@@ -866,3 +899,81 @@ void container_notify_subtree_changed(struct sway_container *container) { | |||
866 | size_t container_titlebar_height() { | 899 | size_t container_titlebar_height() { |
867 | return config->font_height + TITLEBAR_V_PADDING * 2; | 900 | return config->font_height + TITLEBAR_V_PADDING * 2; |
868 | } | 901 | } |
902 | |||
903 | static void configure_floating_view(struct sway_view *view) { | ||
904 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | ||
905 | int max_width = ws->width * 0.6666; | ||
906 | int max_height = ws->height * 0.6666; | ||
907 | int width = | ||
908 | view->natural_width > max_width ? max_width : view->natural_width; | ||
909 | int height = | ||
910 | view->natural_height > max_height ? max_height : view->natural_height; | ||
911 | struct sway_container *output = ws->parent; | ||
912 | int lx = output->x + (ws->width - width) / 2; | ||
913 | int ly = output->y + (ws->height - height) / 2; | ||
914 | |||
915 | view->border_left = view->border_right = view->border_bottom = true; | ||
916 | view_set_maximized(view, false); | ||
917 | view_configure(view, lx, ly, width, height); | ||
918 | } | ||
919 | |||
920 | void container_set_floating(struct sway_container *container, bool enable) { | ||
921 | if (container->is_floating == enable) { | ||
922 | return; | ||
923 | } | ||
924 | |||
925 | struct sway_container *workspace = container_parent(container, C_WORKSPACE); | ||
926 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
927 | container_damage_whole(container); | ||
928 | |||
929 | if (enable) { | ||
930 | container_remove_child(container); | ||
931 | container_add_child(workspace->sway_workspace->floating, container); | ||
932 | container->is_floating = true; | ||
933 | if (container->type == C_VIEW) { | ||
934 | configure_floating_view(container->sway_view); | ||
935 | } | ||
936 | seat_set_focus(seat, seat_get_focus_inactive(seat, container)); | ||
937 | container_reap_empty_recursive(workspace); | ||
938 | } else { | ||
939 | // Returning to tiled | ||
940 | container_remove_child(container); | ||
941 | container_add_child(workspace, container); | ||
942 | container->width = container->parent->width; | ||
943 | container->height = container->parent->height; | ||
944 | if (container->type == C_VIEW) { | ||
945 | view_set_maximized(container->sway_view, true); | ||
946 | } | ||
947 | container->is_floating = false; | ||
948 | container->is_sticky = false; | ||
949 | container_reap_empty_recursive(workspace->sway_workspace->floating); | ||
950 | } | ||
951 | arrange_workspace(workspace); | ||
952 | container_damage_whole(container); | ||
953 | } | ||
954 | |||
955 | void container_set_geometry_from_view(struct sway_container *container) { | ||
956 | if (!sway_assert(container->type == C_VIEW, "Expected a view")) { | ||
957 | return; | ||
958 | } | ||
959 | if (!sway_assert(container->is_floating, "Expected a floating view")) { | ||
960 | return; | ||
961 | } | ||
962 | struct sway_view *view = container->sway_view; | ||
963 | size_t border_width = view->border_thickness * (view->border != B_NONE); | ||
964 | size_t top = | ||
965 | view->border == B_NORMAL ? container_titlebar_height() : border_width; | ||
966 | |||
967 | container->x = view->x - border_width; | ||
968 | container->y = view->y - top; | ||
969 | container->width = view->width + border_width * 2; | ||
970 | container->height = top + view->height + border_width; | ||
971 | } | ||
972 | |||
973 | bool container_self_or_parent_floating(struct sway_container *container) { | ||
974 | while (container->parent->type != C_WORKSPACE | ||
975 | && container->parent->parent->type != C_WORKSPACE) { | ||
976 | container = container->parent; | ||
977 | } | ||
978 | return container->is_floating; | ||
979 | } | ||