summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-03 23:06:01 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-04 14:01:20 +1000
commit04489ff4209dc073027419d90961367cfb998fe8 (patch)
treed6f6213d2374e10a875e8ced872511e6e656ae3e
parentMerge pull request #2419 from RedSoxFan/fix-2416 (diff)
downloadsway-04489ff4209dc073027419d90961367cfb998fe8.tar.gz
sway-04489ff4209dc073027419d90961367cfb998fe8.tar.zst
sway-04489ff4209dc073027419d90961367cfb998fe8.zip
Separate root-related code
This creates a root.c and moves bits and pieces from elsewhere into it. * layout_init has been renamed to root_create and moved into root.c * root_destroy has been created and is called on shutdown * scratchpad code has been moved into root.c, because hidden scratchpad containers are stored in the root struct
-rw-r--r--include/sway/scratchpad.h26
-rw-r--r--include/sway/tree/layout.h23
-rw-r--r--include/sway/tree/root.h57
-rw-r--r--sway/commands/move.c5
-rw-r--r--sway/commands/scratchpad.c81
-rw-r--r--sway/main.c3
-rw-r--r--sway/meson.build2
-rw-r--r--sway/scratchpad.c181
-rw-r--r--sway/tree/arrange.c2
-rw-r--r--sway/tree/container.c6
-rw-r--r--sway/tree/layout.c34
-rw-r--r--sway/tree/root.c147
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 */
9void scratchpad_add_container(struct sway_container *con);
10
11/**
12 * Remove a container from the scratchpad.
13 */
14void scratchpad_remove_container(struct sway_container *con);
15
16/**
17 * Show or hide the next container on the scratchpad.
18 */
19void scratchpad_toggle_auto(void);
20
21/**
22 * Show or hide a specific container on the scratchpad.
23 */
24void 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
8enum movement_direction { 9enum movement_direction {
@@ -24,28 +25,6 @@ enum resize_edge {
24 25
25struct sway_container; 26struct sway_container;
26 27
27struct 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
47void layout_init(void);
48
49void container_add_child(struct sway_container *parent, 28void 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
11extern struct sway_container root_container;
12
13struct 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
33void root_create(void);
34
35void root_destroy(void);
36
37/**
38 * Move a container to the scratchpad.
39 */
40void root_scratchpad_add_container(struct sway_container *con);
41
42/**
43 * Remove a container from the scratchpad.
44 */
45void root_scratchpad_remove_container(struct sway_container *con);
46
47/**
48 * Show a single scratchpad container.
49 */
50void root_scratchpad_show(struct sway_container *con);
51
52/**
53 * Hide a single scratchpad container.
54 */
55void 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
10static 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
72static 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
7struct cmd_results *cmd_scratchpad(int argc, char **argv) { 86struct 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
14void 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
30void 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 */
47static 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 */
94static 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
107void 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
169void 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
17struct sway_container root_container;
18
19static void apply_horiz_layout(struct sway_container *parent) { 17static 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
22struct sway_container root_container;
23
24static void output_layout_handle_change(struct wl_listener *listener,
25 void *data) {
26 arrange_windows(&root_container);
27 transaction_commit_dirty();
28}
29
30void 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
56static int index_child(const struct sway_container *child) { 22static 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
14struct sway_container root_container;
15
16static void output_layout_handle_change(struct wl_listener *listener,
17 void *data) {
18 arrange_windows(&root_container);
19 transaction_commit_dirty();
20}
21
22void 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
48void 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
64void 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
80void 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
93void 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
136void 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}