diff options
author | emersion <contact@emersion.fr> | 2018-04-04 00:26:31 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-04 00:26:31 -0400 |
commit | dee71871d7a37cfa1e53f3f1f60e6e93d21beda4 (patch) | |
tree | 1565ba1fede2da35b170353f895c34205216dc38 | |
parent | Merge pull request #1722 from swaywm/swaybar-hidpi (diff) | |
parent | fix double free (diff) | |
download | sway-dee71871d7a37cfa1e53f3f1f60e6e93d21beda4.tar.gz sway-dee71871d7a37cfa1e53f3f1f60e6e93d21beda4.tar.zst sway-dee71871d7a37cfa1e53f3f1f60e6e93d21beda4.zip |
Merge pull request #1702 from acrisci/split-containers2
properly close container containers
-rw-r--r-- | include/sway/tree/container.h | 22 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 17 | ||||
-rw-r--r-- | include/sway/tree/output.h | 0 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 2 | ||||
-rw-r--r-- | sway/commands/kill.c | 17 | ||||
-rw-r--r-- | sway/commands/layout.c | 3 | ||||
-rw-r--r-- | sway/commands/move.c | 2 | ||||
-rw-r--r-- | sway/commands/workspace.c | 6 | ||||
-rw-r--r-- | sway/config/output.c | 5 | ||||
-rw-r--r-- | sway/desktop/output.c | 17 | ||||
-rw-r--r-- | sway/input/seat.c | 2 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/tree/container.c | 273 | ||||
-rw-r--r-- | sway/tree/layout.c | 56 | ||||
-rw-r--r-- | sway/tree/output.c | 96 | ||||
-rw-r--r-- | sway/tree/view.c | 17 | ||||
-rw-r--r-- | sway/tree/workspace.c | 124 |
17 files changed, 358 insertions, 303 deletions
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 464f80c4..277165ea 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -91,13 +91,11 @@ struct sway_container { | |||
91 | } events; | 91 | } events; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | // TODO make private and use the container-specific create functions | ||
95 | struct sway_container *container_create(enum sway_container_type type); | 94 | struct sway_container *container_create(enum sway_container_type type); |
96 | 95 | ||
97 | const char *container_type_to_str(enum sway_container_type type); | 96 | const char *container_type_to_str(enum sway_container_type type); |
98 | 97 | ||
99 | // TODO only one container create function and pass the type? | 98 | struct sway_container *output_create( |
100 | struct sway_container *container_output_create( | ||
101 | struct sway_output *sway_output); | 99 | struct sway_output *sway_output); |
102 | 100 | ||
103 | /** | 101 | /** |
@@ -110,35 +108,26 @@ struct sway_container *container_container_create(); | |||
110 | * Create a new output. Outputs are children of the root container and have no | 108 | * Create a new output. Outputs are children of the root container and have no |
111 | * order in the tree structure. | 109 | * order in the tree structure. |
112 | */ | 110 | */ |
113 | struct sway_container *container_output_create(struct sway_output *sway_output); | 111 | struct sway_container *output_create(struct sway_output *sway_output); |
114 | 112 | ||
115 | /** | 113 | /** |
116 | * Create a new workspace container. Workspaces are children of an output | 114 | * Create a new workspace container. Workspaces are children of an output |
117 | * container and are ordered alphabetically by name. | 115 | * container and are ordered alphabetically by name. |
118 | */ | 116 | */ |
119 | struct sway_container *container_workspace_create(struct sway_container *output, const char *name); | 117 | struct sway_container *workspace_create(struct sway_container *output, const char *name); |
120 | 118 | ||
121 | /* | 119 | /* |
122 | * Create a new view container. A view can be a child of a workspace container | 120 | * Create a new view container. A view can be a child of a workspace container |
123 | * or a container container and are rendered in the order and structure of | 121 | * or a container container and are rendered in the order and structure of |
124 | * how they are attached to the tree. | 122 | * how they are attached to the tree. |
125 | */ | 123 | */ |
126 | // TODO view containers should be created in a detached state. | ||
127 | struct sway_container *container_view_create( | 124 | struct sway_container *container_view_create( |
128 | struct sway_container *sibling, struct sway_view *sway_view); | 125 | struct sway_container *sibling, struct sway_view *sway_view); |
129 | 126 | ||
130 | // TODO don't return the parent on destroy | ||
131 | struct sway_container *container_destroy(struct sway_container *container); | 127 | struct sway_container *container_destroy(struct sway_container *container); |
132 | 128 | ||
133 | struct sway_container *container_workspace_destroy(struct sway_container *container); | 129 | struct sway_container *container_close(struct sway_container *container); |
134 | struct sway_container *container_output_destroy(struct sway_container *container); | ||
135 | struct sway_container *container_view_destroy(struct sway_container *container); | ||
136 | 130 | ||
137 | // TODO move to layout.c | ||
138 | struct sway_container *container_set_layout(struct sway_container *container, | ||
139 | enum sway_container_layout layout); | ||
140 | |||
141 | // TODO rename to container_descendants_for_each() | ||
142 | void container_descendants(struct sway_container *root, | 131 | void container_descendants(struct sway_container *root, |
143 | enum sway_container_type type, | 132 | enum sway_container_type type, |
144 | void (*func)(struct sway_container *item, void *data), void *data); | 133 | void (*func)(struct sway_container *item, void *data), void *data); |
@@ -153,7 +142,6 @@ struct sway_container *container_find(struct sway_container *container, | |||
153 | /** | 142 | /** |
154 | * Finds a parent container with the given struct sway_containerype. | 143 | * Finds a parent container with the given struct sway_containerype. |
155 | */ | 144 | */ |
156 | // TODO rename to container_parent_of_type() | ||
157 | struct sway_container *container_parent(struct sway_container *container, | 145 | struct sway_container *container_parent(struct sway_container *container, |
158 | enum sway_container_type type); | 146 | enum sway_container_type type); |
159 | 147 | ||
@@ -190,4 +178,6 @@ bool container_has_anscestor(struct sway_container *container, | |||
190 | bool container_has_child(struct sway_container *con, | 178 | bool container_has_child(struct sway_container *con, |
191 | struct sway_container *child); | 179 | struct sway_container *child); |
192 | 180 | ||
181 | void container_create_notify(struct sway_container *container); | ||
182 | |||
193 | #endif | 183 | #endif |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 8badb244..784dcc9b 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -29,42 +29,37 @@ struct sway_root { | |||
29 | 29 | ||
30 | void layout_init(void); | 30 | void layout_init(void); |
31 | 31 | ||
32 | // TODO move to tree.h | ||
33 | void container_add_child(struct sway_container *parent, | 32 | void container_add_child(struct sway_container *parent, |
34 | struct sway_container *child); | 33 | struct sway_container *child); |
35 | 34 | ||
36 | // TODO move to tree.h | ||
37 | struct sway_container *container_add_sibling(struct sway_container *parent, | 35 | struct sway_container *container_add_sibling(struct sway_container *parent, |
38 | struct sway_container *child); | 36 | struct sway_container *child); |
39 | 37 | ||
40 | // TODO move to tree.h | ||
41 | struct sway_container *container_remove_child(struct sway_container *child); | 38 | struct sway_container *container_remove_child(struct sway_container *child); |
42 | 39 | ||
43 | // TODO PRIVATE in tree.h | 40 | struct sway_container *container_replace_child(struct sway_container *child, |
44 | struct sway_container *container_reap_empty(struct sway_container *container); | 41 | struct sway_container *new_child); |
42 | |||
43 | struct sway_container *container_set_layout(struct sway_container *container, | ||
44 | enum sway_container_layout layout); | ||
45 | 45 | ||
46 | // TODO move to tree.h | ||
47 | void container_move_to(struct sway_container* container, | 46 | void container_move_to(struct sway_container* container, |
48 | struct sway_container* destination); | 47 | struct sway_container* destination); |
49 | 48 | ||
50 | void container_move(struct sway_container *container, | 49 | void container_move(struct sway_container *container, |
51 | enum movement_direction dir, int move_amt); | 50 | enum movement_direction dir, int move_amt); |
52 | 51 | ||
53 | // TODO move to output.c | ||
54 | enum sway_container_layout container_get_default_layout( | 52 | enum sway_container_layout container_get_default_layout( |
55 | struct sway_container *output); | 53 | struct sway_container *con); |
56 | 54 | ||
57 | // TODO move to output.c | ||
58 | void container_sort_workspaces(struct sway_container *output); | 55 | void container_sort_workspaces(struct sway_container *output); |
59 | 56 | ||
60 | void arrange_windows(struct sway_container *container, | 57 | void arrange_windows(struct sway_container *container, |
61 | double width, double height); | 58 | double width, double height); |
62 | 59 | ||
63 | // TODO move to container.h | ||
64 | struct sway_container *container_get_in_direction(struct sway_container | 60 | struct sway_container *container_get_in_direction(struct sway_container |
65 | *container, struct sway_seat *seat, enum movement_direction dir); | 61 | *container, struct sway_seat *seat, enum movement_direction dir); |
66 | 62 | ||
67 | // TODO move to tree.h | ||
68 | struct sway_container *container_split(struct sway_container *child, | 63 | struct sway_container *container_split(struct sway_container *child, |
69 | enum sway_container_layout layout); | 64 | enum sway_container_layout layout); |
70 | 65 | ||
diff --git a/include/sway/tree/output.h b/include/sway/tree/output.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/include/sway/tree/output.h | |||
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 4e4c3450..8d49fefb 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -7,8 +7,6 @@ extern char *prev_workspace_name; | |||
7 | 7 | ||
8 | char *workspace_next_name(const char *output_name); | 8 | char *workspace_next_name(const char *output_name); |
9 | 9 | ||
10 | struct sway_container *workspace_create(const char *name); | ||
11 | |||
12 | bool workspace_switch(struct sway_container *workspace); | 10 | bool workspace_switch(struct sway_container *workspace); |
13 | 11 | ||
14 | struct sway_container *workspace_by_number(const char* name); | 12 | struct sway_container *workspace_by_number(const char* name); |
diff --git a/sway/commands/kill.c b/sway/commands/kill.c index 46d6e98e..f3fa52f1 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c | |||
@@ -10,22 +10,7 @@ struct cmd_results *cmd_kill(int argc, char **argv) { | |||
10 | struct sway_container *con = | 10 | struct sway_container *con = |
11 | config->handler_context.current_container; | 11 | config->handler_context.current_container; |
12 | 12 | ||
13 | switch (con->type) { | 13 | container_close(con); |
14 | case C_ROOT: | ||
15 | case C_OUTPUT: | ||
16 | case C_WORKSPACE: | ||
17 | case C_TYPES: | ||
18 | return cmd_results_new(CMD_INVALID, NULL, | ||
19 | "Can only kill views and containers with this command"); | ||
20 | break; | ||
21 | case C_CONTAINER: | ||
22 | con = container_destroy(con); | ||
23 | arrange_windows(con, -1, -1); | ||
24 | break; | ||
25 | case C_VIEW: | ||
26 | view_close(con->sway_view); | ||
27 | break; | ||
28 | } | ||
29 | 14 | ||
30 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 15 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
31 | } | 16 | } |
diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ebab2a48..4c49a627 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c | |||
@@ -28,8 +28,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { | |||
28 | if (strcasecmp(argv[0], "default") == 0) { | 28 | if (strcasecmp(argv[0], "default") == 0) { |
29 | container_set_layout(parent, parent->prev_layout); | 29 | container_set_layout(parent, parent->prev_layout); |
30 | if (parent->layout == L_NONE) { | 30 | if (parent->layout == L_NONE) { |
31 | struct sway_container *output = container_parent(parent, C_OUTPUT); | 31 | container_set_layout(parent, container_get_default_layout(parent)); |
32 | container_set_layout(parent, container_get_default_layout(output)); | ||
33 | } | 32 | } |
34 | } else { | 33 | } else { |
35 | if (parent->layout != L_TABBED && parent->layout != L_STACKED) { | 34 | if (parent->layout != L_TABBED && parent->layout != L_STACKED) { |
diff --git a/sway/commands/move.c b/sway/commands/move.c index 644c622b..c954ab94 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -74,7 +74,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
74 | ws = workspace_by_name(ws_name); | 74 | ws = workspace_by_name(ws_name); |
75 | } | 75 | } |
76 | if (!ws) { | 76 | if (!ws) { |
77 | ws = workspace_create(ws_name ? ws_name : num_name); | 77 | ws = workspace_create(NULL, ws_name ? ws_name : num_name); |
78 | } | 78 | } |
79 | free(ws_name); | 79 | free(ws_name); |
80 | struct sway_container *old_parent = current->parent; | 80 | struct sway_container *old_parent = current->parent; |
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index aa4096f7..958b3222 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c | |||
@@ -61,7 +61,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
61 | if (strcasecmp(argv[0], "number") == 0) { | 61 | if (strcasecmp(argv[0], "number") == 0) { |
62 | if (!(ws = workspace_by_number(argv[1]))) { | 62 | if (!(ws = workspace_by_number(argv[1]))) { |
63 | char *name = join_args(argv + 1, argc - 1); | 63 | char *name = join_args(argv + 1, argc - 1); |
64 | ws = workspace_create(name); | 64 | ws = workspace_create(NULL, name); |
65 | free(name); | 65 | free(name); |
66 | } | 66 | } |
67 | } else if (strcasecmp(argv[0], "next") == 0) { | 67 | } else if (strcasecmp(argv[0], "next") == 0) { |
@@ -80,12 +80,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { | |||
80 | ws = old_workspace; | 80 | ws = old_workspace; |
81 | } else if (prev_workspace_name | 81 | } else if (prev_workspace_name |
82 | && !(ws = workspace_by_name(prev_workspace_name))) { | 82 | && !(ws = workspace_by_name(prev_workspace_name))) { |
83 | ws = workspace_create(prev_workspace_name); | 83 | ws = workspace_create(NULL, prev_workspace_name); |
84 | } | 84 | } |
85 | } else { | 85 | } else { |
86 | char *name = join_args(argv, argc); | 86 | char *name = join_args(argv, argc); |
87 | if (!(ws = workspace_by_name(name))) { | 87 | if (!(ws = workspace_by_name(name))) { |
88 | ws = workspace_create(name); | 88 | ws = workspace_create(NULL, name); |
89 | } | 89 | } |
90 | free(name); | 90 | free(name); |
91 | } | 91 | } |
diff --git a/sway/config/output.c b/sway/config/output.c index 6d832cbc..1c298d37 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -128,8 +128,9 @@ void apply_output_config(struct output_config *oc, struct sway_container *output | |||
128 | struct wlr_output *wlr_output = output->sway_output->wlr_output; | 128 | struct wlr_output *wlr_output = output->sway_output->wlr_output; |
129 | 129 | ||
130 | if (oc && oc->enabled == 0) { | 130 | if (oc && oc->enabled == 0) { |
131 | container_output_destroy(output); | 131 | container_destroy(output); |
132 | wlr_output_layout_remove(output_layout, wlr_output); | 132 | wlr_output_layout_remove(root_container.sway_root->output_layout, |
133 | wlr_output); | ||
133 | return; | 134 | return; |
134 | } | 135 | } |
135 | 136 | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4b407f41..8a4fb4a2 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <assert.h> | 2 | #include <assert.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <time.h> | 4 | #include <time.h> |
5 | #include <strings.h> | ||
5 | #include <wayland-server.h> | 6 | #include <wayland-server.h> |
6 | #include <wlr/render/wlr_renderer.h> | 7 | #include <wlr/render/wlr_renderer.h> |
7 | #include <wlr/types/wlr_box.h> | 8 | #include <wlr/types/wlr_box.h> |
@@ -21,6 +22,16 @@ | |||
21 | #include "sway/tree/layout.h" | 22 | #include "sway/tree/layout.h" |
22 | #include "sway/tree/view.h" | 23 | #include "sway/tree/view.h" |
23 | 24 | ||
25 | struct sway_container *output_by_name(const char *name) { | ||
26 | for (int i = 0; i < root_container.children->length; ++i) { | ||
27 | struct sway_container *output = root_container.children->items[i]; | ||
28 | if (strcasecmp(output->name, name) == 0) { | ||
29 | return output; | ||
30 | } | ||
31 | } | ||
32 | return NULL; | ||
33 | } | ||
34 | |||
24 | /** | 35 | /** |
25 | * Rotate a child's position relative to a parent. The parent size is (pw, ph), | 36 | * Rotate a child's position relative to a parent. The parent size is (pw, ph), |
26 | * the child position is (*sx, *sy) and its size is (sw, sh). | 37 | * the child position is (*sx, *sy) and its size is (sw, sh). |
@@ -334,12 +345,12 @@ void output_damage_whole_view(struct sway_output *output, | |||
334 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 345 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |
335 | struct sway_output *output = | 346 | struct sway_output *output = |
336 | wl_container_of(listener, output, damage_destroy); | 347 | wl_container_of(listener, output, damage_destroy); |
337 | container_output_destroy(output->swayc); | 348 | container_destroy(output->swayc); |
338 | } | 349 | } |
339 | 350 | ||
340 | static void handle_destroy(struct wl_listener *listener, void *data) { | 351 | static void handle_destroy(struct wl_listener *listener, void *data) { |
341 | struct sway_output *output = wl_container_of(listener, output, destroy); | 352 | struct sway_output *output = wl_container_of(listener, output, destroy); |
342 | container_output_destroy(output->swayc); | 353 | container_destroy(output->swayc); |
343 | } | 354 | } |
344 | 355 | ||
345 | static void handle_mode(struct wl_listener *listener, void *data) { | 356 | static void handle_mode(struct wl_listener *listener, void *data) { |
@@ -381,7 +392,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
381 | 392 | ||
382 | output->damage = wlr_output_damage_create(wlr_output); | 393 | output->damage = wlr_output_damage_create(wlr_output); |
383 | 394 | ||
384 | output->swayc = container_output_create(output); | 395 | output->swayc = output_create(output); |
385 | if (!output->swayc) { | 396 | if (!output->swayc) { |
386 | free(output); | 397 | free(output); |
387 | return; | 398 | return; |
diff --git a/sway/input/seat.c b/sway/input/seat.c index cf519a82..4a99e9eb 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -384,7 +384,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
384 | if (last_ws) { | 384 | if (last_ws) { |
385 | ipc_event_workspace(last_ws, container, "focus"); | 385 | ipc_event_workspace(last_ws, container, "focus"); |
386 | if (last_ws->children->length == 0) { | 386 | if (last_ws->children->length == 0) { |
387 | container_workspace_destroy(last_ws); | 387 | container_destroy(last_ws); |
388 | } | 388 | } |
389 | } | 389 | } |
390 | struct sway_container *last_output = last_focus; | 390 | struct sway_container *last_output = last_focus; |
diff --git a/sway/meson.build b/sway/meson.build index a6a633a0..91aab0a0 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -86,9 +86,9 @@ sway_sources = files( | |||
86 | 'security.c', | 86 | 'security.c', |
87 | 'tree/container.c', | 87 | 'tree/container.c', |
88 | 'tree/layout.c', | 88 | 'tree/layout.c', |
89 | 'tree/output.c', | ||
90 | 'tree/view.c', | 89 | 'tree/view.c', |
91 | 'tree/workspace.c', | 90 | 'tree/workspace.c', |
91 | 'tree/output.c', | ||
92 | ) | 92 | ) |
93 | 93 | ||
94 | sway_deps = [ | 94 | sway_deps = [ |
diff --git a/sway/tree/container.c b/sway/tree/container.c index c686401c..eaf4c117 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | ||
2 | #include <stdint.h> | 3 | #include <stdint.h> |
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
4 | #include <string.h> | 5 | #include <string.h> |
@@ -6,7 +7,6 @@ | |||
6 | #include <wayland-server.h> | 7 | #include <wayland-server.h> |
7 | #include <wlr/types/wlr_output_layout.h> | 8 | #include <wlr/types/wlr_output_layout.h> |
8 | #include <wlr/types/wlr_wl_shell.h> | 9 | #include <wlr/types/wlr_wl_shell.h> |
9 | #include "log.h" | ||
10 | #include "sway/config.h" | 10 | #include "sway/config.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" |
@@ -50,7 +50,7 @@ const char *container_type_to_str(enum sway_container_type type) { | |||
50 | } | 50 | } |
51 | } | 51 | } |
52 | 52 | ||
53 | static void notify_new_container(struct sway_container *container) { | 53 | void container_create_notify(struct sway_container *container) { |
54 | wl_signal_emit(&root_container.sway_root->events.new_container, container); | 54 | wl_signal_emit(&root_container.sway_root->events.new_container, container); |
55 | ipc_event_window(container, "new"); | 55 | ipc_event_window(container, "new"); |
56 | } | 56 | } |
@@ -76,21 +76,21 @@ struct sway_container *container_create(enum sway_container_type type) { | |||
76 | return c; | 76 | return c; |
77 | } | 77 | } |
78 | 78 | ||
79 | static struct sway_container *_container_destroy(struct sway_container *cont) { | 79 | static void _container_destroy(struct sway_container *cont) { |
80 | if (cont == NULL) { | 80 | if (cont == NULL) { |
81 | return NULL; | 81 | return; |
82 | } | 82 | } |
83 | 83 | ||
84 | wl_signal_emit(&cont->events.destroy, cont); | 84 | wl_signal_emit(&cont->events.destroy, cont); |
85 | 85 | ||
86 | struct sway_container *parent = cont->parent; | 86 | struct sway_container *parent = cont->parent; |
87 | if (cont->children != NULL) { | 87 | if (cont->children != NULL && cont->children->length) { |
88 | // remove children until there are no more, container_destroy calls | 88 | // remove children until there are no more, container_destroy calls |
89 | // container_remove_child, which removes child from this container | 89 | // container_remove_child, which removes child from this container |
90 | while (cont->children != NULL && cont->children->length != 0) { | 90 | while (cont->children != NULL) { |
91 | struct sway_container *child = cont->children->items[0]; | 91 | struct sway_container *child = cont->children->items[0]; |
92 | container_remove_child(child); | 92 | container_remove_child(child); |
93 | container_destroy(child); | 93 | _container_destroy(child); |
94 | } | 94 | } |
95 | } | 95 | } |
96 | if (cont->marks) { | 96 | if (cont->marks) { |
@@ -106,106 +106,200 @@ static struct sway_container *_container_destroy(struct sway_container *cont) { | |||
106 | list_free(cont->children); | 106 | list_free(cont->children); |
107 | cont->children = NULL; | 107 | cont->children = NULL; |
108 | free(cont); | 108 | free(cont); |
109 | return parent; | ||
110 | } | 109 | } |
111 | 110 | ||
112 | struct sway_container *container_destroy(struct sway_container *cont) { | 111 | static struct sway_container *container_output_destroy( |
113 | struct sway_container *parent = _container_destroy(cont); | 112 | struct sway_container *output) { |
114 | parent = container_reap_empty(parent); | 113 | if (!sway_assert(output, "cannot destroy null output")) { |
115 | arrange_windows(&root_container, -1, -1); | 114 | return NULL; |
116 | return parent; | 115 | } |
117 | } | 116 | |
117 | if (output->children->length > 0) { | ||
118 | // TODO save workspaces when there are no outputs. | ||
119 | // TODO also check if there will ever be no outputs except for exiting | ||
120 | // program | ||
121 | if (root_container.children->length > 1) { | ||
122 | int p = root_container.children->items[0] == output; | ||
123 | // Move workspace from this output to another output | ||
124 | while (output->children->length) { | ||
125 | struct sway_container *child = output->children->items[0]; | ||
126 | container_remove_child(child); | ||
127 | container_add_child(root_container.children->items[p], child); | ||
128 | } | ||
129 | container_sort_workspaces(root_container.children->items[p]); | ||
130 | arrange_windows(root_container.children->items[p], | ||
131 | -1, -1); | ||
132 | } | ||
133 | } | ||
118 | 134 | ||
119 | struct sway_container *container_output_create( | 135 | wl_list_remove(&output->sway_output->destroy.link); |
120 | struct sway_output *sway_output) { | 136 | wl_list_remove(&output->sway_output->mode.link); |
121 | struct wlr_box size; | 137 | wl_list_remove(&output->sway_output->transform.link); |
122 | wlr_output_effective_resolution(sway_output->wlr_output, &size.width, | 138 | wl_list_remove(&output->sway_output->scale.link); |
123 | &size.height); | ||
124 | 139 | ||
125 | const char *name = sway_output->wlr_output->name; | 140 | wl_list_remove(&output->sway_output->damage_destroy.link); |
126 | char identifier[128]; | 141 | wl_list_remove(&output->sway_output->damage_frame.link); |
127 | output_get_identifier(identifier, sizeof(identifier), sway_output); | ||
128 | 142 | ||
129 | struct output_config *oc = NULL, *all = NULL; | 143 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); |
130 | for (int i = 0; i < config->output_configs->length; ++i) { | 144 | _container_destroy(output); |
131 | struct output_config *cur = config->output_configs->items[i]; | 145 | return &root_container; |
146 | } | ||
132 | 147 | ||
133 | if (strcasecmp(name, cur->name) == 0 || | 148 | static struct sway_container *container_workspace_destroy( |
134 | strcasecmp(identifier, cur->name) == 0) { | 149 | struct sway_container *workspace) { |
135 | wlr_log(L_DEBUG, "Matched output config for %s", name); | 150 | if (!sway_assert(workspace, "cannot destroy null workspace")) { |
136 | oc = cur; | 151 | return NULL; |
137 | } | 152 | } |
138 | if (strcasecmp("*", cur->name) == 0) { | 153 | |
139 | wlr_log(L_DEBUG, "Matched wildcard output config for %s", name); | 154 | // Do not destroy this if it's the last workspace on this output |
140 | all = cur; | 155 | struct sway_container *output = container_parent(workspace, C_OUTPUT); |
156 | if (output && output->children->length == 1) { | ||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | struct sway_container *parent = workspace->parent; | ||
161 | if (workspace->children->length == 0) { | ||
162 | // destroy the WS if there are no children (TODO check for floating) | ||
163 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | ||
164 | ipc_event_workspace(workspace, NULL, "empty"); | ||
165 | } else { | ||
166 | // Move children to a different workspace on this output | ||
167 | struct sway_container *new_workspace = NULL; | ||
168 | // TODO move floating | ||
169 | for (int i = 0; i < output->children->length; i++) { | ||
170 | if (output->children->items[i] != workspace) { | ||
171 | new_workspace = output->children->items[i]; | ||
172 | break; | ||
173 | } | ||
141 | } | 174 | } |
142 | 175 | ||
143 | if (oc && all) { | 176 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", |
144 | break; | 177 | workspace->name, new_workspace->name); |
178 | for (int i = 0; i < workspace->children->length; i++) { | ||
179 | container_move_to(workspace->children->items[i], new_workspace); | ||
145 | } | 180 | } |
146 | } | 181 | } |
147 | if (!oc) { | ||
148 | oc = all; | ||
149 | } | ||
150 | 182 | ||
151 | if (oc && !oc->enabled) { | 183 | _container_destroy(workspace); |
152 | return NULL; | 184 | |
185 | output_damage_whole(output->sway_output); | ||
186 | |||
187 | return parent; | ||
188 | } | ||
189 | |||
190 | static void container_root_finish(struct sway_container *con) { | ||
191 | wlr_log(L_ERROR, "TODO: destroy the root container"); | ||
192 | } | ||
193 | |||
194 | static bool container_reap_empty(struct sway_container *con) { | ||
195 | switch (con->type) { | ||
196 | case C_ROOT: | ||
197 | case C_OUTPUT: | ||
198 | // dont reap these | ||
199 | break; | ||
200 | case C_WORKSPACE: | ||
201 | if (!workspace_is_visible(con) && con->children->length == 0) { | ||
202 | container_workspace_destroy(con); | ||
203 | return true; | ||
204 | } | ||
205 | break; | ||
206 | case C_CONTAINER: | ||
207 | if (con->children->length == 0) { | ||
208 | _container_destroy(con); | ||
209 | return true; | ||
210 | } else if (con->children->length == 1) { | ||
211 | struct sway_container *child = con->children->items[0]; | ||
212 | if (child->type == C_CONTAINER) { | ||
213 | container_remove_child(child); | ||
214 | container_replace_child(con, child); | ||
215 | _container_destroy(con); | ||
216 | return true; | ||
217 | } | ||
218 | } | ||
219 | case C_VIEW: | ||
220 | break; | ||
221 | case C_TYPES: | ||
222 | sway_assert(false, "container_reap_empty called on an invalid " | ||
223 | "container"); | ||
224 | break; | ||
153 | } | 225 | } |
154 | 226 | ||
155 | struct sway_container *output = container_create(C_OUTPUT); | 227 | return false; |
156 | output->sway_output = sway_output; | 228 | } |
157 | output->name = strdup(name); | 229 | |
158 | if (output->name == NULL) { | 230 | struct sway_container *container_destroy(struct sway_container *con) { |
159 | container_destroy(output); | 231 | if (con == NULL) { |
160 | return NULL; | 232 | return NULL; |
161 | } | 233 | } |
162 | 234 | ||
163 | // Insert the child before applying config so that the container coordinates | 235 | struct sway_container *parent = con->parent; |
164 | // get updated | 236 | |
165 | container_add_child(&root_container, output); | 237 | switch (con->type) { |
166 | apply_output_config(oc, output); | 238 | case C_ROOT: |
239 | container_root_finish(con); | ||
240 | break; | ||
241 | case C_OUTPUT: | ||
242 | // dont try to reap the root after this | ||
243 | container_output_destroy(con); | ||
244 | break; | ||
245 | case C_WORKSPACE: | ||
246 | // dont try to reap the output after this | ||
247 | container_workspace_destroy(con); | ||
248 | break; | ||
249 | case C_CONTAINER: | ||
250 | if (con->children->length) { | ||
251 | for (int i = 0; i < con->children->length; ++i) { | ||
252 | struct sway_container *child = con->children->items[0]; | ||
253 | container_remove_child(child); | ||
254 | container_add_child(parent, child); | ||
255 | } | ||
256 | } | ||
257 | _container_destroy(con); | ||
258 | break; | ||
259 | case C_VIEW: | ||
260 | _container_destroy(con); | ||
261 | break; | ||
262 | case C_TYPES: | ||
263 | wlr_log(L_ERROR, "container_destroy called on an invalid " | ||
264 | "container"); | ||
265 | break; | ||
266 | } | ||
167 | 267 | ||
168 | load_swaybars(); | 268 | struct sway_container *tmp = parent; |
269 | while (parent) { | ||
270 | tmp = parent->parent; | ||
169 | 271 | ||
170 | // Create workspace | 272 | if (!container_reap_empty(parent)) { |
171 | char *ws_name = workspace_next_name(output->name); | 273 | break; |
172 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); | ||
173 | struct sway_container *ws = container_workspace_create(output, ws_name); | ||
174 | // Set each seat's focus if not already set | ||
175 | struct sway_seat *seat = NULL; | ||
176 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
177 | if (!seat->has_focus) { | ||
178 | seat_set_focus(seat, ws); | ||
179 | } | 274 | } |
275 | |||
276 | parent = tmp; | ||
180 | } | 277 | } |
181 | 278 | ||
182 | free(ws_name); | 279 | return tmp; |
183 | notify_new_container(output); | 280 | } |
184 | return output; | 281 | |
282 | static void container_close_func(struct sway_container *container, void *data) { | ||
283 | if (container->type == C_VIEW) { | ||
284 | view_close(container->sway_view); | ||
285 | } | ||
185 | } | 286 | } |
186 | 287 | ||
187 | struct sway_container *container_workspace_create( | 288 | struct sway_container *container_close(struct sway_container *con) { |
188 | struct sway_container *output, const char *name) { | 289 | if (!sway_assert(con != NULL, |
189 | if (!sway_assert(output, | 290 | "container_close called with a NULL container")) { |
190 | "container_workspace_create called with null output")) { | ||
191 | return NULL; | 291 | return NULL; |
192 | } | 292 | } |
193 | wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); | 293 | |
194 | struct sway_container *workspace = container_create(C_WORKSPACE); | 294 | struct sway_container *parent = con->parent; |
195 | 295 | ||
196 | workspace->x = output->x; | 296 | if (con->type == C_VIEW) { |
197 | workspace->y = output->y; | 297 | view_close(con->sway_view); |
198 | workspace->width = output->width; | 298 | } else { |
199 | workspace->height = output->height; | 299 | container_for_each_descendant_dfs(con, container_close_func, NULL); |
200 | workspace->name = !name ? NULL : strdup(name); | 300 | } |
201 | workspace->prev_layout = L_NONE; | 301 | |
202 | workspace->layout = container_get_default_layout(output); | 302 | return parent; |
203 | workspace->workspace_layout = container_get_default_layout(output); | ||
204 | |||
205 | container_add_child(output, workspace); | ||
206 | container_sort_workspaces(output); | ||
207 | notify_new_container(workspace); | ||
208 | return workspace; | ||
209 | } | 303 | } |
210 | 304 | ||
211 | struct sway_container *container_view_create(struct sway_container *sibling, | 305 | struct sway_container *container_view_create(struct sway_container *sibling, |
@@ -231,23 +325,10 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
231 | // Regular case, create as sibling of current container | 325 | // Regular case, create as sibling of current container |
232 | container_add_sibling(sibling, swayc); | 326 | container_add_sibling(sibling, swayc); |
233 | } | 327 | } |
234 | notify_new_container(swayc); | 328 | container_create_notify(swayc); |
235 | return swayc; | 329 | return swayc; |
236 | } | 330 | } |
237 | 331 | ||
238 | struct sway_container *container_set_layout(struct sway_container *container, | ||
239 | enum sway_container_layout layout) { | ||
240 | if (container->type == C_WORKSPACE) { | ||
241 | container->workspace_layout = layout; | ||
242 | if (layout == L_HORIZ || layout == L_VERT) { | ||
243 | container->layout = layout; | ||
244 | } | ||
245 | } else { | ||
246 | container->layout = layout; | ||
247 | } | ||
248 | return container; | ||
249 | } | ||
250 | |||
251 | void container_descendants(struct sway_container *root, | 332 | void container_descendants(struct sway_container *root, |
252 | enum sway_container_type type, | 333 | enum sway_container_type type, |
253 | void (*func)(struct sway_container *item, void *data), void *data) { | 334 | void (*func)(struct sway_container *item, void *data), void *data) { |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 617350d9..5abdbc32 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <assert.h> | ||
3 | #include <ctype.h> | 2 | #include <ctype.h> |
4 | #include <math.h> | 3 | #include <math.h> |
5 | #include <stdbool.h> | 4 | #include <stdbool.h> |
@@ -52,6 +51,19 @@ static void output_layout_handle_change(struct wl_listener *listener, | |||
52 | arrange_windows(&root_container, -1, -1); | 51 | arrange_windows(&root_container, -1, -1); |
53 | } | 52 | } |
54 | 53 | ||
54 | struct sway_container *container_set_layout(struct sway_container *container, | ||
55 | enum sway_container_layout layout) { | ||
56 | if (container->type == C_WORKSPACE) { | ||
57 | container->workspace_layout = layout; | ||
58 | if (layout == L_HORIZ || layout == L_VERT) { | ||
59 | container->layout = layout; | ||
60 | } | ||
61 | } else { | ||
62 | container->layout = layout; | ||
63 | } | ||
64 | return container; | ||
65 | } | ||
66 | |||
55 | void layout_init(void) { | 67 | void layout_init(void) { |
56 | root_container.id = 0; // normally assigned in new_swayc() | 68 | root_container.id = 0; // normally assigned in new_swayc() |
57 | root_container.type = C_ROOT; | 69 | root_container.type = C_ROOT; |
@@ -107,32 +119,6 @@ void container_add_child(struct sway_container *parent, | |||
107 | child->parent = parent; | 119 | child->parent = parent; |
108 | } | 120 | } |
109 | 121 | ||
110 | struct sway_container *container_reap_empty(struct sway_container *container) { | ||
111 | if (container == NULL) { | ||
112 | return NULL; | ||
113 | } | ||
114 | wlr_log(L_DEBUG, "Reaping %p %s '%s'", container, | ||
115 | container_type_to_str(container->type), container->name); | ||
116 | while (container->type != C_ROOT && container->type != C_OUTPUT | ||
117 | && container->children->length == 0) { | ||
118 | if (container->type == C_WORKSPACE) { | ||
119 | if (!workspace_is_visible(container)) { | ||
120 | struct sway_container *parent = container->parent; | ||
121 | container_workspace_destroy(container); | ||
122 | return parent; | ||
123 | } | ||
124 | return container; | ||
125 | } else if (container->type == C_CONTAINER) { | ||
126 | struct sway_container *parent = container->parent; | ||
127 | container_destroy(container); | ||
128 | container = parent; | ||
129 | } else { | ||
130 | container = container->parent; | ||
131 | } | ||
132 | } | ||
133 | return container; | ||
134 | } | ||
135 | |||
136 | struct sway_container *container_remove_child(struct sway_container *child) { | 122 | struct sway_container *container_remove_child(struct sway_container *child) { |
137 | struct sway_container *parent = child->parent; | 123 | struct sway_container *parent = child->parent; |
138 | for (int i = 0; i < parent->children->length; ++i) { | 124 | for (int i = 0; i < parent->children->length; ++i) { |
@@ -167,7 +153,7 @@ void container_move_to(struct sway_container *container, | |||
167 | if (old_parent->children->length == 0) { | 153 | if (old_parent->children->length == 0) { |
168 | char *ws_name = workspace_next_name(old_parent->name); | 154 | char *ws_name = workspace_next_name(old_parent->name); |
169 | struct sway_container *ws = | 155 | struct sway_container *ws = |
170 | container_workspace_create(old_parent, ws_name); | 156 | workspace_create(old_parent, ws_name); |
171 | free(ws_name); | 157 | free(ws_name); |
172 | seat_set_focus(seat, ws); | 158 | seat_set_focus(seat, ws); |
173 | } | 159 | } |
@@ -186,12 +172,22 @@ void container_move(struct sway_container *container, | |||
186 | } | 172 | } |
187 | 173 | ||
188 | enum sway_container_layout container_get_default_layout( | 174 | enum sway_container_layout container_get_default_layout( |
189 | struct sway_container *output) { | 175 | struct sway_container *con) { |
176 | if (con->type != C_OUTPUT) { | ||
177 | con = container_parent(con, C_OUTPUT); | ||
178 | } | ||
179 | |||
180 | if (!sway_assert(con != NULL, | ||
181 | "container_get_default_layout must be called on an attached" | ||
182 | " container below the root container")) { | ||
183 | return 0; | ||
184 | } | ||
185 | |||
190 | if (config->default_layout != L_NONE) { | 186 | if (config->default_layout != L_NONE) { |
191 | return config->default_layout; | 187 | return config->default_layout; |
192 | } else if (config->default_orientation != L_NONE) { | 188 | } else if (config->default_orientation != L_NONE) { |
193 | return config->default_orientation; | 189 | return config->default_orientation; |
194 | } else if (output->width >= output->height) { | 190 | } else if (con->width >= con->height) { |
195 | return L_HORIZ; | 191 | return L_HORIZ; |
196 | } else { | 192 | } else { |
197 | return L_VERT; | 193 | return L_VERT; |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 0509db23..6c7044a2 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -1,51 +1,73 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <string.h> | ||
1 | #include <strings.h> | 3 | #include <strings.h> |
2 | #include "sway/tree/container.h" | ||
3 | #include "sway/tree/layout.h" | ||
4 | #include "sway/output.h" | 4 | #include "sway/output.h" |
5 | #include "sway/tree/output.h" | ||
6 | #include "sway/tree/workspace.h" | ||
5 | #include "log.h" | 7 | #include "log.h" |
6 | 8 | ||
7 | struct sway_container *container_output_destroy(struct sway_container *output) { | 9 | struct sway_container *output_create( |
8 | if (!sway_assert(output, "cannot destroy null output")) { | 10 | struct sway_output *sway_output) { |
9 | return NULL; | 11 | struct wlr_box size; |
10 | } | 12 | wlr_output_effective_resolution(sway_output->wlr_output, &size.width, |
13 | &size.height); | ||
14 | |||
15 | const char *name = sway_output->wlr_output->name; | ||
16 | char identifier[128]; | ||
17 | output_get_identifier(identifier, sizeof(identifier), sway_output); | ||
18 | |||
19 | struct output_config *oc = NULL, *all = NULL; | ||
20 | for (int i = 0; i < config->output_configs->length; ++i) { | ||
21 | struct output_config *cur = config->output_configs->items[i]; | ||
11 | 22 | ||
12 | if (output->children->length > 0) { | 23 | if (strcasecmp(name, cur->name) == 0 || |
13 | // TODO save workspaces when there are no outputs. | 24 | strcasecmp(identifier, cur->name) == 0) { |
14 | // TODO also check if there will ever be no outputs except for exiting | 25 | wlr_log(L_DEBUG, "Matched output config for %s", name); |
15 | // program | 26 | oc = cur; |
16 | if (root_container.children->length > 1) { | ||
17 | int p = root_container.children->items[0] == output; | ||
18 | // Move workspace from this output to another output | ||
19 | while (output->children->length) { | ||
20 | struct sway_container *child = output->children->items[0]; | ||
21 | container_remove_child(child); | ||
22 | container_add_child(root_container.children->items[p], child); | ||
23 | } | ||
24 | container_sort_workspaces(root_container.children->items[p]); | ||
25 | arrange_windows(root_container.children->items[p], | ||
26 | -1, -1); | ||
27 | } | 27 | } |
28 | if (strcasecmp("*", cur->name) == 0) { | ||
29 | wlr_log(L_DEBUG, "Matched wildcard output config for %s", name); | ||
30 | all = cur; | ||
31 | } | ||
32 | |||
33 | if (oc && all) { | ||
34 | break; | ||
35 | } | ||
36 | } | ||
37 | if (!oc) { | ||
38 | oc = all; | ||
28 | } | 39 | } |
29 | 40 | ||
30 | wl_list_remove(&output->sway_output->destroy.link); | 41 | if (oc && !oc->enabled) { |
31 | wl_list_remove(&output->sway_output->mode.link); | 42 | return NULL; |
32 | wl_list_remove(&output->sway_output->transform.link); | 43 | } |
33 | wl_list_remove(&output->sway_output->scale.link); | ||
34 | 44 | ||
35 | wl_list_remove(&output->sway_output->damage_destroy.link); | 45 | struct sway_container *output = container_create(C_OUTPUT); |
36 | wl_list_remove(&output->sway_output->damage_frame.link); | 46 | output->sway_output = sway_output; |
47 | output->name = strdup(name); | ||
48 | if (output->name == NULL) { | ||
49 | container_destroy(output); | ||
50 | return NULL; | ||
51 | } | ||
37 | 52 | ||
38 | wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); | 53 | apply_output_config(oc, output); |
39 | container_destroy(output); | 54 | container_add_child(&root_container, output); |
40 | return &root_container; | 55 | load_swaybars(); |
41 | } | ||
42 | 56 | ||
43 | struct sway_container *output_by_name(const char *name) { | 57 | // Create workspace |
44 | for (int i = 0; i < root_container.children->length; ++i) { | 58 | char *ws_name = workspace_next_name(output->name); |
45 | struct sway_container *output = root_container.children->items[i]; | 59 | wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); |
46 | if (strcasecmp(output->name, name) == 0){ | 60 | struct sway_container *ws = workspace_create(output, ws_name); |
47 | return output; | 61 | // Set each seat's focus if not already set |
62 | struct sway_seat *seat = NULL; | ||
63 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
64 | if (!seat->has_focus) { | ||
65 | seat_set_focus(seat, ws); | ||
48 | } | 66 | } |
49 | } | 67 | } |
50 | return NULL; | 68 | |
69 | free(ws_name); | ||
70 | container_create_notify(output); | ||
71 | return output; | ||
51 | } | 72 | } |
73 | |||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 09c804e4..aa010a40 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -27,8 +27,7 @@ void view_destroy(struct sway_view *view) { | |||
27 | view_unmap(view); | 27 | view_unmap(view); |
28 | } | 28 | } |
29 | 29 | ||
30 | container_view_destroy(view->swayc); | 30 | container_destroy(view->swayc); |
31 | free(view); | ||
32 | } | 31 | } |
33 | 32 | ||
34 | const char *view_get_title(struct sway_view *view) { | 33 | const char *view_get_title(struct sway_view *view) { |
@@ -78,16 +77,6 @@ void view_close(struct sway_view *view) { | |||
78 | } | 77 | } |
79 | } | 78 | } |
80 | 79 | ||
81 | struct sway_container *container_view_destroy(struct sway_container *view) { | ||
82 | if (!view) { | ||
83 | return NULL; | ||
84 | } | ||
85 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
86 | struct sway_container *parent = container_destroy(view); | ||
87 | arrange_windows(parent, -1, -1); | ||
88 | return parent; | ||
89 | } | ||
90 | |||
91 | void view_damage_whole(struct sway_view *view) { | 80 | void view_damage_whole(struct sway_view *view) { |
92 | for (int i = 0; i < root_container.children->length; ++i) { | 81 | for (int i = 0; i < root_container.children->length; ++i) { |
93 | struct sway_container *cont = root_container.children->items[i]; | 82 | struct sway_container *cont = root_container.children->items[i]; |
@@ -160,10 +149,12 @@ void view_unmap(struct sway_view *view) { | |||
160 | 149 | ||
161 | view_damage_whole(view); | 150 | view_damage_whole(view); |
162 | 151 | ||
163 | container_view_destroy(view->swayc); | 152 | struct sway_container *parent = container_destroy(view->swayc); |
164 | 153 | ||
165 | view->swayc = NULL; | 154 | view->swayc = NULL; |
166 | view->surface = NULL; | 155 | view->surface = NULL; |
156 | |||
157 | arrange_windows(parent, -1, -1); | ||
167 | } | 158 | } |
168 | 159 | ||
169 | void view_update_position(struct sway_view *view, double ox, double oy) { | 160 | void view_update_position(struct sway_view *view, double ox, double oy) { |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 8077de2e..316f01e4 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -14,6 +14,58 @@ | |||
14 | #include "log.h" | 14 | #include "log.h" |
15 | #include "util.h" | 15 | #include "util.h" |
16 | 16 | ||
17 | static struct sway_container *get_workspace_initial_output(const char *name) { | ||
18 | struct sway_container *parent; | ||
19 | // Search for workspace<->output pair | ||
20 | int e = config->workspace_outputs->length; | ||
21 | for (int i = 0; i < config->workspace_outputs->length; ++i) { | ||
22 | struct workspace_output *wso = config->workspace_outputs->items[i]; | ||
23 | if (strcasecmp(wso->workspace, name) == 0) { | ||
24 | // Find output to use if it exists | ||
25 | e = root_container.children->length; | ||
26 | for (i = 0; i < e; ++i) { | ||
27 | parent = root_container.children->items[i]; | ||
28 | if (strcmp(parent->name, wso->output) == 0) { | ||
29 | return parent; | ||
30 | } | ||
31 | } | ||
32 | break; | ||
33 | } | ||
34 | } | ||
35 | // Otherwise put it on the focused output | ||
36 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
37 | struct sway_container *focus = | ||
38 | seat_get_focus_inactive(seat, &root_container); | ||
39 | parent = focus; | ||
40 | parent = container_parent(parent, C_OUTPUT); | ||
41 | return parent; | ||
42 | } | ||
43 | |||
44 | struct sway_container *workspace_create(struct sway_container *output, | ||
45 | const char *name) { | ||
46 | if (output == NULL) { | ||
47 | output = get_workspace_initial_output(name); | ||
48 | } | ||
49 | |||
50 | wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); | ||
51 | struct sway_container *workspace = container_create(C_WORKSPACE); | ||
52 | |||
53 | workspace->x = output->x; | ||
54 | workspace->y = output->y; | ||
55 | workspace->width = output->width; | ||
56 | workspace->height = output->height; | ||
57 | workspace->name = !name ? NULL : strdup(name); | ||
58 | workspace->prev_layout = L_NONE; | ||
59 | workspace->layout = container_get_default_layout(output); | ||
60 | workspace->workspace_layout = workspace->layout; | ||
61 | |||
62 | container_add_child(output, workspace); | ||
63 | container_sort_workspaces(output); | ||
64 | container_create_notify(workspace); | ||
65 | |||
66 | return workspace; | ||
67 | } | ||
68 | |||
17 | char *prev_workspace_name = NULL; | 69 | char *prev_workspace_name = NULL; |
18 | struct workspace_by_number_data { | 70 | struct workspace_by_number_data { |
19 | int len; | 71 | int len; |
@@ -197,74 +249,6 @@ struct sway_container *workspace_by_name(const char *name) { | |||
197 | } | 249 | } |
198 | } | 250 | } |
199 | 251 | ||
200 | struct sway_container *workspace_create(const char *name) { | ||
201 | struct sway_container *parent; | ||
202 | // Search for workspace<->output pair | ||
203 | int i, e = config->workspace_outputs->length; | ||
204 | for (i = 0; i < e; ++i) { | ||
205 | struct workspace_output *wso = config->workspace_outputs->items[i]; | ||
206 | if (strcasecmp(wso->workspace, name) == 0) { | ||
207 | // Find output to use if it exists | ||
208 | e = root_container.children->length; | ||
209 | for (i = 0; i < e; ++i) { | ||
210 | parent = root_container.children->items[i]; | ||
211 | if (strcmp(parent->name, wso->output) == 0) { | ||
212 | return container_workspace_create(parent, name); | ||
213 | } | ||
214 | } | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | // Otherwise create a new one | ||
219 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
220 | struct sway_container *focus = | ||
221 | seat_get_focus_inactive(seat, &root_container); | ||
222 | parent = focus; | ||
223 | parent = container_parent(parent, C_OUTPUT); | ||
224 | struct sway_container *new_ws = container_workspace_create(parent, name); | ||
225 | ipc_event_workspace(NULL, new_ws, "init"); | ||
226 | return new_ws; | ||
227 | } | ||
228 | |||
229 | struct sway_container *container_workspace_destroy( | ||
230 | struct sway_container *workspace) { | ||
231 | if (!sway_assert(workspace, "cannot destroy null workspace")) { | ||
232 | return NULL; | ||
233 | } | ||
234 | |||
235 | // Do not destroy this if it's the last workspace on this output | ||
236 | struct sway_container *output = container_parent(workspace, C_OUTPUT); | ||
237 | if (output && output->children->length == 1) { | ||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | struct sway_container *parent = workspace->parent; | ||
242 | if (workspace->children->length == 0) { | ||
243 | // destroy the WS if there are no children (TODO check for floating) | ||
244 | wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); | ||
245 | ipc_event_workspace(workspace, NULL, "empty"); | ||
246 | } else { | ||
247 | // Move children to a different workspace on this output | ||
248 | struct sway_container *new_workspace = NULL; | ||
249 | // TODO move floating | ||
250 | for (int i = 0; i < output->children->length; i++) { | ||
251 | if (output->children->items[i] != workspace) { | ||
252 | new_workspace = output->children->items[i]; | ||
253 | break; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", | ||
258 | workspace->name, new_workspace->name); | ||
259 | for (int i = 0; i < workspace->children->length; i++) { | ||
260 | container_move_to(workspace->children->items[i], new_workspace); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | container_destroy(workspace); | ||
265 | return parent; | ||
266 | } | ||
267 | |||
268 | /** | 252 | /** |
269 | * Get the previous or next workspace on the specified output. Wraps around at | 253 | * Get the previous or next workspace on the specified output. Wraps around at |
270 | * the end and beginning. If next is false, the previous workspace is returned, | 254 | * the end and beginning. If next is false, the previous workspace is returned, |
@@ -376,7 +360,9 @@ bool workspace_switch(struct sway_container *workspace) { | |||
376 | && active_ws == workspace | 360 | && active_ws == workspace |
377 | && prev_workspace_name) { | 361 | && prev_workspace_name) { |
378 | struct sway_container *new_ws = workspace_by_name(prev_workspace_name); | 362 | struct sway_container *new_ws = workspace_by_name(prev_workspace_name); |
379 | workspace = new_ws ? new_ws : workspace_create(prev_workspace_name); | 363 | workspace = new_ws ? |
364 | new_ws : | ||
365 | workspace_create(NULL, prev_workspace_name); | ||
380 | } | 366 | } |
381 | 367 | ||
382 | if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) | 368 | if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name) |