diff options
-rw-r--r-- | include/sway/scratchpad.h | 26 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 23 | ||||
-rw-r--r-- | include/sway/tree/root.h | 57 | ||||
-rw-r--r-- | sway/commands/move.c | 5 | ||||
-rw-r--r-- | sway/commands/scratchpad.c | 81 | ||||
-rw-r--r-- | sway/main.c | 3 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/scratchpad.c | 181 | ||||
-rw-r--r-- | sway/tree/arrange.c | 2 | ||||
-rw-r--r-- | sway/tree/container.c | 6 | ||||
-rw-r--r-- | sway/tree/layout.c | 34 | ||||
-rw-r--r-- | sway/tree/root.c | 147 |
12 files changed, 292 insertions, 275 deletions
diff --git a/include/sway/scratchpad.h b/include/sway/scratchpad.h deleted file mode 100644 index 5af5256f..00000000 --- a/include/sway/scratchpad.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | #ifndef _SWAY_SCRATCHPAD_H | ||
2 | #define _SWAY_SCRATCHPAD_H | ||
3 | |||
4 | #include "tree/container.h" | ||
5 | |||
6 | /** | ||
7 | * Move a container to the scratchpad. | ||
8 | */ | ||
9 | void scratchpad_add_container(struct sway_container *con); | ||
10 | |||
11 | /** | ||
12 | * Remove a container from the scratchpad. | ||
13 | */ | ||
14 | void scratchpad_remove_container(struct sway_container *con); | ||
15 | |||
16 | /** | ||
17 | * Show or hide the next container on the scratchpad. | ||
18 | */ | ||
19 | void scratchpad_toggle_auto(void); | ||
20 | |||
21 | /** | ||
22 | * Show or hide a specific container on the scratchpad. | ||
23 | */ | ||
24 | void scratchpad_toggle_container(struct sway_container *con); | ||
25 | |||
26 | #endif | ||
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index a4c31bf6..77cd954b 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <wlr/types/wlr_output_layout.h> | 3 | #include <wlr/types/wlr_output_layout.h> |
4 | #include <wlr/render/wlr_texture.h> | 4 | #include <wlr/render/wlr_texture.h> |
5 | #include "sway/tree/container.h" | 5 | #include "sway/tree/container.h" |
6 | #include "sway/tree/root.h" | ||
6 | #include "config.h" | 7 | #include "config.h" |
7 | 8 | ||
8 | enum movement_direction { | 9 | enum movement_direction { |
@@ -24,28 +25,6 @@ enum resize_edge { | |||
24 | 25 | ||
25 | struct sway_container; | 26 | struct sway_container; |
26 | 27 | ||
27 | struct sway_root { | ||
28 | struct wlr_output_layout *output_layout; | ||
29 | |||
30 | struct wl_listener output_layout_change; | ||
31 | #ifdef HAVE_XWAYLAND | ||
32 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link | ||
33 | #endif | ||
34 | struct wl_list drag_icons; // sway_drag_icon::link | ||
35 | |||
36 | struct wlr_texture *debug_tree; | ||
37 | |||
38 | struct wl_list outputs; // sway_output::link | ||
39 | |||
40 | list_t *scratchpad; // struct sway_container | ||
41 | |||
42 | struct { | ||
43 | struct wl_signal new_container; | ||
44 | } events; | ||
45 | }; | ||
46 | |||
47 | void layout_init(void); | ||
48 | |||
49 | void container_add_child(struct sway_container *parent, | 28 | void container_add_child(struct sway_container *parent, |
50 | struct sway_container *child); | 29 | struct sway_container *child); |
51 | 30 | ||
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h new file mode 100644 index 00000000..ada3c73f --- /dev/null +++ b/include/sway/tree/root.h | |||
@@ -0,0 +1,57 @@ | |||
1 | #ifndef _SWAY_ROOT_H | ||
2 | #define _SWAY_ROOT_H | ||
3 | #include <wayland-server-core.h> | ||
4 | #include <wayland-util.h> | ||
5 | #include <wlr/types/wlr_output_layout.h> | ||
6 | #include <wlr/render/wlr_texture.h> | ||
7 | #include "sway/tree/container.h" | ||
8 | #include "config.h" | ||
9 | #include "list.h" | ||
10 | |||
11 | extern struct sway_container root_container; | ||
12 | |||
13 | struct sway_root { | ||
14 | struct wlr_output_layout *output_layout; | ||
15 | |||
16 | struct wl_listener output_layout_change; | ||
17 | #ifdef HAVE_XWAYLAND | ||
18 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link | ||
19 | #endif | ||
20 | struct wl_list drag_icons; // sway_drag_icon::link | ||
21 | |||
22 | struct wlr_texture *debug_tree; | ||
23 | |||
24 | struct wl_list outputs; // sway_output::link | ||
25 | |||
26 | list_t *scratchpad; // struct sway_container | ||
27 | |||
28 | struct { | ||
29 | struct wl_signal new_container; | ||
30 | } events; | ||
31 | }; | ||
32 | |||
33 | void root_create(void); | ||
34 | |||
35 | void root_destroy(void); | ||
36 | |||
37 | /** | ||
38 | * Move a container to the scratchpad. | ||
39 | */ | ||
40 | void root_scratchpad_add_container(struct sway_container *con); | ||
41 | |||
42 | /** | ||
43 | * Remove a container from the scratchpad. | ||
44 | */ | ||
45 | void root_scratchpad_remove_container(struct sway_container *con); | ||
46 | |||
47 | /** | ||
48 | * Show a single scratchpad container. | ||
49 | */ | ||
50 | void root_scratchpad_show(struct sway_container *con); | ||
51 | |||
52 | /** | ||
53 | * Hide a single scratchpad container. | ||
54 | */ | ||
55 | void root_scratchpad_hide(struct sway_container *con); | ||
56 | |||
57 | #endif | ||
diff --git a/sway/commands/move.c b/sway/commands/move.c index 1e8b76f9..841da4c4 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -9,10 +9,9 @@ | |||
9 | #include "sway/input/cursor.h" | 9 | #include "sway/input/cursor.h" |
10 | #include "sway/input/seat.h" | 10 | #include "sway/input/seat.h" |
11 | #include "sway/output.h" | 11 | #include "sway/output.h" |
12 | #include "sway/scratchpad.h" | ||
13 | #include "sway/tree/arrange.h" | 12 | #include "sway/tree/arrange.h" |
14 | #include "sway/tree/container.h" | 13 | #include "sway/tree/container.h" |
15 | #include "sway/tree/layout.h" | 14 | #include "sway/tree/root.h" |
16 | #include "sway/tree/workspace.h" | 15 | #include "sway/tree/workspace.h" |
17 | #include "stringop.h" | 16 | #include "stringop.h" |
18 | #include "list.h" | 17 | #include "list.h" |
@@ -324,7 +323,7 @@ static struct cmd_results *move_to_scratchpad(struct sway_container *con) { | |||
324 | return cmd_results_new(CMD_INVALID, "move", | 323 | return cmd_results_new(CMD_INVALID, "move", |
325 | "Container is already in the scratchpad"); | 324 | "Container is already in the scratchpad"); |
326 | } | 325 | } |
327 | scratchpad_add_container(con); | 326 | root_scratchpad_add_container(con); |
328 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 327 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
329 | } | 328 | } |
330 | 329 | ||
diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c index 01a91d65..0e573aeb 100644 --- a/sway/commands/scratchpad.c +++ b/sway/commands/scratchpad.c | |||
@@ -1,8 +1,87 @@ | |||
1 | #include "log.h" | 1 | #include "log.h" |
2 | #include "sway/commands.h" | 2 | #include "sway/commands.h" |
3 | #include "sway/config.h" | 3 | #include "sway/config.h" |
4 | #include "sway/scratchpad.h" | 4 | #include "sway/input/input-manager.h" |
5 | #include "sway/input/seat.h" | ||
5 | #include "sway/tree/container.h" | 6 | #include "sway/tree/container.h" |
7 | #include "sway/tree/root.h" | ||
8 | #include "sway/tree/workspace.h" | ||
9 | |||
10 | static void scratchpad_toggle_auto(void) { | ||
11 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
12 | struct sway_container *focus = seat_get_focus(seat); | ||
13 | struct sway_container *ws = focus->type == C_WORKSPACE ? | ||
14 | focus : container_parent(focus, C_WORKSPACE); | ||
15 | |||
16 | // If the focus is in a floating split container, | ||
17 | // operate on the split container instead of the child. | ||
18 | if (container_is_floating_or_child(focus)) { | ||
19 | while (focus->parent->layout != L_FLOATING) { | ||
20 | focus = focus->parent; | ||
21 | } | ||
22 | } | ||
23 | |||
24 | |||
25 | // Check if the currently focused window is a scratchpad window and should | ||
26 | // be hidden again. | ||
27 | if (focus->scratchpad) { | ||
28 | wlr_log(WLR_DEBUG, "Focus is a scratchpad window - hiding %s", | ||
29 | focus->name); | ||
30 | root_scratchpad_hide(focus); | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | // Check if there is an unfocused scratchpad window on the current workspace | ||
35 | // and focus it. | ||
36 | for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) { | ||
37 | struct sway_container *floater = | ||
38 | ws->sway_workspace->floating->children->items[i]; | ||
39 | if (floater->scratchpad && focus != floater) { | ||
40 | wlr_log(WLR_DEBUG, | ||
41 | "Focusing other scratchpad window (%s) in this workspace", | ||
42 | floater->name); | ||
43 | root_scratchpad_show(floater); | ||
44 | return; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | // Check if there is a visible scratchpad window on another workspace. | ||
49 | // In this case we move it to the current workspace. | ||
50 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
51 | struct sway_container *con = | ||
52 | root_container.sway_root->scratchpad->items[i]; | ||
53 | if (con->parent) { | ||
54 | wlr_log(WLR_DEBUG, | ||
55 | "Moving a visible scratchpad window (%s) to this workspace", | ||
56 | con->name); | ||
57 | root_scratchpad_show(con); | ||
58 | return; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | // Take the container at the bottom of the scratchpad list | ||
63 | if (!sway_assert(root_container.sway_root->scratchpad->length, | ||
64 | "Scratchpad is empty")) { | ||
65 | return; | ||
66 | } | ||
67 | struct sway_container *con = root_container.sway_root->scratchpad->items[0]; | ||
68 | wlr_log(WLR_DEBUG, "Showing %s from list", con->name); | ||
69 | root_scratchpad_show(con); | ||
70 | } | ||
71 | |||
72 | static void scratchpad_toggle_container(struct sway_container *con) { | ||
73 | if (!sway_assert(con->scratchpad, "Container isn't in the scratchpad")) { | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | // Check if it matches a currently visible scratchpad window and hide it. | ||
78 | if (con->parent) { | ||
79 | root_scratchpad_hide(con); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | root_scratchpad_show(con); | ||
84 | } | ||
6 | 85 | ||
7 | struct cmd_results *cmd_scratchpad(int argc, char **argv) { | 86 | struct cmd_results *cmd_scratchpad(int argc, char **argv) { |
8 | struct cmd_results *error = NULL; | 87 | struct cmd_results *error = NULL; |
diff --git a/sway/main.c b/sway/main.c index c02caf42..d433368b 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -407,7 +407,7 @@ int main(int argc, char **argv) { | |||
407 | 407 | ||
408 | wlr_log(WLR_INFO, "Starting sway version " SWAY_VERSION); | 408 | wlr_log(WLR_INFO, "Starting sway version " SWAY_VERSION); |
409 | 409 | ||
410 | layout_init(); | 410 | root_create(); |
411 | 411 | ||
412 | if (!server_init(&server)) { | 412 | if (!server_init(&server)) { |
413 | return 1; | 413 | return 1; |
@@ -464,6 +464,7 @@ int main(int argc, char **argv) { | |||
464 | wlr_log(WLR_INFO, "Shutting down sway"); | 464 | wlr_log(WLR_INFO, "Shutting down sway"); |
465 | 465 | ||
466 | server_fini(&server); | 466 | server_fini(&server); |
467 | root_destroy(); | ||
467 | 468 | ||
468 | if (config) { | 469 | if (config) { |
469 | free_config(config); | 470 | free_config(config); |
diff --git a/sway/meson.build b/sway/meson.build index 17406f6b..c18fb6e2 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -7,7 +7,6 @@ sway_sources = files( | |||
7 | 'debug-tree.c', | 7 | 'debug-tree.c', |
8 | 'ipc-json.c', | 8 | 'ipc-json.c', |
9 | 'ipc-server.c', | 9 | 'ipc-server.c', |
10 | 'scratchpad.c', | ||
11 | 'security.c', | 10 | 'security.c', |
12 | 'swaynag.c', | 11 | 'swaynag.c', |
13 | 12 | ||
@@ -150,6 +149,7 @@ sway_sources = files( | |||
150 | 'tree/arrange.c', | 149 | 'tree/arrange.c', |
151 | 'tree/container.c', | 150 | 'tree/container.c', |
152 | 'tree/layout.c', | 151 | 'tree/layout.c', |
152 | 'tree/root.c', | ||
153 | 'tree/view.c', | 153 | 'tree/view.c', |
154 | 'tree/workspace.c', | 154 | 'tree/workspace.c', |
155 | 'tree/output.c', | 155 | 'tree/output.c', |
diff --git a/sway/scratchpad.c b/sway/scratchpad.c deleted file mode 100644 index b7d6fd99..00000000 --- a/sway/scratchpad.c +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | #define _XOPEN_SOURCE 700 | ||
2 | #include <stdlib.h> | ||
3 | #include <stdio.h> | ||
4 | #include <stdbool.h> | ||
5 | #include "sway/scratchpad.h" | ||
6 | #include "sway/input/seat.h" | ||
7 | #include "sway/tree/arrange.h" | ||
8 | #include "sway/tree/container.h" | ||
9 | #include "sway/tree/view.h" | ||
10 | #include "sway/tree/workspace.h" | ||
11 | #include "list.h" | ||
12 | #include "log.h" | ||
13 | |||
14 | void scratchpad_add_container(struct sway_container *con) { | ||
15 | if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { | ||
16 | return; | ||
17 | } | ||
18 | con->scratchpad = true; | ||
19 | list_add(root_container.sway_root->scratchpad, con); | ||
20 | |||
21 | struct sway_container *parent = con->parent; | ||
22 | container_set_floating(con, true); | ||
23 | container_remove_child(con); | ||
24 | arrange_windows(parent); | ||
25 | |||
26 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
27 | seat_set_focus(seat, seat_get_focus_inactive(seat, parent)); | ||
28 | } | ||
29 | |||
30 | void scratchpad_remove_container(struct sway_container *con) { | ||
31 | if (!sway_assert(con->scratchpad, "Container is not in scratchpad")) { | ||
32 | return; | ||
33 | } | ||
34 | con->scratchpad = false; | ||
35 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
36 | if (root_container.sway_root->scratchpad->items[i] == con) { | ||
37 | list_del(root_container.sway_root->scratchpad, i); | ||
38 | break; | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Show a single scratchpad container. | ||
45 | * The container might be visible on another workspace already. | ||
46 | */ | ||
47 | static void scratchpad_show(struct sway_container *con) { | ||
48 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
49 | struct sway_container *ws = seat_get_focus(seat); | ||
50 | if (ws->type != C_WORKSPACE) { | ||
51 | ws = container_parent(ws, C_WORKSPACE); | ||
52 | } | ||
53 | |||
54 | // If the current con or any of its parents are in fullscreen mode, we | ||
55 | // first need to disable it before showing the scratchpad con. | ||
56 | if (ws->sway_workspace->fullscreen) { | ||
57 | container_set_fullscreen(ws->sway_workspace->fullscreen, false); | ||
58 | } | ||
59 | |||
60 | // Show the container | ||
61 | if (con->parent) { | ||
62 | container_remove_child(con); | ||
63 | } | ||
64 | container_add_child(ws->sway_workspace->floating, con); | ||
65 | |||
66 | // Make sure the container's center point overlaps this workspace | ||
67 | double center_lx = con->x + con->width / 2; | ||
68 | double center_ly = con->y + con->height / 2; | ||
69 | |||
70 | struct wlr_box workspace_box; | ||
71 | container_get_box(ws, &workspace_box); | ||
72 | if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { | ||
73 | // Maybe resize it | ||
74 | if (con->width > ws->width || con->height > ws->height) { | ||
75 | container_init_floating(con); | ||
76 | } | ||
77 | |||
78 | // Center it | ||
79 | double new_lx = ws->x + (ws->width - con->width) / 2; | ||
80 | double new_ly = ws->y + (ws->height - con->height) / 2; | ||
81 | container_floating_move_to(con, new_lx, new_ly); | ||
82 | } | ||
83 | |||
84 | arrange_windows(ws); | ||
85 | seat_set_focus(seat, seat_get_focus_inactive(seat, con)); | ||
86 | |||
87 | container_set_dirty(con->parent); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Hide a single scratchpad container. | ||
92 | * The container might not be the focused container (eg. when using criteria). | ||
93 | */ | ||
94 | static void scratchpad_hide(struct sway_container *con) { | ||
95 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
96 | struct sway_container *focus = seat_get_focus(seat); | ||
97 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
98 | |||
99 | container_remove_child(con); | ||
100 | arrange_windows(ws); | ||
101 | if (con == focus) { | ||
102 | seat_set_focus(seat, seat_get_focus_inactive(seat, ws)); | ||
103 | } | ||
104 | list_move_to_end(root_container.sway_root->scratchpad, con); | ||
105 | } | ||
106 | |||
107 | void scratchpad_toggle_auto(void) { | ||
108 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
109 | struct sway_container *focus = seat_get_focus(seat); | ||
110 | struct sway_container *ws = focus->type == C_WORKSPACE ? | ||
111 | focus : container_parent(focus, C_WORKSPACE); | ||
112 | |||
113 | // If the focus is in a floating split container, | ||
114 | // operate on the split container instead of the child. | ||
115 | if (container_is_floating_or_child(focus)) { | ||
116 | while (focus->parent->layout != L_FLOATING) { | ||
117 | focus = focus->parent; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | |||
122 | // Check if the currently focused window is a scratchpad window and should | ||
123 | // be hidden again. | ||
124 | if (focus->scratchpad) { | ||
125 | wlr_log(WLR_DEBUG, "Focus is a scratchpad window - hiding %s", | ||
126 | focus->name); | ||
127 | scratchpad_hide(focus); | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | // Check if there is an unfocused scratchpad window on the current workspace | ||
132 | // and focus it. | ||
133 | for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) { | ||
134 | struct sway_container *floater = | ||
135 | ws->sway_workspace->floating->children->items[i]; | ||
136 | if (floater->scratchpad && focus != floater) { | ||
137 | wlr_log(WLR_DEBUG, | ||
138 | "Focusing other scratchpad window (%s) in this workspace", | ||
139 | floater->name); | ||
140 | scratchpad_show(floater); | ||
141 | return; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | // Check if there is a visible scratchpad window on another workspace. | ||
146 | // In this case we move it to the current workspace. | ||
147 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
148 | struct sway_container *con = | ||
149 | root_container.sway_root->scratchpad->items[i]; | ||
150 | if (con->parent) { | ||
151 | wlr_log(WLR_DEBUG, | ||
152 | "Moving a visible scratchpad window (%s) to this workspace", | ||
153 | con->name); | ||
154 | scratchpad_show(con); | ||
155 | return; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | // Take the container at the bottom of the scratchpad list | ||
160 | if (!sway_assert(root_container.sway_root->scratchpad->length, | ||
161 | "Scratchpad is empty")) { | ||
162 | return; | ||
163 | } | ||
164 | struct sway_container *con = root_container.sway_root->scratchpad->items[0]; | ||
165 | wlr_log(WLR_DEBUG, "Showing %s from list", con->name); | ||
166 | scratchpad_show(con); | ||
167 | } | ||
168 | |||
169 | void scratchpad_toggle_container(struct sway_container *con) { | ||
170 | if (!sway_assert(con->scratchpad, "Container isn't in the scratchpad")) { | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | // Check if it matches a currently visible scratchpad window and hide it. | ||
175 | if (con->parent) { | ||
176 | scratchpad_hide(con); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | scratchpad_show(con); | ||
181 | } | ||
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c index 5452b13c..494a8461 100644 --- a/sway/tree/arrange.c +++ b/sway/tree/arrange.c | |||
@@ -14,8 +14,6 @@ | |||
14 | #include "list.h" | 14 | #include "list.h" |
15 | #include "log.h" | 15 | #include "log.h" |
16 | 16 | ||
17 | struct sway_container root_container; | ||
18 | |||
19 | static void apply_horiz_layout(struct sway_container *parent) { | 17 | static void apply_horiz_layout(struct sway_container *parent) { |
20 | size_t num_children = parent->children->length; | 18 | size_t num_children = parent->children->length; |
21 | if (!num_children) { | 19 | if (!num_children) { |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 4a503652..6da5ac3c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include "sway/input/seat.h" | 17 | #include "sway/input/seat.h" |
18 | #include "sway/ipc-server.h" | 18 | #include "sway/ipc-server.h" |
19 | #include "sway/output.h" | 19 | #include "sway/output.h" |
20 | #include "sway/scratchpad.h" | ||
21 | #include "sway/server.h" | 20 | #include "sway/server.h" |
22 | #include "sway/tree/arrange.h" | 21 | #include "sway/tree/arrange.h" |
23 | #include "sway/tree/layout.h" | 22 | #include "sway/tree/layout.h" |
@@ -336,7 +335,6 @@ static struct sway_container *container_destroy_noreaping( | |||
336 | // Workspaces will refuse to be destroyed if they're the last workspace | 335 | // Workspaces will refuse to be destroyed if they're the last workspace |
337 | // on their output. | 336 | // on their output. |
338 | if (!container_workspace_destroy(con)) { | 337 | if (!container_workspace_destroy(con)) { |
339 | wlr_log(WLR_ERROR, "workspace doesn't want to destroy"); | ||
340 | return NULL; | 338 | return NULL; |
341 | } | 339 | } |
342 | } | 340 | } |
@@ -347,7 +345,7 @@ static struct sway_container *container_destroy_noreaping( | |||
347 | container_set_dirty(con); | 345 | container_set_dirty(con); |
348 | 346 | ||
349 | if (con->scratchpad) { | 347 | if (con->scratchpad) { |
350 | scratchpad_remove_container(con); | 348 | root_scratchpad_remove_container(con); |
351 | } | 349 | } |
352 | 350 | ||
353 | if (!con->parent) { | 351 | if (!con->parent) { |
@@ -1097,7 +1095,7 @@ void container_set_floating(struct sway_container *container, bool enable) { | |||
1097 | } else { | 1095 | } else { |
1098 | // Returning to tiled | 1096 | // Returning to tiled |
1099 | if (container->scratchpad) { | 1097 | if (container->scratchpad) { |
1100 | scratchpad_remove_container(container); | 1098 | root_scratchpad_remove_container(container); |
1101 | } | 1099 | } |
1102 | container_remove_child(container); | 1100 | container_remove_child(container); |
1103 | struct sway_container *reference = | 1101 | struct sway_container *reference = |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 1f82e534..07de9664 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -19,40 +19,6 @@ | |||
19 | #include "list.h" | 19 | #include "list.h" |
20 | #include "log.h" | 20 | #include "log.h" |
21 | 21 | ||
22 | struct sway_container root_container; | ||
23 | |||
24 | static void output_layout_handle_change(struct wl_listener *listener, | ||
25 | void *data) { | ||
26 | arrange_windows(&root_container); | ||
27 | transaction_commit_dirty(); | ||
28 | } | ||
29 | |||
30 | void layout_init(void) { | ||
31 | root_container.id = 0; // normally assigned in new_swayc() | ||
32 | root_container.type = C_ROOT; | ||
33 | root_container.layout = L_NONE; | ||
34 | root_container.name = strdup("root"); | ||
35 | root_container.instructions = create_list(); | ||
36 | root_container.children = create_list(); | ||
37 | root_container.current.children = create_list(); | ||
38 | wl_signal_init(&root_container.events.destroy); | ||
39 | |||
40 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | ||
41 | root_container.sway_root->output_layout = wlr_output_layout_create(); | ||
42 | wl_list_init(&root_container.sway_root->outputs); | ||
43 | #ifdef HAVE_XWAYLAND | ||
44 | wl_list_init(&root_container.sway_root->xwayland_unmanaged); | ||
45 | #endif | ||
46 | wl_list_init(&root_container.sway_root->drag_icons); | ||
47 | wl_signal_init(&root_container.sway_root->events.new_container); | ||
48 | root_container.sway_root->scratchpad = create_list(); | ||
49 | |||
50 | root_container.sway_root->output_layout_change.notify = | ||
51 | output_layout_handle_change; | ||
52 | wl_signal_add(&root_container.sway_root->output_layout->events.change, | ||
53 | &root_container.sway_root->output_layout_change); | ||
54 | } | ||
55 | |||
56 | static int index_child(const struct sway_container *child) { | 22 | static int index_child(const struct sway_container *child) { |
57 | struct sway_container *parent = child->parent; | 23 | struct sway_container *parent = child->parent; |
58 | for (int i = 0; i < parent->children->length; ++i) { | 24 | for (int i = 0; i < parent->children->length; ++i) { |
diff --git a/sway/tree/root.c b/sway/tree/root.c new file mode 100644 index 00000000..9f3965be --- /dev/null +++ b/sway/tree/root.c | |||
@@ -0,0 +1,147 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <stdbool.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <wlr/types/wlr_output_layout.h> | ||
6 | #include "sway/input/seat.h" | ||
7 | #include "sway/tree/arrange.h" | ||
8 | #include "sway/tree/container.h" | ||
9 | #include "sway/tree/root.h" | ||
10 | #include "sway/tree/workspace.h" | ||
11 | #include "list.h" | ||
12 | #include "log.h" | ||
13 | |||
14 | struct sway_container root_container; | ||
15 | |||
16 | static void output_layout_handle_change(struct wl_listener *listener, | ||
17 | void *data) { | ||
18 | arrange_windows(&root_container); | ||
19 | transaction_commit_dirty(); | ||
20 | } | ||
21 | |||
22 | void root_create(void) { | ||
23 | root_container.id = 0; // normally assigned in new_swayc() | ||
24 | root_container.type = C_ROOT; | ||
25 | root_container.layout = L_NONE; | ||
26 | root_container.name = strdup("root"); | ||
27 | root_container.instructions = create_list(); | ||
28 | root_container.children = create_list(); | ||
29 | root_container.current.children = create_list(); | ||
30 | wl_signal_init(&root_container.events.destroy); | ||
31 | |||
32 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | ||
33 | root_container.sway_root->output_layout = wlr_output_layout_create(); | ||
34 | wl_list_init(&root_container.sway_root->outputs); | ||
35 | #ifdef HAVE_XWAYLAND | ||
36 | wl_list_init(&root_container.sway_root->xwayland_unmanaged); | ||
37 | #endif | ||
38 | wl_list_init(&root_container.sway_root->drag_icons); | ||
39 | wl_signal_init(&root_container.sway_root->events.new_container); | ||
40 | root_container.sway_root->scratchpad = create_list(); | ||
41 | |||
42 | root_container.sway_root->output_layout_change.notify = | ||
43 | output_layout_handle_change; | ||
44 | wl_signal_add(&root_container.sway_root->output_layout->events.change, | ||
45 | &root_container.sway_root->output_layout_change); | ||
46 | } | ||
47 | |||
48 | void root_destroy(void) { | ||
49 | // sway_root | ||
50 | wl_list_remove(&root_container.sway_root->output_layout_change.link); | ||
51 | list_free(root_container.sway_root->scratchpad); | ||
52 | wlr_output_layout_destroy(root_container.sway_root->output_layout); | ||
53 | free(root_container.sway_root); | ||
54 | |||
55 | // root_container | ||
56 | list_free(root_container.instructions); | ||
57 | list_free(root_container.children); | ||
58 | list_free(root_container.current.children); | ||
59 | free(root_container.name); | ||
60 | |||
61 | memset(&root_container, 0, sizeof(root_container)); | ||
62 | } | ||
63 | |||
64 | void root_scratchpad_add_container(struct sway_container *con) { | ||
65 | if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { | ||
66 | return; | ||
67 | } | ||
68 | con->scratchpad = true; | ||
69 | list_add(root_container.sway_root->scratchpad, con); | ||
70 | |||
71 | struct sway_container *parent = con->parent; | ||
72 | container_set_floating(con, true); | ||
73 | container_remove_child(con); | ||
74 | arrange_windows(parent); | ||
75 | |||
76 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
77 | seat_set_focus(seat, seat_get_focus_inactive(seat, parent)); | ||
78 | } | ||
79 | |||
80 | void root_scratchpad_remove_container(struct sway_container *con) { | ||
81 | if (!sway_assert(con->scratchpad, "Container is not in scratchpad")) { | ||
82 | return; | ||
83 | } | ||
84 | con->scratchpad = false; | ||
85 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
86 | if (root_container.sway_root->scratchpad->items[i] == con) { | ||
87 | list_del(root_container.sway_root->scratchpad, i); | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | void root_scratchpad_show(struct sway_container *con) { | ||
94 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
95 | struct sway_container *ws = seat_get_focus(seat); | ||
96 | if (ws->type != C_WORKSPACE) { | ||
97 | ws = container_parent(ws, C_WORKSPACE); | ||
98 | } | ||
99 | |||
100 | // If the current con or any of its parents are in fullscreen mode, we | ||
101 | // first need to disable it before showing the scratchpad con. | ||
102 | if (ws->sway_workspace->fullscreen) { | ||
103 | container_set_fullscreen(ws->sway_workspace->fullscreen, false); | ||
104 | } | ||
105 | |||
106 | // Show the container | ||
107 | if (con->parent) { | ||
108 | container_remove_child(con); | ||
109 | } | ||
110 | container_add_child(ws->sway_workspace->floating, con); | ||
111 | |||
112 | // Make sure the container's center point overlaps this workspace | ||
113 | double center_lx = con->x + con->width / 2; | ||
114 | double center_ly = con->y + con->height / 2; | ||
115 | |||
116 | struct wlr_box workspace_box; | ||
117 | container_get_box(ws, &workspace_box); | ||
118 | if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { | ||
119 | // Maybe resize it | ||
120 | if (con->width > ws->width || con->height > ws->height) { | ||
121 | container_init_floating(con); | ||
122 | } | ||
123 | |||
124 | // Center it | ||
125 | double new_lx = ws->x + (ws->width - con->width) / 2; | ||
126 | double new_ly = ws->y + (ws->height - con->height) / 2; | ||
127 | container_floating_move_to(con, new_lx, new_ly); | ||
128 | } | ||
129 | |||
130 | arrange_windows(ws); | ||
131 | seat_set_focus(seat, seat_get_focus_inactive(seat, con)); | ||
132 | |||
133 | container_set_dirty(con->parent); | ||
134 | } | ||
135 | |||
136 | void root_scratchpad_hide(struct sway_container *con) { | ||
137 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
138 | struct sway_container *focus = seat_get_focus(seat); | ||
139 | struct sway_container *ws = container_parent(con, C_WORKSPACE); | ||
140 | |||
141 | container_remove_child(con); | ||
142 | arrange_windows(ws); | ||
143 | if (con == focus) { | ||
144 | seat_set_focus(seat, seat_get_focus_inactive(seat, ws)); | ||
145 | } | ||
146 | list_move_to_end(root_container.sway_root->scratchpad, con); | ||
147 | } | ||