diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-30 11:58:17 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-03-30 13:49:34 -0400 |
commit | 49379dd0fc0758f89d7f4fa4fb5b08c7f4c26ae6 (patch) | |
tree | b67a66382125811fde75e5c3dff37d7081860c78 | |
parent | Merge pull request #1664 from swaywm/xwayland-add-to-focused (diff) | |
download | sway-49379dd0fc0758f89d7f4fa4fb5b08c7f4c26ae6.tar.gz sway-49379dd0fc0758f89d7f4fa4fb5b08c7f4c26ae6.tar.zst sway-49379dd0fc0758f89d7f4fa4fb5b08c7f4c26ae6.zip |
Fix workspace deletion edge cases
-rw-r--r-- | include/sway/tree/container.h | 2 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 2 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 2 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 3 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 20 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/tree/container.c | 101 | ||||
-rw-r--r-- | sway/tree/layout.c | 58 | ||||
-rw-r--r-- | sway/tree/output.c | 36 | ||||
-rw-r--r-- | sway/tree/view.c | 11 | ||||
-rw-r--r-- | sway/tree/workspace.c | 56 |
11 files changed, 145 insertions, 147 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 24e8468e..6aa66da0 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -104,7 +104,7 @@ struct sway_container *container_workspace_destroy( | |||
104 | 104 | ||
105 | struct sway_container *container_view_destroy(struct sway_container *view); | 105 | struct sway_container *container_view_destroy(struct sway_container *view); |
106 | 106 | ||
107 | void container_destroy(struct sway_container *cont); | 107 | struct sway_container *container_destroy(struct sway_container *cont); |
108 | 108 | ||
109 | struct sway_container *container_set_layout(struct sway_container *container, | 109 | struct sway_container *container_set_layout(struct sway_container *container, |
110 | enum sway_container_layout layout); | 110 | enum sway_container_layout layout); |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 8239366b..0a904c4b 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -39,6 +39,8 @@ struct sway_container *container_add_sibling(struct sway_container *parent, | |||
39 | 39 | ||
40 | struct sway_container *container_remove_child(struct sway_container *child); | 40 | struct sway_container *container_remove_child(struct sway_container *child); |
41 | 41 | ||
42 | struct sway_container *container_reap_empty(struct sway_container *container); | ||
43 | |||
42 | void container_move_to(struct sway_container* container, | 44 | void container_move_to(struct sway_container* container, |
43 | struct sway_container* destination); | 45 | struct sway_container* destination); |
44 | 46 | ||
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index d73b29c1..4e4c3450 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -23,4 +23,6 @@ struct sway_container *workspace_output_prev(struct sway_container *current); | |||
23 | 23 | ||
24 | struct sway_container *workspace_prev(struct sway_container *current); | 24 | struct sway_container *workspace_prev(struct sway_container *current); |
25 | 25 | ||
26 | bool workspace_is_visible(struct sway_container *ws); | ||
27 | |||
26 | #endif | 28 | #endif |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 25c0cbca..01f38d16 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -83,10 +83,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
83 | wl_container_of(listener, sway_xdg_surface, destroy); | 83 | wl_container_of(listener, sway_xdg_surface, destroy); |
84 | wl_list_remove(&sway_xdg_surface->commit.link); | 84 | wl_list_remove(&sway_xdg_surface->commit.link); |
85 | wl_list_remove(&sway_xdg_surface->destroy.link); | 85 | wl_list_remove(&sway_xdg_surface->destroy.link); |
86 | struct sway_container *parent = container_view_destroy(sway_xdg_surface->view->swayc); | 86 | container_view_destroy(sway_xdg_surface->view->swayc); |
87 | free(sway_xdg_surface->view); | 87 | free(sway_xdg_surface->view); |
88 | free(sway_xdg_surface); | 88 | free(sway_xdg_surface); |
89 | arrange_windows(parent, -1, -1); | ||
90 | } | 89 | } |
91 | 90 | ||
92 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | 91 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3e08b20e..357c8883 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -109,29 +109,17 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
109 | wl_list_remove(&sway_surface->destroy.link); | 109 | wl_list_remove(&sway_surface->destroy.link); |
110 | wl_list_remove(&sway_surface->request_configure.link); | 110 | wl_list_remove(&sway_surface->request_configure.link); |
111 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 111 | wl_list_remove(&sway_surface->view->unmanaged_view_link); |
112 | 112 | container_view_destroy(sway_surface->view->swayc); | |
113 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | 113 | sway_surface->view->swayc = NULL; |
114 | if (parent) { | 114 | sway_surface->view->surface = NULL; |
115 | arrange_windows(parent, -1, -1); | ||
116 | } | ||
117 | |||
118 | free(sway_surface->view); | ||
119 | free(sway_surface); | ||
120 | } | 115 | } |
121 | 116 | ||
122 | static void handle_unmap_notify(struct wl_listener *listener, void *data) { | 117 | static void handle_unmap_notify(struct wl_listener *listener, void *data) { |
123 | struct sway_xwayland_surface *sway_surface = | 118 | struct sway_xwayland_surface *sway_surface = |
124 | wl_container_of(listener, sway_surface, unmap_notify); | 119 | wl_container_of(listener, sway_surface, unmap_notify); |
125 | |||
126 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 120 | wl_list_remove(&sway_surface->view->unmanaged_view_link); |
127 | wl_list_init(&sway_surface->view->unmanaged_view_link); | 121 | wl_list_init(&sway_surface->view->unmanaged_view_link); |
128 | 122 | container_view_destroy(sway_surface->view->swayc); | |
129 | // take it out of the tree | ||
130 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | ||
131 | if (parent) { | ||
132 | arrange_windows(parent, -1, -1); | ||
133 | } | ||
134 | |||
135 | sway_surface->view->swayc = NULL; | 123 | sway_surface->view->swayc = NULL; |
136 | sway_surface->view->surface = NULL; | 124 | sway_surface->view->surface = NULL; |
137 | } | 125 | } |
diff --git a/sway/meson.build b/sway/meson.build index 9c5e4a00..e8a192f0 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -82,6 +82,7 @@ sway_sources = files( | |||
82 | 'security.c', | 82 | 'security.c', |
83 | 'tree/container.c', | 83 | 'tree/container.c', |
84 | 'tree/layout.c', | 84 | 'tree/layout.c', |
85 | 'tree/output.c', | ||
85 | 'tree/view.c', | 86 | 'tree/view.c', |
86 | 'tree/workspace.c', | 87 | 'tree/workspace.c', |
87 | ) | 88 | ) |
diff --git a/sway/tree/container.c b/sway/tree/container.c index ed39a154..778108b4 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -10,12 +10,12 @@ | |||
10 | #include "sway/tree/container.h" | 10 | #include "sway/tree/container.h" |
11 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
12 | #include "sway/input/seat.h" | 12 | #include "sway/input/seat.h" |
13 | #include "sway/tree/layout.h" | 13 | #include "sway/ipc-server.h" |
14 | #include "sway/output.h" | 14 | #include "sway/output.h" |
15 | #include "sway/server.h" | 15 | #include "sway/server.h" |
16 | #include "sway/tree/layout.h" | ||
16 | #include "sway/tree/view.h" | 17 | #include "sway/tree/view.h" |
17 | #include "sway/tree/workspace.h" | 18 | #include "sway/tree/workspace.h" |
18 | #include "sway/ipc-server.h" | ||
19 | #include "log.h" | 19 | #include "log.h" |
20 | 20 | ||
21 | static list_t *bfs_queue; | 21 | static list_t *bfs_queue; |
@@ -58,13 +58,14 @@ static struct sway_container *container_create(enum sway_container_type type) { | |||
58 | return c; | 58 | return c; |
59 | } | 59 | } |
60 | 60 | ||
61 | void container_destroy(struct sway_container *cont) { | 61 | struct sway_container *container_destroy(struct sway_container *cont) { |
62 | if (cont == NULL) { | 62 | if (cont == NULL) { |
63 | return; | 63 | return NULL; |
64 | } | 64 | } |
65 | 65 | ||
66 | wl_signal_emit(&cont->events.destroy, cont); | 66 | wl_signal_emit(&cont->events.destroy, cont); |
67 | 67 | ||
68 | struct sway_container *parent = cont->parent; | ||
68 | if (cont->children) { | 69 | if (cont->children) { |
69 | // remove children until there are no more, container_destroy calls | 70 | // remove children until there are no more, container_destroy calls |
70 | // container_remove_child, which removes child from this container | 71 | // container_remove_child, which removes child from this container |
@@ -77,13 +78,14 @@ void container_destroy(struct sway_container *cont) { | |||
77 | list_foreach(cont->marks, free); | 78 | list_foreach(cont->marks, free); |
78 | list_free(cont->marks); | 79 | list_free(cont->marks); |
79 | } | 80 | } |
80 | if (cont->parent) { | 81 | if (parent) { |
81 | container_remove_child(cont); | 82 | container_remove_child(cont); |
82 | } | 83 | } |
83 | if (cont->name) { | 84 | if (cont->name) { |
84 | free(cont->name); | 85 | free(cont->name); |
85 | } | 86 | } |
86 | free(cont); | 87 | free(cont); |
88 | return parent; | ||
87 | } | 89 | } |
88 | 90 | ||
89 | struct sway_container *container_output_create( | 91 | struct sway_container *container_output_create( |
@@ -202,95 +204,6 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
202 | return swayc; | 204 | return swayc; |
203 | } | 205 | } |
204 | 206 | ||
205 | struct sway_container *container_output_destroy(struct sway_container *output) { | ||
206 | if (!sway_assert(output, "cannot destroy null output")) { | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | if (output->children->length > 0) { | ||
211 | // TODO save workspaces when there are no outputs. | ||
212 | // TODO also check if there will ever be no outputs except for exiting | ||
213 | // program | ||
214 | if (root_container.children->length > 1) { | ||
215 | int p = root_container.children->items[0] == output; | ||
216 | // Move workspace from this output to another output | ||
217 | while (output->children->length) { | ||
218 | struct sway_container *child = output->children->items[0]; | ||
219 | container_remove_child(child); | ||
220 | container_add_child(root_container.children->items[p], child); | ||
221 | } | ||
222 | container_sort_workspaces(root_container.children->items[p]); | ||
223 | arrange_windows(root_container.children->items[p], | ||
224 | -1, -1); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | wl_list_remove(&output->sway_output->frame.link); | ||
229 | wl_list_remove(&output->sway_output->destroy.link); | ||
230 | wl_list_remove(&output->sway_output->mode.link); | ||
231 | |||
232 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | ||
233 | container_destroy(output); | ||
234 | |||
235 | return &root_container; | ||
236 | } | ||
237 | |||
238 | struct sway_container *container_workspace_destroy( | ||
239 | struct sway_container *workspace) { | ||
240 | if (!sway_assert(workspace, "cannot destroy null workspace")) { | ||
241 | return NULL; | ||
242 | } | ||
243 | |||
244 | // Do not destroy this if it's the last workspace on this output | ||
245 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | ||
246 | if (output && output->children->length == 1) { | ||
247 | return NULL; | ||
248 | } | ||
249 | |||
250 | struct sway_container *parent = workspace->parent; | ||
251 | if (workspace->children->length == 0) { | ||
252 | // destroy the WS if there are no children (TODO check for floating) | ||
253 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | ||
254 | ipc_event_workspace(workspace, NULL, "empty"); | ||
255 | } else { | ||
256 | // Move children to a different workspace on this output | ||
257 | struct sway_container *new_workspace = NULL; | ||
258 | // TODO move floating | ||
259 | for (int i = 0; i < output->children->length; i++) { | ||
260 | if (output->children->items[i] != workspace) { | ||
261 | new_workspace = output->children->items[i]; | ||
262 | break; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", | ||
267 | workspace->name, new_workspace->name); | ||
268 | for (int i = 0; i < workspace->children->length; i++) { | ||
269 | container_move_to(workspace->children->items[i], new_workspace); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | container_destroy(workspace); | ||
274 | return parent; | ||
275 | } | ||
276 | |||
277 | struct sway_container *container_view_destroy(struct sway_container *view) { | ||
278 | if (!view) { | ||
279 | return NULL; | ||
280 | } | ||
281 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
282 | struct sway_container *parent = view->parent; | ||
283 | container_destroy(view); | ||
284 | |||
285 | // TODO WLR: Destroy empty containers | ||
286 | /* | ||
287 | if (parent && parent->type == C_CONTAINER) { | ||
288 | return destroy_container(parent); | ||
289 | } | ||
290 | */ | ||
291 | return parent; | ||
292 | } | ||
293 | |||
294 | struct sway_container *container_set_layout(struct sway_container *container, | 207 | struct sway_container *container_set_layout(struct sway_container *container, |
295 | enum sway_container_layout layout) { | 208 | enum sway_container_layout layout) { |
296 | if (container->type == C_WORKSPACE) { | 209 | if (container->type == C_WORKSPACE) { |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 73c4849b..32e6a77c 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "sway/tree/container.h" | 9 | #include "sway/tree/container.h" |
10 | #include "sway/tree/layout.h" | 10 | #include "sway/tree/layout.h" |
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/tree/workspace.h" | ||
12 | #include "sway/tree/view.h" | 13 | #include "sway/tree/view.h" |
13 | #include "sway/input/seat.h" | 14 | #include "sway/input/seat.h" |
14 | #include "sway/ipc-server.h" | 15 | #include "sway/ipc-server.h" |
@@ -99,40 +100,40 @@ void container_add_child(struct sway_container *parent, | |||
99 | parent, parent->type, parent->width, parent->height); | 100 | parent, parent->type, parent->width, parent->height); |
100 | list_add(parent->children, child); | 101 | list_add(parent->children, child); |
101 | child->parent = parent; | 102 | child->parent = parent; |
102 | // set focus for this container | 103 | } |
103 | /* TODO WLR | 104 | |
104 | if (parent->type == C_WORKSPACE && child->type == C_VIEW && | 105 | struct sway_container *container_reap_empty(struct sway_container *container) { |
105 | (parent->workspace_layout == L_TABBED || parent->workspace_layout == | 106 | if (!sway_assert(container, "reaping null container")) { |
106 | L_STACKED)) { | 107 | return NULL; |
107 | child = new_container(child, parent->workspace_layout); | ||
108 | } | 108 | } |
109 | */ | 109 | wlr_log(L_DEBUG, "reaping %p %s", container, container->name); |
110 | while (container->children->length == 0) { | ||
111 | if (container->type == C_WORKSPACE) { | ||
112 | if (!workspace_is_visible(container)) { | ||
113 | container_workspace_destroy(container); | ||
114 | } | ||
115 | break; | ||
116 | } else if (container->type == C_CONTAINER) { | ||
117 | struct sway_container *parent = container->parent; | ||
118 | container_destroy(container); | ||
119 | container = parent; | ||
120 | } else { | ||
121 | container = container->parent; | ||
122 | } | ||
123 | } | ||
124 | return container; | ||
110 | } | 125 | } |
111 | 126 | ||
112 | struct sway_container *container_remove_child(struct sway_container *child) { | 127 | struct sway_container *container_remove_child(struct sway_container *child) { |
113 | int i; | ||
114 | struct sway_container *parent = child->parent; | 128 | struct sway_container *parent = child->parent; |
115 | for (i = 0; i < parent->children->length; ++i) { | 129 | for (int i = 0; i < parent->children->length; ++i) { |
116 | if (parent->children->items[i] == child) { | 130 | if (parent->children->items[i] == child) { |
117 | list_del(parent->children, i); | 131 | list_del(parent->children, i); |
118 | break; | 132 | break; |
119 | } | 133 | } |
120 | } | 134 | } |
121 | child->parent = NULL; | 135 | child->parent = NULL; |
122 | return parent; | 136 | return container_reap_empty(parent); |
123 | } | ||
124 | |||
125 | struct sway_container *container_reap_empty(struct sway_container *container) { | ||
126 | if (!sway_assert(container, "reaping null container")) { | ||
127 | return NULL; | ||
128 | } | ||
129 | while (container->children->length == 0 && container->type == C_CONTAINER) { | ||
130 | wlr_log(L_DEBUG, "Container: Destroying container '%p'", container); | ||
131 | struct sway_container *parent = container->parent; | ||
132 | container_destroy(container); | ||
133 | container = parent; | ||
134 | } | ||
135 | return container; | ||
136 | } | 137 | } |
137 | 138 | ||
138 | void container_move_to(struct sway_container* container, | 139 | void container_move_to(struct sway_container* container, |
@@ -145,16 +146,9 @@ void container_move_to(struct sway_container* container, | |||
145 | container->width = container->height = 0; | 146 | container->width = container->height = 0; |
146 | struct sway_container *new_parent = | 147 | struct sway_container *new_parent = |
147 | container_add_sibling(destination, container); | 148 | container_add_sibling(destination, container); |
148 | if (destination->type == C_WORKSPACE) { | 149 | if (old_parent) { |
149 | // If the workspace only has one child after adding one, it | 150 | arrange_windows(old_parent, -1, -1); |
150 | // means that the workspace was just initialized. | ||
151 | // TODO: Consider floating views in this test | ||
152 | if (destination->children->length == 1) { | ||
153 | ipc_event_workspace(NULL, destination, "init"); | ||
154 | } | ||
155 | } | 151 | } |
156 | old_parent = container_reap_empty(old_parent); | ||
157 | arrange_windows(old_parent, -1, -1); | ||
158 | arrange_windows(new_parent, -1, -1); | 152 | arrange_windows(new_parent, -1, -1); |
159 | } | 153 | } |
160 | 154 | ||
diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 00000000..2246cb11 --- /dev/null +++ b/sway/tree/output.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #include "sway/tree/container.h" | ||
2 | #include "sway/tree/layout.h" | ||
3 | #include "sway/output.h" | ||
4 | #include "log.h" | ||
5 | |||
6 | struct sway_container *container_output_destroy(struct sway_container *output) { | ||
7 | if (!sway_assert(output, "cannot destroy null output")) { | ||
8 | return NULL; | ||
9 | } | ||
10 | |||
11 | if (output->children->length > 0) { | ||
12 | // TODO save workspaces when there are no outputs. | ||
13 | // TODO also check if there will ever be no outputs except for exiting | ||
14 | // program | ||
15 | if (root_container.children->length > 1) { | ||
16 | int p = root_container.children->items[0] == output; | ||
17 | // Move workspace from this output to another output | ||
18 | while (output->children->length) { | ||
19 | struct sway_container *child = output->children->items[0]; | ||
20 | container_remove_child(child); | ||
21 | container_add_child(root_container.children->items[p], child); | ||
22 | } | ||
23 | container_sort_workspaces(root_container.children->items[p]); | ||
24 | arrange_windows(root_container.children->items[p], | ||
25 | -1, -1); | ||
26 | } | ||
27 | } | ||
28 | |||
29 | wl_list_remove(&output->sway_output->frame.link); | ||
30 | wl_list_remove(&output->sway_output->destroy.link); | ||
31 | wl_list_remove(&output->sway_output->mode.link); | ||
32 | |||
33 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | ||
34 | container_destroy(output); | ||
35 | return &root_container; | ||
36 | } | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index d5325c31..480ff693 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "sway/tree/container.h" | 3 | #include "sway/tree/container.h" |
4 | #include "sway/tree/layout.h" | 4 | #include "sway/tree/layout.h" |
5 | #include "sway/tree/view.h" | 5 | #include "sway/tree/view.h" |
6 | #include "log.h" | ||
6 | 7 | ||
7 | const char *view_get_title(struct sway_view *view) { | 8 | const char *view_get_title(struct sway_view *view) { |
8 | if (view->iface.get_prop) { | 9 | if (view->iface.get_prop) { |
@@ -94,3 +95,13 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | |||
94 | } | 95 | } |
95 | } | 96 | } |
96 | } | 97 | } |
98 | |||
99 | struct sway_container *container_view_destroy(struct sway_container *view) { | ||
100 | if (!view) { | ||
101 | return NULL; | ||
102 | } | ||
103 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
104 | struct sway_container *parent = container_destroy(view); | ||
105 | arrange_windows(parent, -1, -1); | ||
106 | return parent; | ||
107 | } | ||
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5800ea09..c629f1f1 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -6,9 +6,10 @@ | |||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <strings.h> | 7 | #include <strings.h> |
8 | #include "stringop.h" | 8 | #include "stringop.h" |
9 | #include "sway/tree/container.h" | ||
10 | #include "sway/input/input-manager.h" | 9 | #include "sway/input/input-manager.h" |
11 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
11 | #include "sway/ipc-server.h" | ||
12 | #include "sway/tree/container.h" | ||
12 | #include "sway/tree/workspace.h" | 13 | #include "sway/tree/workspace.h" |
13 | #include "log.h" | 14 | #include "log.h" |
14 | #include "util.h" | 15 | #include "util.h" |
@@ -202,7 +203,48 @@ struct sway_container *workspace_create(const char *name) { | |||
202 | sway_seat_get_focus_inactive(seat, &root_container); | 203 | sway_seat_get_focus_inactive(seat, &root_container); |
203 | parent = focus; | 204 | parent = focus; |
204 | parent = container_parent(parent, C_OUTPUT); | 205 | parent = container_parent(parent, C_OUTPUT); |
205 | return container_workspace_create(parent, name); | 206 | struct sway_container *new_ws = container_workspace_create(parent, name); |
207 | ipc_event_workspace(NULL, new_ws, "init"); | ||
208 | return new_ws; | ||
209 | } | ||
210 | |||
211 | struct sway_container *container_workspace_destroy( | ||
212 | struct sway_container *workspace) { | ||
213 | if (!sway_assert(workspace, "cannot destroy null workspace")) { | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | // Do not destroy this if it's the last workspace on this output | ||
218 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | ||
219 | if (output && output->children->length == 1) { | ||
220 | return NULL; | ||
221 | } | ||
222 | |||
223 | struct sway_container *parent = workspace->parent; | ||
224 | if (workspace->children->length == 0) { | ||
225 | // destroy the WS if there are no children (TODO check for floating) | ||
226 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | ||
227 | ipc_event_workspace(workspace, NULL, "empty"); | ||
228 | } else { | ||
229 | // Move children to a different workspace on this output | ||
230 | struct sway_container *new_workspace = NULL; | ||
231 | // TODO move floating | ||
232 | for (int i = 0; i < output->children->length; i++) { | ||
233 | if (output->children->items[i] != workspace) { | ||
234 | new_workspace = output->children->items[i]; | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", | ||
240 | workspace->name, new_workspace->name); | ||
241 | for (int i = 0; i < workspace->children->length; i++) { | ||
242 | container_move_to(workspace->children->items[i], new_workspace); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | container_destroy(workspace); | ||
247 | return parent; | ||
206 | } | 248 | } |
207 | 249 | ||
208 | /** | 250 | /** |
@@ -343,3 +385,13 @@ bool workspace_switch(struct sway_container *workspace) { | |||
343 | arrange_windows(output, -1, -1); | 385 | arrange_windows(output, -1, -1); |
344 | return true; | 386 | return true; |
345 | } | 387 | } |
388 | |||
389 | bool workspace_is_visible(struct sway_container *ws) { | ||
390 | struct sway_container *output = container_parent(ws, C_OUTPUT); | ||
391 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
392 | struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); | ||
393 | if (focus->type != C_WORKSPACE) { | ||
394 | focus = container_parent(focus, C_WORKSPACE); | ||
395 | } | ||
396 | return focus == ws; | ||
397 | } | ||