diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/arrange.c | 12 | ||||
-rw-r--r-- | sway/tree/container.c | 133 | ||||
-rw-r--r-- | sway/tree/layout.c | 73 | ||||
-rw-r--r-- | sway/tree/view.c | 87 | ||||
-rw-r--r-- | sway/tree/workspace.c | 17 |
5 files changed, 229 insertions, 93 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index bdef56ea..da4f7889 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c | |||
@@ -247,6 +247,18 @@ void arrange_children_of(struct sway_container *parent) { | |||
247 | arrange_children_of(child); | 247 | arrange_children_of(child); |
248 | } | 248 | } |
249 | } | 249 | } |
250 | |||
251 | // If container is a workspace, process floating containers too | ||
252 | if (parent->type == C_WORKSPACE) { | ||
253 | struct sway_workspace *ws = workspace->sway_workspace; | ||
254 | for (int i = 0; i < ws->floating->children->length; ++i) { | ||
255 | struct sway_container *child = ws->floating->children->items[i]; | ||
256 | if (child->type != C_VIEW) { | ||
257 | arrange_children_of(child); | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | |||
250 | container_damage_whole(parent); | 262 | container_damage_whole(parent); |
251 | update_debug_tree(); | 263 | update_debug_tree(); |
252 | } | 264 | } |
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 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 7bbeb4b1..59ad0b53 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -45,20 +45,14 @@ void layout_init(void) { | |||
45 | } | 45 | } |
46 | 46 | ||
47 | static int index_child(const struct sway_container *child) { | 47 | static int index_child(const struct sway_container *child) { |
48 | // TODO handle floating | ||
49 | struct sway_container *parent = child->parent; | 48 | struct sway_container *parent = child->parent; |
50 | int i, len; | 49 | for (int i = 0; i < parent->children->length; ++i) { |
51 | len = parent->children->length; | ||
52 | for (i = 0; i < len; ++i) { | ||
53 | if (parent->children->items[i] == child) { | 50 | if (parent->children->items[i] == child) { |
54 | break; | 51 | return i; |
55 | } | 52 | } |
56 | } | 53 | } |
57 | 54 | // This happens if the child is a floating container | |
58 | if (!sway_assert(i < len, "Stray container")) { | 55 | return -1; |
59 | return -1; | ||
60 | } | ||
61 | return i; | ||
62 | } | 56 | } |
63 | 57 | ||
64 | static void container_handle_fullscreen_reparent(struct sway_container *viewcon, | 58 | static void container_handle_fullscreen_reparent(struct sway_container *viewcon, |
@@ -142,26 +136,11 @@ struct sway_container *container_remove_child(struct sway_container *child) { | |||
142 | } | 136 | } |
143 | 137 | ||
144 | struct sway_container *parent = child->parent; | 138 | struct sway_container *parent = child->parent; |
145 | if (!child->is_floating) { | 139 | for (int i = 0; i < parent->children->length; ++i) { |
146 | for (int i = 0; i < parent->children->length; ++i) { | 140 | if (parent->children->items[i] == child) { |
147 | if (parent->children->items[i] == child) { | 141 | list_del(parent->children, i); |
148 | list_del(parent->children, i); | 142 | break; |
149 | break; | ||
150 | } | ||
151 | } | ||
152 | } else { | ||
153 | if (!sway_assert(parent->type == C_WORKSPACE && child->type == C_VIEW, | ||
154 | "Found floating non-view and/or in non-workspace")) { | ||
155 | return parent; | ||
156 | } | ||
157 | struct sway_workspace *ws = parent->sway_workspace; | ||
158 | for (int i = 0; i < ws->floating->length; ++i) { | ||
159 | if (ws->floating->items[i] == child) { | ||
160 | list_del(ws->floating, i); | ||
161 | break; | ||
162 | } | ||
163 | } | 143 | } |
164 | child->is_floating = false; | ||
165 | } | 144 | } |
166 | child->parent = NULL; | 145 | child->parent = NULL; |
167 | container_notify_subtree_changed(parent); | 146 | container_notify_subtree_changed(parent); |
@@ -169,32 +148,16 @@ struct sway_container *container_remove_child(struct sway_container *child) { | |||
169 | return parent; | 148 | return parent; |
170 | } | 149 | } |
171 | 150 | ||
172 | void container_add_floating(struct sway_container *workspace, | ||
173 | struct sway_container *child) { | ||
174 | if (!sway_assert(workspace->type == C_WORKSPACE && child->type == C_VIEW, | ||
175 | "Attempted to float non-view and/or in non-workspace")) { | ||
176 | return; | ||
177 | } | ||
178 | if (!sway_assert(!child->parent, | ||
179 | "child already has a parent (invalid call)")) { | ||
180 | return; | ||
181 | } | ||
182 | if (!sway_assert(!child->is_floating, | ||
183 | "child is already floating (invalid state)")) { | ||
184 | return; | ||
185 | } | ||
186 | struct sway_workspace *ws = workspace->sway_workspace; | ||
187 | list_add(ws->floating, child); | ||
188 | child->parent = workspace; | ||
189 | child->is_floating = true; | ||
190 | } | ||
191 | |||
192 | void container_move_to(struct sway_container *container, | 151 | void container_move_to(struct sway_container *container, |
193 | struct sway_container *destination) { | 152 | struct sway_container *destination) { |
194 | if (container == destination | 153 | if (container == destination |
195 | || container_has_ancestor(container, destination)) { | 154 | || container_has_ancestor(container, destination)) { |
196 | return; | 155 | return; |
197 | } | 156 | } |
157 | if (container->is_floating) { | ||
158 | // TODO | ||
159 | return; | ||
160 | } | ||
198 | struct sway_container *old_parent = container_remove_child(container); | 161 | struct sway_container *old_parent = container_remove_child(container); |
199 | container->width = container->height = 0; | 162 | container->width = container->height = 0; |
200 | container->saved_width = container->saved_height = 0; | 163 | container->saved_width = container->saved_height = 0; |
@@ -207,8 +170,9 @@ void container_move_to(struct sway_container *container, | |||
207 | } | 170 | } |
208 | wl_signal_emit(&container->events.reparent, old_parent); | 171 | wl_signal_emit(&container->events.reparent, old_parent); |
209 | if (container->type == C_WORKSPACE) { | 172 | if (container->type == C_WORKSPACE) { |
210 | struct sway_seat *seat = input_manager_get_default_seat( | 173 | // If moving a workspace to a new output, maybe create a new workspace |
211 | input_manager); | 174 | // on the previous output |
175 | struct sway_seat *seat = input_manager_get_default_seat(input_manager); | ||
212 | if (old_parent->children->length == 0) { | 176 | if (old_parent->children->length == 0) { |
213 | char *ws_name = workspace_next_name(old_parent->name); | 177 | char *ws_name = workspace_next_name(old_parent->name); |
214 | struct sway_container *ws = | 178 | struct sway_container *ws = |
@@ -754,6 +718,10 @@ struct sway_container *container_get_in_direction( | |||
754 | enum movement_direction dir) { | 718 | enum movement_direction dir) { |
755 | struct sway_container *parent = container->parent; | 719 | struct sway_container *parent = container->parent; |
756 | 720 | ||
721 | if (container->is_floating) { | ||
722 | return NULL; | ||
723 | } | ||
724 | |||
757 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { | 725 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { |
758 | if (dir == MOVE_PARENT || dir == MOVE_CHILD) { | 726 | if (dir == MOVE_PARENT || dir == MOVE_CHILD) { |
759 | return NULL; | 727 | return NULL; |
@@ -778,6 +746,9 @@ struct sway_container *container_get_in_direction( | |||
778 | bool can_move = false; | 746 | bool can_move = false; |
779 | int desired; | 747 | int desired; |
780 | int idx = index_child(container); | 748 | int idx = index_child(container); |
749 | if (idx == -1) { | ||
750 | return NULL; | ||
751 | } | ||
781 | if (parent->type == C_ROOT) { | 752 | if (parent->type == C_ROOT) { |
782 | enum wlr_direction wlr_dir = 0; | 753 | enum wlr_direction wlr_dir = 0; |
783 | if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir), | 754 | if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir), |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 26ff1e8d..651a2be6 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -158,21 +158,19 @@ void view_autoconfigure(struct sway_view *view) { | |||
158 | 158 | ||
159 | view->border_top = view->border_bottom = true; | 159 | view->border_top = view->border_bottom = true; |
160 | view->border_left = view->border_right = true; | 160 | view->border_left = view->border_right = true; |
161 | if (view->swayc->layout != L_FLOATING) { | 161 | if (config->hide_edge_borders == E_BOTH |
162 | if (config->hide_edge_borders == E_BOTH | 162 | || config->hide_edge_borders == E_VERTICAL |
163 | || config->hide_edge_borders == E_VERTICAL | 163 | || (config->hide_edge_borders == E_SMART && !other_views)) { |
164 | || (config->hide_edge_borders == E_SMART && !other_views)) { | 164 | view->border_left = view->swayc->x != ws->x; |
165 | view->border_left = view->swayc->x != ws->x; | 165 | int right_x = view->swayc->x + view->swayc->width; |
166 | int right_x = view->swayc->x + view->swayc->width; | 166 | view->border_right = right_x != ws->x + ws->width; |
167 | view->border_right = right_x != ws->x + ws->width; | 167 | } |
168 | } | 168 | if (config->hide_edge_borders == E_BOTH |
169 | if (config->hide_edge_borders == E_BOTH | 169 | || config->hide_edge_borders == E_HORIZONTAL |
170 | || config->hide_edge_borders == E_HORIZONTAL | 170 | || (config->hide_edge_borders == E_SMART && !other_views)) { |
171 | || (config->hide_edge_borders == E_SMART && !other_views)) { | 171 | view->border_top = view->swayc->y != ws->y; |
172 | view->border_top = view->swayc->y != ws->y; | 172 | int bottom_y = view->swayc->y + view->swayc->height; |
173 | int bottom_y = view->swayc->y + view->swayc->height; | 173 | view->border_bottom = bottom_y != ws->y + ws->height; |
174 | view->border_bottom = bottom_y != ws->y + ws->height; | ||
175 | } | ||
176 | } | 174 | } |
177 | 175 | ||
178 | double x, y, width, height; | 176 | double x, y, width, height; |
@@ -184,11 +182,11 @@ void view_autoconfigure(struct sway_view *view) { | |||
184 | // disable any top border because we'll always have the title bar. | 182 | // disable any top border because we'll always have the title bar. |
185 | if (view->swayc->parent->layout == L_TABBED) { | 183 | if (view->swayc->parent->layout == L_TABBED) { |
186 | y_offset = container_titlebar_height(); | 184 | y_offset = container_titlebar_height(); |
187 | view->border_top = 0; | 185 | view->border_top = false; |
188 | } else if (view->swayc->parent->layout == L_STACKED) { | 186 | } else if (view->swayc->parent->layout == L_STACKED) { |
189 | y_offset = container_titlebar_height() | 187 | y_offset = container_titlebar_height() |
190 | * view->swayc->parent->children->length; | 188 | * view->swayc->parent->children->length; |
191 | view->border_top = 0; | 189 | view->border_top = false; |
192 | } | 190 | } |
193 | 191 | ||
194 | switch (view->border) { | 192 | switch (view->border) { |
@@ -237,6 +235,12 @@ void view_set_activated(struct sway_view *view, bool activated) { | |||
237 | } | 235 | } |
238 | } | 236 | } |
239 | 237 | ||
238 | void view_set_maximized(struct sway_view *view, bool maximized) { | ||
239 | if (view->impl->set_maximized) { | ||
240 | view->impl->set_maximized(view, maximized); | ||
241 | } | ||
242 | } | ||
243 | |||
240 | // Set fullscreen, but without IPC events or arranging windows. | 244 | // Set fullscreen, but without IPC events or arranging windows. |
241 | void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) { | 245 | void view_set_fullscreen_raw(struct sway_view *view, bool fullscreen) { |
242 | if (view->is_fullscreen == fullscreen) { | 246 | if (view->is_fullscreen == fullscreen) { |
@@ -452,6 +456,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
452 | // TODO: CT_ASSIGN_OUTPUT | 456 | // TODO: CT_ASSIGN_OUTPUT |
453 | } | 457 | } |
454 | } | 458 | } |
459 | // If we're about to launch the view into the floating container, then | ||
460 | // launch it as a tiled view in the root of the workspace instead. | ||
461 | if (focus->is_floating) { | ||
462 | focus = focus->parent->parent; | ||
463 | } | ||
455 | free(criterias); | 464 | free(criterias); |
456 | cont = container_view_create(focus, view); | 465 | cont = container_view_create(focus, view); |
457 | 466 | ||
@@ -468,7 +477,12 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
468 | wl_signal_add(&view->swayc->events.reparent, &view->container_reparent); | 477 | wl_signal_add(&view->swayc->events.reparent, &view->container_reparent); |
469 | view->container_reparent.notify = view_handle_container_reparent; | 478 | view->container_reparent.notify = view_handle_container_reparent; |
470 | 479 | ||
471 | arrange_children_of(cont->parent); | 480 | if (view->impl->wants_floating && view->impl->wants_floating(view)) { |
481 | container_set_floating(view->swayc, true); | ||
482 | } else { | ||
483 | arrange_children_of(cont->parent); | ||
484 | } | ||
485 | |||
472 | input_manager_set_focus(input_manager, cont); | 486 | input_manager_set_focus(input_manager, cont); |
473 | if (workspace) { | 487 | if (workspace) { |
474 | workspace_switch(workspace); | 488 | workspace_switch(workspace); |
@@ -516,16 +530,14 @@ void view_unmap(struct sway_view *view) { | |||
516 | } | 530 | } |
517 | } | 531 | } |
518 | 532 | ||
519 | void view_update_position(struct sway_view *view, double ox, double oy) { | 533 | void view_update_position(struct sway_view *view, double lx, double ly) { |
520 | if (view->swayc->x == ox && view->swayc->y == oy) { | 534 | if (!view->swayc->is_floating) { |
521 | return; | 535 | return; |
522 | } | 536 | } |
523 | |||
524 | // TODO: Only allow this if the view is floating (this function will only be | ||
525 | // called in response to wayland clients wanting to reposition themselves). | ||
526 | container_damage_whole(view->swayc); | 537 | container_damage_whole(view->swayc); |
527 | view->swayc->x = ox; | 538 | view->x = lx; |
528 | view->swayc->y = oy; | 539 | view->y = ly; |
540 | container_set_geometry_from_view(view->swayc); | ||
529 | container_damage_whole(view->swayc); | 541 | container_damage_whole(view->swayc); |
530 | } | 542 | } |
531 | 543 | ||
@@ -533,15 +545,15 @@ void view_update_size(struct sway_view *view, int width, int height) { | |||
533 | if (view->width == width && view->height == height) { | 545 | if (view->width == width && view->height == height) { |
534 | return; | 546 | return; |
535 | } | 547 | } |
536 | |||
537 | container_damage_whole(view->swayc); | 548 | container_damage_whole(view->swayc); |
538 | // Should we update the swayc width/height here too? | ||
539 | view->width = width; | 549 | view->width = width; |
540 | view->height = height; | 550 | view->height = height; |
551 | if (view->swayc->is_floating) { | ||
552 | container_set_geometry_from_view(view->swayc); | ||
553 | } | ||
541 | container_damage_whole(view->swayc); | 554 | container_damage_whole(view->swayc); |
542 | } | 555 | } |
543 | 556 | ||
544 | |||
545 | static void view_subsurface_create(struct sway_view *view, | 557 | static void view_subsurface_create(struct sway_view *view, |
546 | struct wlr_subsurface *subsurface) { | 558 | struct wlr_subsurface *subsurface) { |
547 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); | 559 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); |
@@ -888,6 +900,19 @@ bool view_is_visible(struct sway_view *view) { | |||
888 | if (!view->swayc) { | 900 | if (!view->swayc) { |
889 | return false; | 901 | return false; |
890 | } | 902 | } |
903 | struct sway_container *workspace = | ||
904 | container_parent(view->swayc, C_WORKSPACE); | ||
905 | // Determine if view is nested inside a floating container which is sticky. | ||
906 | // A simple floating view will have this ancestry: | ||
907 | // C_VIEW (is_floating=true) -> floating -> workspace | ||
908 | // A more complex ancestry could be: | ||
909 | // C_VIEW -> C_CONTAINER (tabbed and is_floating) -> floating -> workspace | ||
910 | struct sway_container *floater = view->swayc; | ||
911 | while (floater->parent->type != C_WORKSPACE | ||
912 | && floater->parent->parent->type != C_WORKSPACE) { | ||
913 | floater = floater->parent; | ||
914 | } | ||
915 | bool is_sticky = floater->is_floating && floater->is_sticky; | ||
891 | // Check view isn't in a tabbed or stacked container on an inactive tab | 916 | // Check view isn't in a tabbed or stacked container on an inactive tab |
892 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 917 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
893 | struct sway_container *container = view->swayc; | 918 | struct sway_container *container = view->swayc; |
@@ -901,10 +926,12 @@ bool view_is_visible(struct sway_view *view) { | |||
901 | container = container->parent; | 926 | container = container->parent; |
902 | } | 927 | } |
903 | // Check view isn't hidden by another fullscreen view | 928 | // Check view isn't hidden by another fullscreen view |
904 | struct sway_container *workspace = container; | ||
905 | if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { | 929 | if (workspace->sway_workspace->fullscreen && !view->is_fullscreen) { |
906 | return false; | 930 | return false; |
907 | } | 931 | } |
908 | // Check the workspace is visible | 932 | // Check the workspace is visible |
909 | return workspace_is_visible(workspace); | 933 | if (!is_sticky) { |
934 | return workspace_is_visible(workspace); | ||
935 | } | ||
936 | return true; | ||
910 | } | 937 | } |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c4f8ac5e..5bef409a 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -65,7 +65,9 @@ struct sway_container *workspace_create(struct sway_container *output, | |||
65 | return NULL; | 65 | return NULL; |
66 | } | 66 | } |
67 | swayws->swayc = workspace; | 67 | swayws->swayc = workspace; |
68 | swayws->floating = create_list(); | 68 | swayws->floating = container_create(C_CONTAINER); |
69 | swayws->floating->parent = swayws->swayc; | ||
70 | swayws->floating->reapable = false; | ||
69 | workspace->sway_workspace = swayws; | 71 | workspace->sway_workspace = swayws; |
70 | 72 | ||
71 | container_add_child(output, workspace); | 73 | container_add_child(output, workspace); |
@@ -408,3 +410,16 @@ bool workspace_is_visible(struct sway_container *ws) { | |||
408 | } | 410 | } |
409 | return focus == ws; | 411 | return focus == ws; |
410 | } | 412 | } |
413 | |||
414 | bool workspace_is_empty(struct sway_container *ws) { | ||
415 | if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) { | ||
416 | return false; | ||
417 | } | ||
418 | if (ws->children->length) { | ||
419 | return false; | ||
420 | } | ||
421 | if (ws->sway_workspace->floating->children->length) { | ||
422 | return false; | ||
423 | } | ||
424 | return true; | ||
425 | } | ||