diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-18 00:10:32 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-04-18 00:10:32 +1000 |
commit | 72beae209b03815e39d0aaa11348fa17c8a7bca9 (patch) | |
tree | fefa256f93c8fa7a3e80f9fb54accd0e6108e77a /sway | |
parent | Fix views unmapping their own fullscreen windows. (diff) | |
download | sway-72beae209b03815e39d0aaa11348fa17c8a7bca9.tar.gz sway-72beae209b03815e39d0aaa11348fa17c8a7bca9.tar.zst sway-72beae209b03815e39d0aaa11348fa17c8a7bca9.zip |
Fullscreen fixes.
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands/fullscreen.c | 7 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 31 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 4 | ||||
-rw-r--r-- | sway/tree/layout.c | 136 | ||||
-rw-r--r-- | sway/tree/view.c | 20 |
5 files changed, 169 insertions, 29 deletions
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index 5a044aa8..8692e92d 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c | |||
@@ -6,8 +6,11 @@ | |||
6 | #include "sway/tree/view.h" | 6 | #include "sway/tree/view.h" |
7 | #include "sway/tree/layout.h" | 7 | #include "sway/tree/layout.h" |
8 | 8 | ||
9 | // fullscreen toggle|enable|disable | ||
10 | struct cmd_results *cmd_fullscreen(int argc, char **argv) { | 9 | struct cmd_results *cmd_fullscreen(int argc, char **argv) { |
10 | struct cmd_results *error = NULL; | ||
11 | if ((error = checkarg(argc, "fullscreen", EXPECTED_LESS_THAN, 2))) { | ||
12 | return error; | ||
13 | } | ||
11 | struct sway_container *container = | 14 | struct sway_container *container = |
12 | config->handler_context.current_container; | 15 | config->handler_context.current_container; |
13 | if (container->type != C_VIEW) { | 16 | if (container->type != C_VIEW) { |
@@ -25,7 +28,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { | |||
25 | wants_fullscreen = false; | 28 | wants_fullscreen = false; |
26 | } else { | 29 | } else { |
27 | return cmd_results_new(CMD_INVALID, "fullscreen", | 30 | return cmd_results_new(CMD_INVALID, "fullscreen", |
28 | "Expected 'fullscreen' or fullscreen <enable|disable|toggle>'"); | 31 | "Expected 'fullscreen' or 'fullscreen <enable|disable|toggle>'"); |
29 | } | 32 | } |
30 | 33 | ||
31 | view_set_fullscreen(view, wants_fullscreen); | 34 | view_set_fullscreen(view, wants_fullscreen); |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 96332e5c..2d666d95 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -61,14 +61,21 @@ static void destroy(struct sway_view *view) { | |||
61 | } | 61 | } |
62 | wl_list_remove(&wl_shell_view->commit.link); | 62 | wl_list_remove(&wl_shell_view->commit.link); |
63 | wl_list_remove(&wl_shell_view->destroy.link); | 63 | wl_list_remove(&wl_shell_view->destroy.link); |
64 | wl_list_remove(&wl_shell_view->request_fullscreen.link); | ||
65 | wl_list_remove(&wl_shell_view->set_state.link); | ||
64 | free(wl_shell_view); | 66 | free(wl_shell_view); |
65 | } | 67 | } |
66 | 68 | ||
69 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { | ||
70 | // TODO | ||
71 | } | ||
72 | |||
67 | static const struct sway_view_impl view_impl = { | 73 | static const struct sway_view_impl view_impl = { |
68 | .get_prop = get_prop, | 74 | .get_prop = get_prop, |
69 | .configure = configure, | 75 | .configure = configure, |
70 | .close = _close, | 76 | .close = _close, |
71 | .destroy = destroy, | 77 | .destroy = destroy, |
78 | .set_fullscreen = set_fullscreen, | ||
72 | }; | 79 | }; |
73 | 80 | ||
74 | static void handle_commit(struct wl_listener *listener, void *data) { | 81 | static void handle_commit(struct wl_listener *listener, void *data) { |
@@ -88,6 +95,23 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
88 | view_destroy(&wl_shell_view->view); | 95 | view_destroy(&wl_shell_view->view); |
89 | } | 96 | } |
90 | 97 | ||
98 | static void handle_request_fullscreen(struct wl_listener *listener, void *data) { | ||
99 | struct sway_wl_shell_view *wl_shell_view = | ||
100 | wl_container_of(listener, wl_shell_view, request_fullscreen); | ||
101 | view_set_fullscreen(&wl_shell_view->view, true); | ||
102 | } | ||
103 | |||
104 | static void handle_set_state(struct wl_listener *listener, void *data) { | ||
105 | struct sway_wl_shell_view *wl_shell_view = | ||
106 | wl_container_of(listener, wl_shell_view, set_state); | ||
107 | struct sway_view *view = &wl_shell_view->view; | ||
108 | struct wlr_wl_shell_surface *surface = view->wlr_wl_shell_surface; | ||
109 | if (view->is_fullscreen && | ||
110 | surface->state != WLR_WL_SHELL_SURFACE_STATE_FULLSCREEN) { | ||
111 | view_set_fullscreen(view, false); | ||
112 | } | ||
113 | } | ||
114 | |||
91 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | 115 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { |
92 | struct sway_server *server = wl_container_of(listener, server, | 116 | struct sway_server *server = wl_container_of(listener, server, |
93 | wl_shell_surface); | 117 | wl_shell_surface); |
@@ -127,6 +151,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
127 | wl_shell_view->destroy.notify = handle_destroy; | 151 | wl_shell_view->destroy.notify = handle_destroy; |
128 | wl_signal_add(&shell_surface->events.destroy, &wl_shell_view->destroy); | 152 | wl_signal_add(&shell_surface->events.destroy, &wl_shell_view->destroy); |
129 | 153 | ||
154 | wl_shell_view->request_fullscreen.notify = handle_request_fullscreen; | ||
155 | wl_signal_add(&shell_surface->events.request_fullscreen, | ||
156 | &wl_shell_view->request_fullscreen); | ||
157 | |||
158 | wl_shell_view->set_state.notify = handle_set_state; | ||
159 | wl_signal_add(&shell_surface->events.set_state, &wl_shell_view->set_state); | ||
160 | |||
130 | view_map(&wl_shell_view->view, shell_surface->surface); | 161 | view_map(&wl_shell_view->view, shell_surface->surface); |
131 | 162 | ||
132 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_FULLSCREEN) { | 163 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_FULLSCREEN) { |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 731862a9..6c0556b2 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -229,7 +229,9 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
229 | wl_container_of(listener, xdg_shell_v6_view, request_fullscreen); | 229 | wl_container_of(listener, xdg_shell_v6_view, request_fullscreen); |
230 | struct wlr_xdg_toplevel_v6_set_fullscreen_event *e = data; | 230 | struct wlr_xdg_toplevel_v6_set_fullscreen_event *e = data; |
231 | 231 | ||
232 | if (xdg_shell_v6_view->view.wlr_xdg_surface_v6->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) { | 232 | if (!sway_assert(xdg_shell_v6_view->view.wlr_xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL, |
233 | "xdg_shell_v6 requested fullscreen of surface with role %i", | ||
234 | xdg_shell_v6_view->view.wlr_xdg_surface_v6->role)) { | ||
233 | return; | 235 | return; |
234 | } | 236 | } |
235 | 237 | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 62219bb1..d931c4dc 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) { |
@@ -137,21 +177,6 @@ void container_move_to(struct sway_container *container, | |||
137 | || container_has_anscestor(container, destination)) { | 177 | || container_has_anscestor(container, destination)) { |
138 | return; | 178 | return; |
139 | } | 179 | } |
140 | |||
141 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { | ||
142 | struct sway_container *old_workspace = container; | ||
143 | if (old_workspace->type != C_WORKSPACE) { | ||
144 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | ||
145 | } | ||
146 | struct sway_container *new_workspace = destination; | ||
147 | if (new_workspace->type != C_WORKSPACE) { | ||
148 | new_workspace = container_parent(new_workspace, C_WORKSPACE); | ||
149 | } | ||
150 | if (old_workspace != new_workspace) { | ||
151 | view_set_fullscreen(container->sway_view, false); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | struct sway_container *old_parent = container_remove_child(container); | 180 | struct sway_container *old_parent = container_remove_child(container); |
156 | container->width = container->height = 0; | 181 | container->width = container->height = 0; |
157 | struct sway_container *new_parent; | 182 | struct sway_container *new_parent; |
@@ -179,6 +204,26 @@ void container_move_to(struct sway_container *container, | |||
179 | arrange_windows(old_parent, -1, -1); | 204 | arrange_windows(old_parent, -1, -1); |
180 | } | 205 | } |
181 | 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 | } | ||
182 | } | 227 | } |
183 | 228 | ||
184 | static bool sway_dir_to_wlr(enum movement_direction dir, | 229 | static bool sway_dir_to_wlr(enum movement_direction dir, |
@@ -283,6 +328,11 @@ void container_move(struct sway_container *container, | |||
283 | struct sway_container *current = container; | 328 | struct sway_container *current = container; |
284 | struct sway_container *parent = current->parent; | 329 | struct sway_container *parent = current->parent; |
285 | 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 | |||
286 | if (parent != container_flatten(parent)) { | 336 | if (parent != container_flatten(parent)) { |
287 | // 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 |
288 | // and leave | 338 | // and leave |
@@ -546,6 +596,14 @@ void arrange_windows(struct sway_container *container, | |||
546 | container->name, container->width, container->height, container->x, | 596 | container->name, container->width, container->height, container->x, |
547 | container->y); | 597 | container->y); |
548 | 598 | ||
599 | if (container->type == C_WORKSPACE | ||
600 | && container->sway_workspace->fullscreen) { | ||
601 | struct wlr_output *wlr_output | ||
602 | = container->parent->sway_output->wlr_output; | ||
603 | view_configure(container->sway_workspace->fullscreen, 0, 0, | ||
604 | wlr_output->width, wlr_output->height); | ||
605 | } | ||
606 | |||
549 | double x = 0, y = 0; | 607 | double x = 0, y = 0; |
550 | switch (container->type) { | 608 | switch (container->type) { |
551 | case C_ROOT: | 609 | case C_ROOT: |
@@ -831,19 +889,27 @@ static struct sway_container *sway_output_from_wlr(struct wlr_output *output) { | |||
831 | return NULL; | 889 | return NULL; |
832 | } | 890 | } |
833 | 891 | ||
834 | struct sway_container *container_get_in_direction( | 892 | static struct sway_container *container_get_in_direction_naive( |
835 | struct sway_container *container, struct sway_seat *seat, | 893 | struct sway_container *container, struct sway_seat *seat, |
836 | enum movement_direction dir) { | 894 | enum movement_direction dir) { |
837 | if (dir == MOVE_CHILD) { | ||
838 | return seat_get_focus_inactive(seat, container); | ||
839 | } | ||
840 | |||
841 | struct sway_container *parent = container->parent; | 895 | struct sway_container *parent = container->parent; |
842 | if (dir == MOVE_PARENT) { | 896 | |
843 | if (parent->type == C_OUTPUT) { | 897 | if (container->type == C_VIEW && container->sway_view->is_fullscreen) { |
898 | if (dir == MOVE_PARENT || dir == MOVE_CHILD) { | ||
844 | return NULL; | 899 | return NULL; |
845 | } else { | 900 | } |
846 | return parent; | 901 | container = container_parent(container, C_OUTPUT); |
902 | parent = container->parent; | ||
903 | } else { | ||
904 | if (dir == MOVE_CHILD) { | ||
905 | return seat_get_focus_inactive(seat, container); | ||
906 | } | ||
907 | if (dir == MOVE_PARENT) { | ||
908 | if (parent->type == C_OUTPUT) { | ||
909 | return NULL; | ||
910 | } else { | ||
911 | return parent; | ||
912 | } | ||
847 | } | 913 | } |
848 | } | 914 | } |
849 | 915 | ||
@@ -932,6 +998,28 @@ struct sway_container *container_get_in_direction( | |||
932 | } | 998 | } |
933 | } | 999 | } |
934 | 1000 | ||
1001 | struct sway_container *container_get_in_direction( | ||
1002 | struct sway_container *container, struct sway_seat *seat, | ||
1003 | enum movement_direction dir) { | ||
1004 | struct sway_container *result = container_get_in_direction_naive(container, | ||
1005 | seat, dir); | ||
1006 | if (!result) { | ||
1007 | return NULL; | ||
1008 | } | ||
1009 | struct sway_container *old_workspace = container; | ||
1010 | if (old_workspace->type != C_WORKSPACE) { | ||
1011 | old_workspace = container_parent(old_workspace, C_WORKSPACE); | ||
1012 | } | ||
1013 | struct sway_container *new_workspace = result; | ||
1014 | if (new_workspace->type != C_WORKSPACE) { | ||
1015 | new_workspace = container_parent(new_workspace, C_WORKSPACE); | ||
1016 | } | ||
1017 | if (old_workspace != new_workspace && new_workspace->sway_workspace->fullscreen) { | ||
1018 | result = new_workspace->sway_workspace->fullscreen->swayc; | ||
1019 | } | ||
1020 | return result; | ||
1021 | } | ||
1022 | |||
935 | struct sway_container *container_replace_child(struct sway_container *child, | 1023 | struct sway_container *container_replace_child(struct sway_container *child, |
936 | struct sway_container *new_child) { | 1024 | struct sway_container *new_child) { |
937 | struct sway_container *parent = child->parent; | 1025 | struct sway_container *parent = child->parent; |
diff --git a/sway/tree/view.c b/sway/tree/view.c index fa27ec36..b92c7099 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -91,13 +91,29 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
91 | view->is_fullscreen = fullscreen; | 91 | view->is_fullscreen = fullscreen; |
92 | 92 | ||
93 | if (fullscreen) { | 93 | if (fullscreen) { |
94 | if (workspace->sway_workspace->fullscreen) { | ||
95 | view_set_fullscreen(workspace->sway_workspace->fullscreen, false); | ||
96 | } | ||
94 | workspace->sway_workspace->fullscreen = view; | 97 | workspace->sway_workspace->fullscreen = view; |
95 | view_configure(view, 0, 0, output->wlr_output->width, output->wlr_output->height); | 98 | |
99 | struct sway_seat *seat; | ||
100 | struct sway_container *focus, *focus_ws; | ||
101 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
102 | focus = seat_get_focus(seat); | ||
103 | focus_ws = focus; | ||
104 | if (focus_ws->type != C_WORKSPACE) { | ||
105 | focus_ws = container_parent(focus_ws, C_WORKSPACE); | ||
106 | } | ||
107 | seat_set_focus(seat, view->swayc); | ||
108 | if (focus_ws != workspace) { | ||
109 | seat_set_focus(seat, focus); | ||
110 | } | ||
111 | } | ||
96 | } else { | 112 | } else { |
97 | workspace->sway_workspace->fullscreen = NULL; | 113 | workspace->sway_workspace->fullscreen = NULL; |
98 | arrange_windows(workspace, -1, -1); | ||
99 | } | 114 | } |
100 | 115 | ||
116 | arrange_windows(workspace, -1, -1); | ||
101 | output_damage_whole(output); | 117 | output_damage_whole(output); |
102 | 118 | ||
103 | ipc_event_window(view->swayc, "fullscreen_mode"); | 119 | ipc_event_window(view->swayc, "fullscreen_mode"); |