aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/root.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-30 21:00:10 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-09-05 18:01:43 +1000
commit7586f150c058997d9dde387ea7c091ffa7a3c3c7 (patch)
tree63d19027974c1db62ce3a74ca1d2314eb6d5049b /sway/tree/root.c
parentMerge pull request #2569 from RyanDwyer/deny-reload-repeat (diff)
downloadsway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.gz
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.tar.zst
sway-7586f150c058997d9dde387ea7c091ffa7a3c3c7.zip
Implement type safe arguments and demote sway_container
This commit changes the meaning of sway_container so that it only refers to layout containers and view containers. Workspaces, outputs and the root are no longer known as containers. Instead, root, outputs, workspaces and containers are all a type of node, and containers come in two types: layout containers and view containers. In addition to the above, this implements type safe variables. This means we use specific types such as sway_output and sway_workspace instead of generic containers or nodes. However, it's worth noting that in a few places places (eg. seat focus and transactions) referring to them in a generic way is unavoidable which is why we still use nodes in some places. If you want a TL;DR, look at node.h, as well as the struct definitions for root, output, workspace and container. Note that sway_output now contains a workspaces list, and workspaces now contain a tiling and floating list, and containers now contain a pointer back to the workspace. There are now functions for seat_get_focused_workspace and seat_get_focused_container. The latter will return NULL if a workspace itself is focused. Most other seat functions like seat_get_focus and seat_set_focus now accept and return nodes. In the config->handler_context struct, current_container has been replaced with three pointers: node, container and workspace. node is the same as what current_container was, while workspace is the workspace that the node resides on and container is the actual container, which may be NULL if a workspace itself is focused. The global root_container variable has been replaced with one simply called root, which is a pointer to the sway_root instance. The way outputs are created, enabled, disabled and destroyed has changed. Previously we'd wrap the sway_output in a container when it is enabled, but as we don't have containers any more it needs a different approach. The output_create and output_destroy functions previously created/destroyed the container, but now they create/destroy the sway_output. There is a new function output_disable to disable an output without destroying it. Containers have a new view property. If this is populated then the container is a view container, otherwise it's a layout container. Like before, this property is immutable for the life of the container. Containers have both a `sway_container *parent` and `sway_workspace *workspace`. As we use specific types now, parent cannot point to a workspace so it'll be NULL for containers which are direct children of the workspace. The workspace property is set for all containers, except those which are hidden in the scratchpad as they have no workspace. In some cases we need to refer to workspaces in a container-like way. For example, workspaces have layout and children, but when using specific types this makes it difficult. Likewise, it's difficult for a container to get its parent's layout when the parent could be another container or a workspace. To make it easier, some helper functions have been created: container_parent_layout and container_get_siblings. container_remove_child has been renamed to container_detach and container_replace_child has been renamed to container_replace. `container_handle_fullscreen_reparent(con, old_parent)` has had the old_parent removed. We now unfullscreen the workspace when detaching the container, so this function is simplified and only needs one argument now. container_notify_subtree_changed has been renamed to container_update_representation. This is more descriptive of its purpose. I also wanted to be able to call it with whatever container was changed rather than the container's parent, which makes bubbling up to the workspace easier. There are now state structs per node thing. ie. sway_output_state, sway_workspace_state and sway_container_state. The focus, move and layout commands have been completely refactored to work with the specific types. I considered making these a separate PR, but I'd be backporting my changes only to replace them again, and it's easier just to test everything at once.
Diffstat (limited to 'sway/tree/root.c')
-rw-r--r--sway/tree/root.c186
1 files changed, 89 insertions, 97 deletions
diff --git a/sway/tree/root.c b/sway/tree/root.c
index b42371de..ecc04ddb 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -14,54 +14,45 @@
14#include "log.h" 14#include "log.h"
15#include "util.h" 15#include "util.h"
16 16
17struct sway_container root_container; 17struct sway_root *root;
18 18
19static void output_layout_handle_change(struct wl_listener *listener, 19static void output_layout_handle_change(struct wl_listener *listener,
20 void *data) { 20 void *data) {
21 arrange_windows(&root_container); 21 arrange_root();
22 transaction_commit_dirty(); 22 transaction_commit_dirty();
23} 23}
24 24
25void root_create(void) { 25struct sway_root *root_create(void) {
26 root_container.id = 0; // normally assigned in new_swayc() 26 struct sway_root *root = calloc(1, sizeof(struct sway_root));
27 root_container.type = C_ROOT; 27 if (!root) {
28 root_container.layout = L_NONE; 28 wlr_log(WLR_ERROR, "Unable to allocate sway_root");
29 root_container.name = strdup("root"); 29 return NULL;
30 root_container.children = create_list(); 30 }
31 root_container.current.children = create_list(); 31 node_init(&root->node, N_ROOT, root);
32 wl_signal_init(&root_container.events.destroy); 32 root->output_layout = wlr_output_layout_create();
33 33 wl_list_init(&root->all_outputs);
34 root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
35 root_container.sway_root->output_layout = wlr_output_layout_create();
36 wl_list_init(&root_container.sway_root->all_outputs);
37#ifdef HAVE_XWAYLAND 34#ifdef HAVE_XWAYLAND
38 wl_list_init(&root_container.sway_root->xwayland_unmanaged); 35 wl_list_init(&root->xwayland_unmanaged);
39#endif 36#endif
40 wl_list_init(&root_container.sway_root->drag_icons); 37 wl_list_init(&root->drag_icons);
41 wl_signal_init(&root_container.sway_root->events.new_container); 38 wl_signal_init(&root->events.new_node);
42 root_container.sway_root->scratchpad = create_list(); 39 root->outputs = create_list();
43 root_container.sway_root->saved_workspaces = create_list(); 40 root->scratchpad = create_list();
44 41 root->saved_workspaces = create_list();
45 root_container.sway_root->output_layout_change.notify = 42
46 output_layout_handle_change; 43 root->output_layout_change.notify = output_layout_handle_change;
47 wl_signal_add(&root_container.sway_root->output_layout->events.change, 44 wl_signal_add(&root->output_layout->events.change,
48 &root_container.sway_root->output_layout_change); 45 &root->output_layout_change);
46 return root;
49} 47}
50 48
51void root_destroy(void) { 49void root_destroy(struct sway_root *root) {
52 // sway_root 50 wl_list_remove(&root->output_layout_change.link);
53 wl_list_remove(&root_container.sway_root->output_layout_change.link); 51 list_free(root->scratchpad);
54 list_free(root_container.sway_root->scratchpad); 52 list_free(root->saved_workspaces);
55 list_free(root_container.sway_root->saved_workspaces); 53 list_free(root->outputs);
56 wlr_output_layout_destroy(root_container.sway_root->output_layout); 54 wlr_output_layout_destroy(root->output_layout);
57 free(root_container.sway_root); 55 free(root);
58
59 // root_container
60 list_free(root_container.children);
61 list_free(root_container.current.children);
62 free(root_container.name);
63
64 memset(&root_container, 0, sizeof(root_container));
65} 56}
66 57
67void root_scratchpad_add_container(struct sway_container *con) { 58void root_scratchpad_add_container(struct sway_container *con) {
@@ -69,15 +60,21 @@ void root_scratchpad_add_container(struct sway_container *con) {
69 return; 60 return;
70 } 61 }
71 con->scratchpad = true; 62 con->scratchpad = true;
72 list_add(root_container.sway_root->scratchpad, con); 63 list_add(root->scratchpad, con);
73 64
74 struct sway_container *parent = con->parent; 65 struct sway_container *parent = con->parent;
66 struct sway_workspace *workspace = con->workspace;
75 container_set_floating(con, true); 67 container_set_floating(con, true);
76 container_remove_child(con); 68 container_detach(con);
77 arrange_windows(parent);
78 69
79 struct sway_seat *seat = input_manager_current_seat(input_manager); 70 struct sway_seat *seat = input_manager_current_seat(input_manager);
80 seat_set_focus(seat, seat_get_focus_inactive(seat, parent)); 71 if (parent) {
72 arrange_container(parent);
73 seat_set_focus(seat, seat_get_focus_inactive(seat, &parent->node));
74 } else {
75 arrange_workspace(workspace);
76 seat_set_focus(seat, seat_get_focus_inactive(seat, &workspace->node));
77 }
81} 78}
82 79
83void root_scratchpad_remove_container(struct sway_container *con) { 80void root_scratchpad_remove_container(struct sway_container *con) {
@@ -85,28 +82,25 @@ void root_scratchpad_remove_container(struct sway_container *con) {
85 return; 82 return;
86 } 83 }
87 con->scratchpad = false; 84 con->scratchpad = false;
88 int index = list_find(root_container.sway_root->scratchpad, con); 85 int index = list_find(root->scratchpad, con);
89 if (index != -1) { 86 if (index != -1) {
90 list_del(root_container.sway_root->scratchpad, index); 87 list_del(root->scratchpad, index);
91 } 88 }
92} 89}
93 90
94void root_scratchpad_show(struct sway_container *con) { 91void root_scratchpad_show(struct sway_container *con) {
95 struct sway_seat *seat = input_manager_current_seat(input_manager); 92 struct sway_seat *seat = input_manager_current_seat(input_manager);
96 struct sway_container *ws = seat_get_focus(seat); 93 struct sway_workspace *ws = seat_get_focused_workspace(seat);
97 if (ws->type != C_WORKSPACE) {
98 ws = container_parent(ws, C_WORKSPACE);
99 }
100 94
101 // If the current con or any of its parents are in fullscreen mode, we 95 // If the current con or any of its parents are in fullscreen mode, we
102 // first need to disable it before showing the scratchpad con. 96 // first need to disable it before showing the scratchpad con.
103 if (ws->sway_workspace->fullscreen) { 97 if (ws->fullscreen) {
104 container_set_fullscreen(ws->sway_workspace->fullscreen, false); 98 container_set_fullscreen(ws->fullscreen, false);
105 } 99 }
106 100
107 // Show the container 101 // Show the container
108 if (con->parent) { 102 if (con->workspace) {
109 container_remove_child(con); 103 container_detach(con);
110 } 104 }
111 workspace_add_floating(ws, con); 105 workspace_add_floating(ws, con);
112 106
@@ -115,7 +109,7 @@ void root_scratchpad_show(struct sway_container *con) {
115 double center_ly = con->y + con->height / 2; 109 double center_ly = con->y + con->height / 2;
116 110
117 struct wlr_box workspace_box; 111 struct wlr_box workspace_box;
118 container_get_box(ws, &workspace_box); 112 workspace_get_box(ws, &workspace_box);
119 if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { 113 if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) {
120 // Maybe resize it 114 // Maybe resize it
121 if (con->width > ws->width || con->height > ws->height) { 115 if (con->width > ws->width || con->height > ws->height) {
@@ -128,23 +122,21 @@ void root_scratchpad_show(struct sway_container *con) {
128 container_floating_move_to(con, new_lx, new_ly); 122 container_floating_move_to(con, new_lx, new_ly);
129 } 123 }
130 124
131 arrange_windows(ws); 125 arrange_workspace(ws);
132 seat_set_focus(seat, seat_get_focus_inactive(seat, con)); 126 seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node));
133
134 container_set_dirty(con->parent);
135} 127}
136 128
137void root_scratchpad_hide(struct sway_container *con) { 129void root_scratchpad_hide(struct sway_container *con) {
138 struct sway_seat *seat = input_manager_current_seat(input_manager); 130 struct sway_seat *seat = input_manager_current_seat(input_manager);
139 struct sway_container *focus = seat_get_focus(seat); 131 struct sway_node *focus = seat_get_focus(seat);
140 struct sway_container *ws = container_parent(con, C_WORKSPACE); 132 struct sway_workspace *ws = con->workspace;
141 133
142 container_remove_child(con); 134 container_detach(con);
143 arrange_windows(ws); 135 arrange_workspace(ws);
144 if (con == focus) { 136 if (&con->node == focus) {
145 seat_set_focus(seat, seat_get_focus_inactive(seat, ws)); 137 seat_set_focus(seat, seat_get_focus_inactive(seat, &ws->node));
146 } 138 }
147 list_move_to_end(root_container.sway_root->scratchpad, con); 139 list_move_to_end(root->scratchpad, con);
148} 140}
149 141
150struct pid_workspace { 142struct pid_workspace {
@@ -152,7 +144,7 @@ struct pid_workspace {
152 char *workspace; 144 char *workspace;
153 struct timespec time_added; 145 struct timespec time_added;
154 146
155 struct sway_container *output; 147 struct sway_output *output;
156 struct wl_listener output_destroy; 148 struct wl_listener output_destroy;
157 149
158 struct wl_list link; 150 struct wl_list link;
@@ -160,13 +152,13 @@ struct pid_workspace {
160 152
161static struct wl_list pid_workspaces; 153static struct wl_list pid_workspaces;
162 154
163struct sway_container *root_workspace_for_pid(pid_t pid) { 155struct sway_workspace *root_workspace_for_pid(pid_t pid) {
164 if (!pid_workspaces.prev && !pid_workspaces.next) { 156 if (!pid_workspaces.prev && !pid_workspaces.next) {
165 wl_list_init(&pid_workspaces); 157 wl_list_init(&pid_workspaces);
166 return NULL; 158 return NULL;
167 } 159 }
168 160
169 struct sway_container *ws = NULL; 161 struct sway_workspace *ws = NULL;
170 struct pid_workspace *pw = NULL; 162 struct pid_workspace *pw = NULL;
171 163
172 wlr_log(WLR_DEBUG, "Looking up workspace for pid %d", pid); 164 wlr_log(WLR_DEBUG, "Looking up workspace for pid %d", pid);
@@ -219,16 +211,12 @@ void root_record_workspace_pid(pid_t pid) {
219 } 211 }
220 212
221 struct sway_seat *seat = input_manager_current_seat(input_manager); 213 struct sway_seat *seat = input_manager_current_seat(input_manager);
222 struct sway_container *ws = 214 struct sway_workspace *ws = seat_get_focused_workspace(seat);
223 seat_get_focus_inactive(seat, &root_container);
224 if (ws && ws->type != C_WORKSPACE) {
225 ws = container_parent(ws, C_WORKSPACE);
226 }
227 if (!ws) { 215 if (!ws) {
228 wlr_log(WLR_DEBUG, "Bailing out, no workspace"); 216 wlr_log(WLR_DEBUG, "Bailing out, no workspace");
229 return; 217 return;
230 } 218 }
231 struct sway_container *output = ws->parent; 219 struct sway_output *output = ws->output;
232 if (!output) { 220 if (!output) {
233 wlr_log(WLR_DEBUG, "Bailing out, no output"); 221 wlr_log(WLR_DEBUG, "Bailing out, no output");
234 return; 222 return;
@@ -255,30 +243,28 @@ void root_record_workspace_pid(pid_t pid) {
255 pw->pid = pid; 243 pw->pid = pid;
256 memcpy(&pw->time_added, &now, sizeof(struct timespec)); 244 memcpy(&pw->time_added, &now, sizeof(struct timespec));
257 pw->output_destroy.notify = pw_handle_output_destroy; 245 pw->output_destroy.notify = pw_handle_output_destroy;
258 wl_signal_add(&output->sway_output->wlr_output->events.destroy, 246 wl_signal_add(&output->wlr_output->events.destroy, &pw->output_destroy);
259 &pw->output_destroy);
260 wl_list_insert(&pid_workspaces, &pw->link); 247 wl_list_insert(&pid_workspaces, &pw->link);
261} 248}
262 249
263void root_for_each_workspace(void (*f)(struct sway_container *con, void *data), 250void root_for_each_workspace(void (*f)(struct sway_workspace *ws, void *data),
264 void *data) { 251 void *data) {
265 for (int i = 0; i < root_container.children->length; ++i) { 252 for (int i = 0; i < root->outputs->length; ++i) {
266 struct sway_container *output = root_container.children->items[i]; 253 struct sway_output *output = root->outputs->items[i];
267 output_for_each_workspace(output, f, data); 254 output_for_each_workspace(output, f, data);
268 } 255 }
269} 256}
270 257
271void root_for_each_container(void (*f)(struct sway_container *con, void *data), 258void root_for_each_container(void (*f)(struct sway_container *con, void *data),
272 void *data) { 259 void *data) {
273 for (int i = 0; i < root_container.children->length; ++i) { 260 for (int i = 0; i < root->outputs->length; ++i) {
274 struct sway_container *output = root_container.children->items[i]; 261 struct sway_output *output = root->outputs->items[i];
275 output_for_each_container(output, f, data); 262 output_for_each_container(output, f, data);
276 } 263 }
277 264
278 // Scratchpad 265 // Scratchpad
279 for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { 266 for (int i = 0; i < root->scratchpad->length; ++i) {
280 struct sway_container *container = 267 struct sway_container *container = root->scratchpad->items[i];
281 root_container.sway_root->scratchpad->items[i];
282 // If the container has a parent then it's visible on a workspace 268 // If the container has a parent then it's visible on a workspace
283 // and will have been iterated in the previous for loop. So we only 269 // and will have been iterated in the previous for loop. So we only
284 // iterate the hidden scratchpad containers here. 270 // iterate the hidden scratchpad containers here.
@@ -289,10 +275,10 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
289 } 275 }
290} 276}
291 277
292struct sway_container *root_find_output( 278struct sway_output *root_find_output(
293 bool (*test)(struct sway_container *con, void *data), void *data) { 279 bool (*test)(struct sway_output *output, void *data), void *data) {
294 for (int i = 0; i < root_container.children->length; ++i) { 280 for (int i = 0; i < root->outputs->length; ++i) {
295 struct sway_container *output = root_container.children->items[i]; 281 struct sway_output *output = root->outputs->items[i];
296 if (test(output, data)) { 282 if (test(output, data)) {
297 return output; 283 return output;
298 } 284 }
@@ -300,11 +286,11 @@ struct sway_container *root_find_output(
300 return NULL; 286 return NULL;
301} 287}
302 288
303struct sway_container *root_find_workspace( 289struct sway_workspace *root_find_workspace(
304 bool (*test)(struct sway_container *con, void *data), void *data) { 290 bool (*test)(struct sway_workspace *ws, void *data), void *data) {
305 struct sway_container *result = NULL; 291 struct sway_workspace *result = NULL;
306 for (int i = 0; i < root_container.children->length; ++i) { 292 for (int i = 0; i < root->outputs->length; ++i) {
307 struct sway_container *output = root_container.children->items[i]; 293 struct sway_output *output = root->outputs->items[i];
308 if ((result = output_find_workspace(output, test, data))) { 294 if ((result = output_find_workspace(output, test, data))) {
309 return result; 295 return result;
310 } 296 }
@@ -315,17 +301,16 @@ struct sway_container *root_find_workspace(
315struct sway_container *root_find_container( 301struct sway_container *root_find_container(
316 bool (*test)(struct sway_container *con, void *data), void *data) { 302 bool (*test)(struct sway_container *con, void *data), void *data) {
317 struct sway_container *result = NULL; 303 struct sway_container *result = NULL;
318 for (int i = 0; i < root_container.children->length; ++i) { 304 for (int i = 0; i < root->outputs->length; ++i) {
319 struct sway_container *output = root_container.children->items[i]; 305 struct sway_output *output = root->outputs->items[i];
320 if ((result = output_find_container(output, test, data))) { 306 if ((result = output_find_container(output, test, data))) {
321 return result; 307 return result;
322 } 308 }
323 } 309 }
324 310
325 // Scratchpad 311 // Scratchpad
326 for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { 312 for (int i = 0; i < root->scratchpad->length; ++i) {
327 struct sway_container *container = 313 struct sway_container *container = root->scratchpad->items[i];
328 root_container.sway_root->scratchpad->items[i];
329 if (!container->parent) { 314 if (!container->parent) {
330 if (test(container, data)) { 315 if (test(container, data)) {
331 return container; 316 return container;
@@ -337,3 +322,10 @@ struct sway_container *root_find_container(
337 } 322 }
338 return NULL; 323 return NULL;
339} 324}
325
326void root_get_box(struct sway_root *root, struct wlr_box *box) {
327 box->x = root->x;
328 box->y = root->y;
329 box->width = root->width;
330 box->height = root->height;
331}