diff options
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r-- | sway/tree/layout.c | 116 |
1 files changed, 93 insertions, 23 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 0b637822..7ffc2484 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -82,6 +82,37 @@ static int index_child(const struct sway_container *child) { | |||
82 | return i; | 82 | return i; |
83 | } | 83 | } |
84 | 84 | ||
85 | static void container_handle_fullscreen_reparent(struct sway_container *viewcon, | ||
86 | struct sway_container *old_parent) { | ||
87 | if (viewcon->type != C_VIEW || !viewcon->sway_view->is_fullscreen) { | ||
88 | return; | ||
89 | } | ||
90 | struct sway_view *view = viewcon->sway_view; | ||
91 | struct sway_container *old_workspace = old_parent; | ||
92 | if (old_workspace && old_workspace->type != C_WORKSPACE) { | ||
93 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | ||
94 | } | ||
95 | struct sway_container *new_workspace = container_parent(view->swayc, | ||
96 | C_WORKSPACE); | ||
97 | if (old_workspace == new_workspace) { | ||
98 | return; | ||
99 | } | ||
100 | // Unmark the old workspace as fullscreen | ||
101 | if (old_workspace) { | ||
102 | old_workspace->sway_workspace->fullscreen = NULL; | ||
103 | } | ||
104 | |||
105 | // Mark the new workspace as fullscreen | ||
106 | if (new_workspace->sway_workspace->fullscreen) { | ||
107 | view_set_fullscreen(new_workspace->sway_workspace->fullscreen, false); | ||
108 | } | ||
109 | new_workspace->sway_workspace->fullscreen = view; | ||
110 | // Resize view to new output dimensions | ||
111 | struct sway_output *output = new_workspace->parent->sway_output; | ||
112 | view_configure(view, 0, 0, | ||
113 | output->wlr_output->width, output->wlr_output->height); | ||
114 | } | ||
115 | |||
85 | void container_insert_child(struct sway_container *parent, | 116 | void container_insert_child(struct sway_container *parent, |
86 | struct sway_container *child, int i) { | 117 | struct sway_container *child, int i) { |
87 | struct sway_container *old_parent = child->parent; | 118 | struct sway_container *old_parent = child->parent; |
@@ -91,6 +122,7 @@ void container_insert_child(struct sway_container *parent, | |||
91 | wlr_log(L_DEBUG, "Inserting id:%zd at index %d", child->id, i); | 122 | wlr_log(L_DEBUG, "Inserting id:%zd at index %d", child->id, i); |
92 | list_insert(parent->children, i, child); | 123 | list_insert(parent->children, i, child); |
93 | child->parent = parent; | 124 | child->parent = parent; |
125 | container_handle_fullscreen_reparent(child, old_parent); | ||
94 | wl_signal_emit(&child->events.reparent, old_parent); | 126 | wl_signal_emit(&child->events.reparent, old_parent); |
95 | } | 127 | } |
96 | 128 | ||
@@ -106,6 +138,7 @@ struct sway_container *container_add_sibling(struct sway_container *fixed, | |||
106 | int i = index_child(fixed); | 138 | int i = index_child(fixed); |
107 | list_insert(parent->children, i + 1, active); | 139 | list_insert(parent->children, i + 1, active); |
108 | active->parent = parent; | 140 | active->parent = parent; |
141 | container_handle_fullscreen_reparent(active, old_parent); | ||
109 | wl_signal_emit(&active->events.reparent, old_parent); | 142 | wl_signal_emit(&active->events.reparent, old_parent); |
110 | return active->parent; | 143 | return active->parent; |
111 | } | 144 | } |
@@ -115,11 +148,18 @@ void container_add_child(struct sway_container *parent, | |||
115 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", | 148 | wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", |
116 | child, child->type, child->width, child->height, | 149 | child, child->type, child->width, child->height, |
117 | parent, parent->type, parent->width, parent->height); | 150 | parent, parent->type, parent->width, parent->height); |
151 | struct sway_container *old_parent = child->parent; | ||
118 | list_add(parent->children, child); | 152 | list_add(parent->children, child); |
153 | container_handle_fullscreen_reparent(child, old_parent); | ||
119 | child->parent = parent; | 154 | child->parent = parent; |
120 | } | 155 | } |
121 | 156 | ||
122 | struct sway_container *container_remove_child(struct sway_container *child) { | 157 | struct sway_container *container_remove_child(struct sway_container *child) { |
158 | if (child->type == C_VIEW && child->sway_view->is_fullscreen) { | ||
159 | struct sway_container *workspace = container_parent(child, C_WORKSPACE); | ||
160 | workspace->sway_workspace->fullscreen = NULL; | ||
161 | } | ||
162 | |||
123 | struct sway_container *parent = child->parent; | 163 | struct sway_container *parent = child->parent; |
124 | for (int i = 0; i < parent->children->length; ++i) { | 164 | for (int i = 0; i < parent->children->length; ++i) { |
125 | if (parent->children->items[i] == child) { | 165 | if (parent->children->items[i] == child) { |
@@ -164,6 +204,26 @@ void container_move_to(struct sway_container *container, | |||
164 | arrange_windows(old_parent, -1, -1); | 204 | arrange_windows(old_parent, -1, -1); |
165 | } | 205 | } |
166 | arrange_windows(new_parent, -1, -1); | 206 | arrange_windows(new_parent, -1, -1); |
207 | // If view was moved to a fullscreen workspace, refocus the fullscreen view | ||
208 | struct sway_container *new_workspace = container; | ||
209 | if (new_workspace->type != C_WORKSPACE) { | ||
210 | new_workspace = container_parent(new_workspace, C_WORKSPACE); | ||
211 | } | ||
212 | if (new_workspace->sway_workspace->fullscreen) { | ||
213 | struct sway_seat *seat; | ||
214 | struct sway_container *focus, *focus_ws; | ||
215 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
216 | focus = seat_get_focus(seat); | ||
217 | focus_ws = focus; | ||
218 | if (focus_ws->type != C_WORKSPACE) { | ||
219 | focus_ws = container_parent(focus_ws, C_WORKSPACE); | ||
220 | } | ||
221 | seat_set_focus(seat, new_workspace->sway_workspace->fullscreen->swayc); | ||
222 | if (focus_ws != new_workspace) { | ||
223 | seat_set_focus(seat, focus); | ||
224 | } | ||
225 | } | ||
226 | } | ||
167 | } | 227 | } |
168 | 228 | ||
169 | static bool sway_dir_to_wlr(enum movement_direction dir, | 229 | static bool sway_dir_to_wlr(enum movement_direction dir, |
@@ -268,6 +328,11 @@ void container_move(struct sway_container *container, | |||
268 | struct sway_container *current = container; | 328 | struct sway_container *current = container; |
269 | struct sway_container *parent = current->parent; | 329 | struct sway_container *parent = current->parent; |
270 | 330 | ||
331 | // If moving a fullscreen view, only consider outputs | ||
332 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { | ||
333 | current = container_parent(container, C_OUTPUT); | ||
334 | } | ||
335 | |||
271 | if (parent != container_flatten(parent)) { | 336 | if (parent != container_flatten(parent)) { |
272 | // Special case: we were the last one in this container, so flatten it | 337 | // Special case: we were the last one in this container, so flatten it |
273 | // and leave | 338 | // and leave |
@@ -568,6 +633,11 @@ void arrange_windows(struct sway_container *container, | |||
568 | container->y = y = area->y; | 633 | container->y = y = area->y; |
569 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", | 634 | wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", |
570 | container->name, container->x, container->y); | 635 | container->name, container->x, container->y); |
636 | if (container->sway_workspace->fullscreen) { | ||
637 | view_configure(container->sway_workspace->fullscreen, 0, 0, | ||
638 | output->width, output->height); | ||
639 | return; | ||
640 | } | ||
571 | } | 641 | } |
572 | // children are properly handled below | 642 | // children are properly handled below |
573 | break; | 643 | break; |
@@ -816,34 +886,26 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { | |||
816 | struct sway_container *container_get_in_direction( | 886 | struct sway_container *container_get_in_direction( |
817 | struct sway_container *container, struct sway_seat *seat, | 887 | struct sway_container *container, struct sway_seat *seat, |
818 | enum movement_direction dir) { | 888 | enum movement_direction dir) { |
819 | if (dir == MOVE_CHILD) { | ||
820 | return seat_get_focus_inactive(seat, container); | ||
821 | } | ||
822 | |||
823 | struct sway_container *parent = container->parent; | 889 | struct sway_container *parent = container->parent; |
824 | if (dir == MOVE_PARENT) { | 890 | |
825 | if (parent->type == C_OUTPUT) { | 891 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { |
892 | if (dir == MOVE_PARENT || dir == MOVE_CHILD) { | ||
826 | return NULL; | 893 | return NULL; |
827 | } else { | ||
828 | return parent; | ||
829 | } | 894 | } |
830 | } | ||
831 | |||
832 | // TODO WLR fullscreen | ||
833 | /* | ||
834 | if (container->type == C_VIEW && swayc_is_fullscreen(container)) { | ||
835 | wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); | ||
836 | container = container_parent(container, C_OUTPUT); | 895 | container = container_parent(container, C_OUTPUT); |
837 | get_layout_center_position(container, &abs_pos); | 896 | parent = container->parent; |
838 | struct sway_container *output = | 897 | } else { |
839 | swayc_adjacent_output(container, dir, &abs_pos, true); | 898 | if (dir == MOVE_CHILD) { |
840 | return get_swayc_in_output_direction(output, dir); | 899 | return seat_get_focus_inactive(seat, container); |
841 | } | 900 | } |
842 | if (container->type == C_WORKSPACE && container->fullscreen) { | 901 | if (dir == MOVE_PARENT) { |
843 | sway_log(L_DEBUG, "Moving to fullscreen view"); | 902 | if (parent->type == C_OUTPUT) { |
844 | return container->fullscreen; | 903 | return NULL; |
904 | } else { | ||
905 | return parent; | ||
906 | } | ||
907 | } | ||
845 | } | 908 | } |
846 | */ | ||
847 | 909 | ||
848 | struct sway_container *wrap_candidate = NULL; | 910 | struct sway_container *wrap_candidate = NULL; |
849 | while (true) { | 911 | while (true) { |
@@ -874,6 +936,14 @@ struct sway_container *container_get_in_direction( | |||
874 | if (next == NULL) { | 936 | if (next == NULL) { |
875 | return NULL; | 937 | return NULL; |
876 | } | 938 | } |
939 | struct sway_container *next_workspace = next; | ||
940 | if (next_workspace->type != C_WORKSPACE) { | ||
941 | next_workspace = container_parent(next_workspace, C_WORKSPACE); | ||
942 | } | ||
943 | sway_assert(next_workspace, "Next container has no workspace"); | ||
944 | if (next_workspace->sway_workspace->fullscreen) { | ||
945 | return next_workspace->sway_workspace->fullscreen->swayc; | ||
946 | } | ||
877 | if (next->children && next->children->length) { | 947 | if (next->children && next->children->length) { |
878 | // TODO consider floating children as well | 948 | // TODO consider floating children as well |
879 | return seat_get_focus_inactive_view(seat, next); | 949 | return seat_get_focus_inactive_view(seat, next); |