diff options
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r-- | sway/tree/layout.c | 136 |
1 files changed, 112 insertions, 24 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 0b637822..56d4e1d2 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 |
@@ -531,6 +596,12 @@ void arrange_windows(struct sway_container *container, | |||
531 | container->name, container->width, container->height, container->x, | 596 | container->name, container->width, container->height, container->x, |
532 | container->y); | 597 | container->y); |
533 | 598 | ||
599 | if (container->type == C_WORKSPACE | ||
600 | && container->sway_workspace->fullscreen) { | ||
601 | view_configure(container->sway_workspace->fullscreen, 0, 0, | ||
602 | container->parent->width, container->parent->height); | ||
603 | } | ||
604 | |||
534 | double x = 0, y = 0; | 605 | double x = 0, y = 0; |
535 | switch (container->type) { | 606 | switch (container->type) { |
536 | case C_ROOT: | 607 | case C_ROOT: |
@@ -557,6 +628,9 @@ void arrange_windows(struct sway_container *container, | |||
557 | return; | 628 | return; |
558 | case C_WORKSPACE: | 629 | case C_WORKSPACE: |
559 | { | 630 | { |
631 | if (container->sway_workspace->fullscreen) { | ||
632 | return; | ||
633 | } | ||
560 | struct sway_container *output = | 634 | struct sway_container *output = |
561 | container_parent(container, C_OUTPUT); | 635 | container_parent(container, C_OUTPUT); |
562 | struct wlr_box *area = &output->sway_output->usable_area; | 636 | struct wlr_box *area = &output->sway_output->usable_area; |
@@ -813,37 +887,29 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { | |||
813 | return NULL; | 887 | return NULL; |
814 | } | 888 | } |
815 | 889 | ||
816 | struct sway_container *container_get_in_direction( | 890 | static struct sway_container *container_get_in_direction_naive( |
817 | struct sway_container *container, struct sway_seat *seat, | 891 | struct sway_container *container, struct sway_seat *seat, |
818 | enum movement_direction dir) { | 892 | 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; | 893 | struct sway_container *parent = container->parent; |
824 | if (dir == MOVE_PARENT) { | 894 | |
825 | if (parent->type == C_OUTPUT) { | 895 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { |
896 | if (dir == MOVE_PARENT || dir == MOVE_CHILD) { | ||
826 | return NULL; | 897 | return NULL; |
827 | } else { | ||
828 | return parent; | ||
829 | } | 898 | } |
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); | 899 | container = container_parent(container, C_OUTPUT); |
837 | get_layout_center_position(container, &abs_pos); | 900 | parent = container->parent; |
838 | struct sway_container *output = | 901 | } else { |
839 | swayc_adjacent_output(container, dir, &abs_pos, true); | 902 | if (dir == MOVE_CHILD) { |
840 | return get_swayc_in_output_direction(output, dir); | 903 | return seat_get_focus_inactive(seat, container); |
841 | } | 904 | } |
842 | if (container->type == C_WORKSPACE && container->fullscreen) { | 905 | if (dir == MOVE_PARENT) { |
843 | sway_log(L_DEBUG, "Moving to fullscreen view"); | 906 | if (parent->type == C_OUTPUT) { |
844 | return container->fullscreen; | 907 | return NULL; |
908 | } else { | ||
909 | return parent; | ||
910 | } | ||
911 | } | ||
845 | } | 912 | } |
846 | */ | ||
847 | 913 | ||
848 | struct sway_container *wrap_candidate = NULL; | 914 | struct sway_container *wrap_candidate = NULL; |
849 | while (true) { | 915 | while (true) { |
@@ -930,6 +996,28 @@ struct sway_container *container_get_in_direction( | |||
930 | } | 996 | } |
931 | } | 997 | } |
932 | 998 | ||
999 | struct sway_container *container_get_in_direction( | ||
1000 | struct sway_container *container, struct sway_seat *seat, | ||
1001 | enum movement_direction dir) { | ||
1002 | struct sway_container *result = container_get_in_direction_naive(container, | ||
1003 | seat, dir); | ||
1004 | if (!result) { | ||
1005 | return NULL; | ||
1006 | } | ||
1007 | struct sway_container *old_workspace = container; | ||
1008 | if (old_workspace->type != C_WORKSPACE) { | ||
1009 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | ||
1010 | } | ||
1011 | struct sway_container *new_workspace = result; | ||
1012 | if (new_workspace->type != C_WORKSPACE) { | ||
1013 | new_workspace = container_parent(new_workspace, C_WORKSPACE); | ||
1014 | } | ||
1015 | if (old_workspace != new_workspace && new_workspace->sway_workspace->fullscreen) { | ||
1016 | result = new_workspace->sway_workspace->fullscreen->swayc; | ||
1017 | } | ||
1018 | return result; | ||
1019 | } | ||
1020 | |||
933 | struct sway_container *container_replace_child(struct sway_container *child, | 1021 | struct sway_container *container_replace_child(struct sway_container *child, |
934 | struct sway_container *new_child) { | 1022 | struct sway_container *new_child) { |
935 | struct sway_container *parent = child->parent; | 1023 | struct sway_container *parent = child->parent; |