diff options
-rw-r--r-- | include/sway/input/seat.h | 20 | ||||
-rw-r--r-- | include/sway/output.h | 14 | ||||
-rw-r--r-- | include/sway/tree/container.h | 19 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 2 | ||||
-rw-r--r-- | include/sway/tree/root.h | 15 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 13 | ||||
-rw-r--r-- | sway/commands/floating.c | 3 | ||||
-rw-r--r-- | sway/commands/fullscreen.c | 3 | ||||
-rw-r--r-- | sway/commands/hide_edge_borders.c | 2 | ||||
-rw-r--r-- | sway/commands/move.c | 6 | ||||
-rw-r--r-- | sway/commands/rename.c | 3 | ||||
-rw-r--r-- | sway/commands/show_marks.c | 3 | ||||
-rw-r--r-- | sway/commands/swap.c | 6 | ||||
-rw-r--r-- | sway/commands/unmark.c | 3 | ||||
-rw-r--r-- | sway/config.c | 13 | ||||
-rw-r--r-- | sway/criteria.c | 15 | ||||
-rw-r--r-- | sway/desktop/output.c | 9 | ||||
-rw-r--r-- | sway/input/cursor.c | 34 | ||||
-rw-r--r-- | sway/input/seat.c | 33 | ||||
-rw-r--r-- | sway/ipc-server.c | 8 | ||||
-rw-r--r-- | sway/tree/container.c | 76 | ||||
-rw-r--r-- | sway/tree/layout.c | 23 | ||||
-rw-r--r-- | sway/tree/output.c | 73 | ||||
-rw-r--r-- | sway/tree/root.c | 78 | ||||
-rw-r--r-- | sway/tree/view.c | 6 | ||||
-rw-r--r-- | sway/tree/workspace.c | 85 |
26 files changed, 389 insertions, 176 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 9dfb0714..5c404ecd 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -35,6 +35,14 @@ struct sway_drag_icon { | |||
35 | struct wl_listener destroy; | 35 | struct wl_listener destroy; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | enum sway_seat_operation { | ||
39 | OP_NONE, | ||
40 | OP_DOWN, | ||
41 | OP_MOVE, | ||
42 | OP_RESIZE_FLOATING, | ||
43 | OP_RESIZE_TILING, | ||
44 | }; | ||
45 | |||
38 | struct sway_seat { | 46 | struct sway_seat { |
39 | struct wlr_seat *wlr_seat; | 47 | struct wlr_seat *wlr_seat; |
40 | struct sway_cursor *cursor; | 48 | struct sway_cursor *cursor; |
@@ -54,13 +62,7 @@ struct sway_seat { | |||
54 | double touch_x, touch_y; | 62 | double touch_x, touch_y; |
55 | 63 | ||
56 | // Operations (drag and resize) | 64 | // Operations (drag and resize) |
57 | enum { | 65 | enum sway_seat_operation operation; |
58 | OP_NONE, | ||
59 | OP_MOVE, | ||
60 | OP_RESIZE_FLOATING, | ||
61 | OP_RESIZE_TILING, | ||
62 | } operation; | ||
63 | |||
64 | struct sway_container *op_container; | 66 | struct sway_container *op_container; |
65 | enum wlr_edges op_resize_edge; | 67 | enum wlr_edges op_resize_edge; |
66 | uint32_t op_button; | 68 | uint32_t op_button; |
@@ -68,6 +70,7 @@ struct sway_seat { | |||
68 | double op_ref_lx, op_ref_ly; // cursor's x/y at start of op | 70 | double op_ref_lx, op_ref_ly; // cursor's x/y at start of op |
69 | double op_ref_width, op_ref_height; // container's size at start of op | 71 | double op_ref_width, op_ref_height; // container's size at start of op |
70 | double op_ref_con_lx, op_ref_con_ly; // container's x/y at start of op | 72 | double op_ref_con_lx, op_ref_con_ly; // container's x/y at start of op |
73 | bool op_moved; // if the mouse moved during a down op | ||
71 | 74 | ||
72 | uint32_t last_button; | 75 | uint32_t last_button; |
73 | uint32_t last_button_serial; | 76 | uint32_t last_button_serial; |
@@ -157,6 +160,9 @@ bool seat_is_input_allowed(struct sway_seat *seat, struct wlr_surface *surface); | |||
157 | 160 | ||
158 | void drag_icon_update_position(struct sway_drag_icon *icon); | 161 | void drag_icon_update_position(struct sway_drag_icon *icon); |
159 | 162 | ||
163 | void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | ||
164 | uint32_t button, double sx, double sy); | ||
165 | |||
160 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, | 166 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, |
161 | uint32_t button); | 167 | uint32_t button); |
162 | 168 | ||
diff --git a/include/sway/output.h b/include/sway/output.h index 80dcd37b..d0d034b3 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -58,6 +58,8 @@ void output_damage_whole_container(struct sway_output *output, | |||
58 | 58 | ||
59 | struct sway_container *output_by_name(const char *name); | 59 | struct sway_container *output_by_name(const char *name); |
60 | 60 | ||
61 | void output_sort_workspaces(struct sway_container *output); | ||
62 | |||
61 | void output_enable(struct sway_output *output); | 63 | void output_enable(struct sway_output *output); |
62 | 64 | ||
63 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output); | 65 | bool output_has_opaque_overlay_layer_surface(struct sway_output *output); |
@@ -93,4 +95,16 @@ void output_drag_icons_for_each_surface(struct sway_output *output, | |||
93 | struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, | 95 | struct wl_list *drag_icons, sway_surface_iterator_func_t iterator, |
94 | void *user_data); | 96 | void *user_data); |
95 | 97 | ||
98 | void output_for_each_workspace(struct sway_container *output, | ||
99 | void (*f)(struct sway_container *con, void *data), void *data); | ||
100 | |||
101 | void output_for_each_container(struct sway_container *output, | ||
102 | void (*f)(struct sway_container *con, void *data), void *data); | ||
103 | |||
104 | struct sway_container *output_find_workspace(struct sway_container *output, | ||
105 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
106 | |||
107 | struct sway_container *output_find_container(struct sway_container *output, | ||
108 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
109 | |||
96 | #endif | 110 | #endif |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index fdcc31ec..c8410801 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -214,15 +214,11 @@ struct sway_container *container_destroy(struct sway_container *container); | |||
214 | 214 | ||
215 | struct sway_container *container_close(struct sway_container *container); | 215 | struct sway_container *container_close(struct sway_container *container); |
216 | 216 | ||
217 | void container_descendants(struct sway_container *root, | ||
218 | enum sway_container_type type, | ||
219 | void (*func)(struct sway_container *item, void *data), void *data); | ||
220 | |||
221 | /** | 217 | /** |
222 | * Search a container's descendants a container based on test criteria. Returns | 218 | * Search a container's descendants a container based on test criteria. Returns |
223 | * the first container that passes the test. | 219 | * the first container that passes the test. |
224 | */ | 220 | */ |
225 | struct sway_container *container_find(struct sway_container *container, | 221 | struct sway_container *container_find_child(struct sway_container *container, |
226 | bool (*test)(struct sway_container *view, void *data), void *data); | 222 | bool (*test)(struct sway_container *view, void *data), void *data); |
227 | 223 | ||
228 | /** | 224 | /** |
@@ -244,10 +240,7 @@ struct sway_container *tiling_container_at( | |||
244 | struct sway_container *con, double lx, double ly, | 240 | struct sway_container *con, double lx, double ly, |
245 | struct wlr_surface **surface, double *sx, double *sy); | 241 | struct wlr_surface **surface, double *sx, double *sy); |
246 | 242 | ||
247 | /** | 243 | void container_for_each_child(struct sway_container *container, |
248 | * Apply the function for each child of the container depth first. | ||
249 | */ | ||
250 | void container_for_each_descendant(struct sway_container *container, | ||
251 | void (*f)(struct sway_container *container, void *data), void *data); | 244 | void (*f)(struct sway_container *container, void *data), void *data); |
252 | 245 | ||
253 | /** | 246 | /** |
@@ -361,12 +354,4 @@ bool container_is_floating_or_child(struct sway_container *container); | |||
361 | */ | 354 | */ |
362 | bool container_is_fullscreen_or_child(struct sway_container *container); | 355 | bool container_is_fullscreen_or_child(struct sway_container *container); |
363 | 356 | ||
364 | /** | ||
365 | * Wrap the children of parent in a new container. The new container will be the | ||
366 | * only child of parent. | ||
367 | * | ||
368 | * The new container is returned. | ||
369 | */ | ||
370 | struct sway_container *container_wrap_children(struct sway_container *parent); | ||
371 | |||
372 | #endif | 357 | #endif |
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index 77cd954b..5b803dfe 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -45,8 +45,6 @@ void container_move(struct sway_container *container, | |||
45 | enum sway_container_layout container_get_default_layout( | 45 | enum sway_container_layout container_get_default_layout( |
46 | struct sway_container *con); | 46 | struct sway_container *con); |
47 | 47 | ||
48 | void container_sort_workspaces(struct sway_container *output); | ||
49 | |||
50 | struct sway_container *container_get_in_direction(struct sway_container | 48 | struct sway_container *container_get_in_direction(struct sway_container |
51 | *container, struct sway_seat *seat, enum movement_direction dir); | 49 | *container, struct sway_seat *seat, enum movement_direction dir); |
52 | 50 | ||
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index edb7c817..d1f04a96 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h | |||
@@ -58,4 +58,19 @@ struct sway_container *root_workspace_for_pid(pid_t pid); | |||
58 | 58 | ||
59 | void root_record_workspace_pid(pid_t pid); | 59 | void root_record_workspace_pid(pid_t pid); |
60 | 60 | ||
61 | void root_for_each_workspace(void (*f)(struct sway_container *con, void *data), | ||
62 | void *data); | ||
63 | |||
64 | void root_for_each_container(void (*f)(struct sway_container *con, void *data), | ||
65 | void *data); | ||
66 | |||
67 | struct sway_container *root_find_output( | ||
68 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
69 | |||
70 | struct sway_container *root_find_workspace( | ||
71 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
72 | |||
73 | struct sway_container *root_find_container( | ||
74 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
75 | |||
61 | #endif | 76 | #endif |
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 056f2329..c9dbb538 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h | |||
@@ -50,4 +50,17 @@ struct sway_container *workspace_output_get_highest_available( | |||
50 | 50 | ||
51 | void workspace_detect_urgent(struct sway_container *workspace); | 51 | void workspace_detect_urgent(struct sway_container *workspace); |
52 | 52 | ||
53 | void workspace_for_each_container(struct sway_container *ws, | ||
54 | void (*f)(struct sway_container *con, void *data), void *data); | ||
55 | |||
56 | struct sway_container *workspace_find_container(struct sway_container *ws, | ||
57 | bool (*test)(struct sway_container *con, void *data), void *data); | ||
58 | |||
59 | /** | ||
60 | * Wrap the workspace's tiling children in a new container. | ||
61 | * The new container will be the only direct tiling child of the workspace. | ||
62 | * The new container is returned. | ||
63 | */ | ||
64 | struct sway_container *workspace_wrap_children(struct sway_container *ws); | ||
65 | |||
53 | #endif | 66 | #endif |
diff --git a/sway/commands/floating.c b/sway/commands/floating.c index 31de5ec3..c9467ef0 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "sway/tree/container.h" | 8 | #include "sway/tree/container.h" |
9 | #include "sway/tree/layout.h" | 9 | #include "sway/tree/layout.h" |
10 | #include "sway/tree/view.h" | 10 | #include "sway/tree/view.h" |
11 | #include "sway/tree/workspace.h" | ||
11 | #include "list.h" | 12 | #include "list.h" |
12 | 13 | ||
13 | struct cmd_results *cmd_floating(int argc, char **argv) { | 14 | struct cmd_results *cmd_floating(int argc, char **argv) { |
@@ -24,7 +25,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) { | |||
24 | if (container->type == C_WORKSPACE) { | 25 | if (container->type == C_WORKSPACE) { |
25 | // Wrap the workspace's children in a container so we can float it | 26 | // Wrap the workspace's children in a container so we can float it |
26 | struct sway_container *workspace = container; | 27 | struct sway_container *workspace = container; |
27 | container = container_wrap_children(container); | 28 | container = workspace_wrap_children(container); |
28 | workspace->layout = L_HORIZ; | 29 | workspace->layout = L_HORIZ; |
29 | seat_set_focus(config->handler_context.seat, container); | 30 | seat_set_focus(config->handler_context.seat, container); |
30 | } | 31 | } |
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index 5ad06e40..a0661200 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "sway/tree/arrange.h" | 4 | #include "sway/tree/arrange.h" |
5 | #include "sway/tree/container.h" | 5 | #include "sway/tree/container.h" |
6 | #include "sway/tree/view.h" | 6 | #include "sway/tree/view.h" |
7 | #include "sway/tree/workspace.h" | ||
7 | #include "sway/tree/layout.h" | 8 | #include "sway/tree/layout.h" |
8 | #include "util.h" | 9 | #include "util.h" |
9 | 10 | ||
@@ -21,7 +22,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { | |||
21 | if (container->type == C_WORKSPACE) { | 22 | if (container->type == C_WORKSPACE) { |
22 | // Wrap the workspace's children in a container so we can fullscreen it | 23 | // Wrap the workspace's children in a container so we can fullscreen it |
23 | struct sway_container *workspace = container; | 24 | struct sway_container *workspace = container; |
24 | container = container_wrap_children(container); | 25 | container = workspace_wrap_children(container); |
25 | workspace->layout = L_HORIZ; | 26 | workspace->layout = L_HORIZ; |
26 | seat_set_focus(config->handler_context.seat, container); | 27 | seat_set_focus(config->handler_context.seat, container); |
27 | } | 28 | } |
diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c index bb390f5f..d59c9fdb 100644 --- a/sway/commands/hide_edge_borders.c +++ b/sway/commands/hide_edge_borders.c | |||
@@ -31,7 +31,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { | |||
31 | "<none|vertical|horizontal|both|smart>'"); | 31 | "<none|vertical|horizontal|both|smart>'"); |
32 | } | 32 | } |
33 | 33 | ||
34 | container_for_each_descendant(&root_container, _configure_view, NULL); | 34 | root_for_each_container(_configure_view, NULL); |
35 | 35 | ||
36 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 36 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
37 | } | 37 | } |
diff --git a/sway/commands/move.c b/sway/commands/move.c index de6b1b0a..acdc50b5 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c | |||
@@ -64,7 +64,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, | |||
64 | return cmd_results_new(CMD_FAILURE, "move", | 64 | return cmd_results_new(CMD_FAILURE, "move", |
65 | "Can't move an empty workspace"); | 65 | "Can't move an empty workspace"); |
66 | } | 66 | } |
67 | current = container_wrap_children(current); | 67 | current = workspace_wrap_children(current); |
68 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { | 68 | } else if (current->type != C_CONTAINER && current->type != C_VIEW) { |
69 | return cmd_results_new(CMD_FAILURE, "move", | 69 | return cmd_results_new(CMD_FAILURE, "move", |
70 | "Can only move containers and views."); | 70 | "Can only move containers and views."); |
@@ -245,7 +245,7 @@ static void workspace_move_to_output(struct sway_container *workspace, | |||
245 | // Try to remove an empty workspace from the destination output. | 245 | // Try to remove an empty workspace from the destination output. |
246 | container_reap_empty_recursive(new_output_focus); | 246 | container_reap_empty_recursive(new_output_focus); |
247 | 247 | ||
248 | container_sort_workspaces(output); | 248 | output_sort_workspaces(output); |
249 | seat_set_focus(seat, output); | 249 | seat_set_focus(seat, output); |
250 | workspace_output_raise_priority(workspace, old_output, output); | 250 | workspace_output_raise_priority(workspace, old_output, output); |
251 | ipc_event_workspace(NULL, workspace, "move"); | 251 | ipc_event_workspace(NULL, workspace, "move"); |
@@ -437,7 +437,7 @@ static struct cmd_results *move_to_scratchpad(struct sway_container *con) { | |||
437 | if (con->type == C_WORKSPACE) { | 437 | if (con->type == C_WORKSPACE) { |
438 | // Wrap the workspace's children in a container | 438 | // Wrap the workspace's children in a container |
439 | struct sway_container *workspace = con; | 439 | struct sway_container *workspace = con; |
440 | con = container_wrap_children(con); | 440 | con = workspace_wrap_children(con); |
441 | workspace->layout = L_HORIZ; | 441 | workspace->layout = L_HORIZ; |
442 | } | 442 | } |
443 | 443 | ||
diff --git a/sway/commands/rename.c b/sway/commands/rename.c index c6952bbb..c69bbdac 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "sway/commands.h" | 6 | #include "sway/commands.h" |
7 | #include "sway/config.h" | 7 | #include "sway/config.h" |
8 | #include "sway/ipc-server.h" | 8 | #include "sway/ipc-server.h" |
9 | #include "sway/output.h" | ||
9 | #include "sway/tree/container.h" | 10 | #include "sway/tree/container.h" |
10 | #include "sway/tree/workspace.h" | 11 | #include "sway/tree/workspace.h" |
11 | 12 | ||
@@ -82,7 +83,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { | |||
82 | free(workspace->name); | 83 | free(workspace->name); |
83 | workspace->name = new_name; | 84 | workspace->name = new_name; |
84 | 85 | ||
85 | container_sort_workspaces(workspace->parent); | 86 | output_sort_workspaces(workspace->parent); |
86 | ipc_event_workspace(NULL, workspace, "rename"); | 87 | ipc_event_workspace(NULL, workspace, "rename"); |
87 | 88 | ||
88 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 89 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c index cf153a0a..dd7d170c 100644 --- a/sway/commands/show_marks.c +++ b/sway/commands/show_marks.c | |||
@@ -24,8 +24,7 @@ struct cmd_results *cmd_show_marks(int argc, char **argv) { | |||
24 | config->show_marks = parse_boolean(argv[0], config->show_marks); | 24 | config->show_marks = parse_boolean(argv[0], config->show_marks); |
25 | 25 | ||
26 | if (config->show_marks) { | 26 | if (config->show_marks) { |
27 | container_for_each_descendant(&root_container, | 27 | root_for_each_container(rebuild_marks_iterator, NULL); |
28 | rebuild_marks_iterator, NULL); | ||
29 | } | 28 | } |
30 | 29 | ||
31 | for (int i = 0; i < root_container.children->length; ++i) { | 30 | for (int i = 0; i < root_container.children->length; ++i) { |
diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 4e3a9cce..615e6b1d 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c | |||
@@ -50,13 +50,13 @@ struct cmd_results *cmd_swap(int argc, char **argv) { | |||
50 | if (strcasecmp(argv[2], "id") == 0) { | 50 | if (strcasecmp(argv[2], "id") == 0) { |
51 | #ifdef HAVE_XWAYLAND | 51 | #ifdef HAVE_XWAYLAND |
52 | xcb_window_t id = strtol(value, NULL, 0); | 52 | xcb_window_t id = strtol(value, NULL, 0); |
53 | other = container_find(&root_container, test_id, (void *)&id); | 53 | other = root_find_container(test_id, (void *)&id); |
54 | #endif | 54 | #endif |
55 | } else if (strcasecmp(argv[2], "con_id") == 0) { | 55 | } else if (strcasecmp(argv[2], "con_id") == 0) { |
56 | size_t con_id = atoi(value); | 56 | size_t con_id = atoi(value); |
57 | other = container_find(&root_container, test_con_id, (void *)con_id); | 57 | other = root_find_container(test_con_id, (void *)con_id); |
58 | } else if (strcasecmp(argv[2], "mark") == 0) { | 58 | } else if (strcasecmp(argv[2], "mark") == 0) { |
59 | other = container_find(&root_container, test_mark, (void *)value); | 59 | other = root_find_container(test_mark, (void *)value); |
60 | } else { | 60 | } else { |
61 | free(value); | 61 | free(value); |
62 | return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); | 62 | return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); |
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c index 44ceccee..c183785b 100644 --- a/sway/commands/unmark.c +++ b/sway/commands/unmark.c | |||
@@ -52,8 +52,7 @@ struct cmd_results *cmd_unmark(int argc, char **argv) { | |||
52 | view_find_and_unmark(mark); | 52 | view_find_and_unmark(mark); |
53 | } else { | 53 | } else { |
54 | // Remove all marks from all views | 54 | // Remove all marks from all views |
55 | container_for_each_descendant(&root_container, | 55 | root_for_each_container(remove_all_marks_iterator, NULL); |
56 | remove_all_marks_iterator, NULL); | ||
57 | } | 56 | } |
58 | free(mark); | 57 | free(mark); |
59 | 58 | ||
diff --git a/sway/config.c b/sway/config.c index bd14222a..642abbac 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -822,18 +822,7 @@ void config_update_font_height(bool recalculate) { | |||
822 | size_t prev_max_height = config->font_height; | 822 | size_t prev_max_height = config->font_height; |
823 | config->font_height = 0; | 823 | config->font_height = 0; |
824 | 824 | ||
825 | container_for_each_descendant(&root_container, | 825 | root_for_each_container(find_font_height_iterator, &recalculate); |
826 | find_font_height_iterator, &recalculate); | ||
827 | |||
828 | // Also consider floating views | ||
829 | for (int i = 0; i < root_container.children->length; ++i) { | ||
830 | struct sway_container *output = root_container.children->items[i]; | ||
831 | for (int j = 0; j < output->children->length; ++j) { | ||
832 | struct sway_container *ws = output->children->items[j]; | ||
833 | container_for_each_descendant(ws->sway_workspace->floating, | ||
834 | find_font_height_iterator, &recalculate); | ||
835 | } | ||
836 | } | ||
837 | 826 | ||
838 | if (config->font_height != prev_max_height) { | 827 | if (config->font_height != prev_max_height) { |
839 | arrange_windows(&root_container); | 828 | arrange_windows(&root_container); |
diff --git a/sway/criteria.c b/sway/criteria.c index a5df1eef..81c2325a 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -167,8 +167,7 @@ static bool criteria_matches_view(struct criteria *criteria, | |||
167 | return false; | 167 | return false; |
168 | } | 168 | } |
169 | list_t *urgent_views = create_list(); | 169 | list_t *urgent_views = create_list(); |
170 | container_for_each_descendant(&root_container, | 170 | root_for_each_container(find_urgent_iterator, urgent_views); |
171 | find_urgent_iterator, urgent_views); | ||
172 | list_stable_sort(urgent_views, cmp_urgent); | 171 | list_stable_sort(urgent_views, cmp_urgent); |
173 | struct sway_view *target; | 172 | struct sway_view *target; |
174 | if (criteria->urgent == 'o') { // oldest | 173 | if (criteria->urgent == 'o') { // oldest |
@@ -228,17 +227,7 @@ list_t *criteria_get_views(struct criteria *criteria) { | |||
228 | .criteria = criteria, | 227 | .criteria = criteria, |
229 | .matches = matches, | 228 | .matches = matches, |
230 | }; | 229 | }; |
231 | container_for_each_descendant(&root_container, | 230 | root_for_each_container(criteria_get_views_iterator, &data); |
232 | criteria_get_views_iterator, &data); | ||
233 | |||
234 | // Scratchpad items which are hidden are not in the tree. | ||
235 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
236 | struct sway_container *con = | ||
237 | root_container.sway_root->scratchpad->items[i]; | ||
238 | if (!con->parent) { | ||
239 | criteria_get_views_iterator(con, &data); | ||
240 | } | ||
241 | } | ||
242 | return matches; | 231 | return matches; |
243 | } | 232 | } |
244 | 233 | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b4564fac..1e4f196b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -304,15 +304,14 @@ struct send_frame_done_data { | |||
304 | 304 | ||
305 | static void send_frame_done_container_iterator(struct sway_container *con, | 305 | static void send_frame_done_container_iterator(struct sway_container *con, |
306 | void *_data) { | 306 | void *_data) { |
307 | struct send_frame_done_data *data = _data; | 307 | if (con->type != C_VIEW) { |
308 | if (!sway_assert(con->type == C_VIEW, "expected a view")) { | ||
309 | return; | 308 | return; |
310 | } | 309 | } |
311 | |||
312 | if (!view_is_visible(con->sway_view)) { | 310 | if (!view_is_visible(con->sway_view)) { |
313 | return; | 311 | return; |
314 | } | 312 | } |
315 | 313 | ||
314 | struct send_frame_done_data *data = _data; | ||
316 | output_view_for_each_surface(data->output, con->sway_view, | 315 | output_view_for_each_surface(data->output, con->sway_view, |
317 | send_frame_done_iterator, data->when); | 316 | send_frame_done_iterator, data->when); |
318 | } | 317 | } |
@@ -323,8 +322,8 @@ static void send_frame_done_container(struct sway_output *output, | |||
323 | .output = output, | 322 | .output = output, |
324 | .when = when, | 323 | .when = when, |
325 | }; | 324 | }; |
326 | container_descendants(con, C_VIEW, | 325 | output_for_each_container(output->swayc, |
327 | send_frame_done_container_iterator, &data); | 326 | send_frame_done_container_iterator, &data); |
328 | } | 327 | } |
329 | 328 | ||
330 | static void send_frame_done(struct sway_output *output, struct timespec *when) { | 329 | static void send_frame_done(struct sway_output *output, struct timespec *when) { |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3b70b471..762b8081 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -215,6 +215,19 @@ static enum wlr_edges find_resize_edge(struct sway_container *cont, | |||
215 | return edge; | 215 | return edge; |
216 | } | 216 | } |
217 | 217 | ||
218 | static void handle_down_motion(struct sway_seat *seat, | ||
219 | struct sway_cursor *cursor, uint32_t time_msec) { | ||
220 | struct sway_container *con = seat->op_container; | ||
221 | if (seat_is_input_allowed(seat, con->sway_view->surface)) { | ||
222 | double moved_x = cursor->cursor->x - seat->op_ref_lx; | ||
223 | double moved_y = cursor->cursor->y - seat->op_ref_ly; | ||
224 | double sx = seat->op_ref_con_lx + moved_x; | ||
225 | double sy = seat->op_ref_con_ly + moved_y; | ||
226 | wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy); | ||
227 | } | ||
228 | seat->op_moved = true; | ||
229 | } | ||
230 | |||
218 | static void handle_move_motion(struct sway_seat *seat, | 231 | static void handle_move_motion(struct sway_seat *seat, |
219 | struct sway_cursor *cursor) { | 232 | struct sway_cursor *cursor) { |
220 | struct sway_container *con = seat->op_container; | 233 | struct sway_container *con = seat->op_container; |
@@ -397,6 +410,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
397 | 410 | ||
398 | if (seat->operation != OP_NONE) { | 411 | if (seat->operation != OP_NONE) { |
399 | switch (seat->operation) { | 412 | switch (seat->operation) { |
413 | case OP_DOWN: | ||
414 | handle_down_motion(seat, cursor, time_msec); | ||
415 | break; | ||
400 | case OP_MOVE: | 416 | case OP_MOVE: |
401 | handle_move_motion(seat, cursor); | 417 | handle_move_motion(seat, cursor); |
402 | break; | 418 | break; |
@@ -726,13 +742,13 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
726 | } | 742 | } |
727 | 743 | ||
728 | // Via mod+click | 744 | // Via mod+click |
729 | struct sway_container *floater = cont; | ||
730 | while (floater->parent->layout != L_FLOATING) { | ||
731 | floater = floater->parent; | ||
732 | } | ||
733 | uint32_t btn_resize = config->floating_mod_inverse ? | 745 | uint32_t btn_resize = config->floating_mod_inverse ? |
734 | BTN_LEFT : BTN_RIGHT; | 746 | BTN_LEFT : BTN_RIGHT; |
735 | if (button == btn_resize) { | 747 | if (mod_pressed && button == btn_resize) { |
748 | struct sway_container *floater = cont; | ||
749 | while (floater->parent->layout != L_FLOATING) { | ||
750 | floater = floater->parent; | ||
751 | } | ||
736 | edge = 0; | 752 | edge = 0; |
737 | edge |= cursor->cursor->x > floater->x + floater->width / 2 ? | 753 | edge |= cursor->cursor->x > floater->x + floater->width / 2 ? |
738 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; | 754 | WLR_EDGE_RIGHT : WLR_EDGE_LEFT; |
@@ -743,6 +759,14 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
743 | } | 759 | } |
744 | } | 760 | } |
745 | 761 | ||
762 | // Handle mousedown on a container surface | ||
763 | if (surface && cont && state == WLR_BUTTON_PRESSED) { | ||
764 | seat_set_focus(seat, cont); | ||
765 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
766 | seat_begin_down(seat, cont, button, sx, sy); | ||
767 | return; | ||
768 | } | ||
769 | |||
746 | // Handle clicking a container surface | 770 | // Handle clicking a container surface |
747 | if (cont) { | 771 | if (cont) { |
748 | seat_set_focus(seat, cont); | 772 | seat_set_focus(seat, cont); |
diff --git a/sway/input/seat.c b/sway/input/seat.c index fa41904a..d35c62a0 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -313,9 +313,6 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) { | |||
313 | 313 | ||
314 | static void collect_focus_iter(struct sway_container *con, void *data) { | 314 | static void collect_focus_iter(struct sway_container *con, void *data) { |
315 | struct sway_seat *seat = data; | 315 | struct sway_seat *seat = data; |
316 | if (con->type > C_WORKSPACE) { | ||
317 | return; | ||
318 | } | ||
319 | struct sway_seat_container *seat_con = | 316 | struct sway_seat_container *seat_con = |
320 | seat_container_from_container(seat, con); | 317 | seat_container_from_container(seat, con); |
321 | if (!seat_con) { | 318 | if (!seat_con) { |
@@ -349,7 +346,8 @@ struct sway_seat *seat_create(struct sway_input_manager *input, | |||
349 | // init the focus stack | 346 | // init the focus stack |
350 | wl_list_init(&seat->focus_stack); | 347 | wl_list_init(&seat->focus_stack); |
351 | 348 | ||
352 | container_for_each_descendant(&root_container, collect_focus_iter, seat); | 349 | root_for_each_workspace(collect_focus_iter, seat); |
350 | root_for_each_container(collect_focus_iter, seat); | ||
353 | 351 | ||
354 | wl_signal_add(&root_container.sway_root->events.new_container, | 352 | wl_signal_add(&root_container.sway_root->events.new_container, |
355 | &seat->new_container); | 353 | &seat->new_container); |
@@ -954,6 +952,18 @@ struct seat_config *seat_get_config(struct sway_seat *seat) { | |||
954 | return NULL; | 952 | return NULL; |
955 | } | 953 | } |
956 | 954 | ||
955 | void seat_begin_down(struct sway_seat *seat, struct sway_container *con, | ||
956 | uint32_t button, double sx, double sy) { | ||
957 | seat->operation = OP_DOWN; | ||
958 | seat->op_container = con; | ||
959 | seat->op_button = button; | ||
960 | seat->op_ref_lx = seat->cursor->cursor->x; | ||
961 | seat->op_ref_ly = seat->cursor->cursor->y; | ||
962 | seat->op_ref_con_lx = sx; | ||
963 | seat->op_ref_con_ly = sy; | ||
964 | seat->op_moved = false; | ||
965 | } | ||
966 | |||
957 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, | 967 | void seat_begin_move(struct sway_seat *seat, struct sway_container *con, |
958 | uint32_t button) { | 968 | uint32_t button) { |
959 | if (!seat->cursor) { | 969 | if (!seat->cursor) { |
@@ -1007,6 +1017,7 @@ void seat_begin_resize_tiling(struct sway_seat *seat, | |||
1007 | } | 1017 | } |
1008 | 1018 | ||
1009 | void seat_end_mouse_operation(struct sway_seat *seat) { | 1019 | void seat_end_mouse_operation(struct sway_seat *seat) { |
1020 | enum sway_seat_operation operation = seat->operation; | ||
1010 | if (seat->operation == OP_MOVE) { | 1021 | if (seat->operation == OP_MOVE) { |
1011 | // We "move" the container to its own location so it discovers its | 1022 | // We "move" the container to its own location so it discovers its |
1012 | // output again. | 1023 | // output again. |
@@ -1015,7 +1026,19 @@ void seat_end_mouse_operation(struct sway_seat *seat) { | |||
1015 | } | 1026 | } |
1016 | seat->operation = OP_NONE; | 1027 | seat->operation = OP_NONE; |
1017 | seat->op_container = NULL; | 1028 | seat->op_container = NULL; |
1018 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 1029 | if (operation == OP_DOWN) { |
1030 | // Set the cursor's previous coords to the x/y at the start of the | ||
1031 | // operation, so the container change will be detected if using | ||
1032 | // focus_follows_mouse and the cursor moved off the original container | ||
1033 | // during the operation. | ||
1034 | seat->cursor->previous.x = seat->op_ref_lx; | ||
1035 | seat->cursor->previous.y = seat->op_ref_ly; | ||
1036 | if (seat->op_moved) { | ||
1037 | cursor_send_pointer_motion(seat->cursor, 0, true); | ||
1038 | } | ||
1039 | } else { | ||
1040 | cursor_set_image(seat->cursor, "left_ptr", NULL); | ||
1041 | } | ||
1019 | } | 1042 | } |
1020 | 1043 | ||
1021 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 1044 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index dad1f310..34e940ad 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -522,7 +522,7 @@ void ipc_client_disconnect(struct ipc_client *client) { | |||
522 | 522 | ||
523 | static void ipc_get_workspaces_callback(struct sway_container *workspace, | 523 | static void ipc_get_workspaces_callback(struct sway_container *workspace, |
524 | void *data) { | 524 | void *data) { |
525 | if (workspace->type != C_WORKSPACE) { | 525 | if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { |
526 | return; | 526 | return; |
527 | } | 527 | } |
528 | json_object *workspace_json = ipc_json_describe_container(workspace); | 528 | json_object *workspace_json = ipc_json_describe_container(workspace); |
@@ -631,8 +631,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
631 | case IPC_GET_WORKSPACES: | 631 | case IPC_GET_WORKSPACES: |
632 | { | 632 | { |
633 | json_object *workspaces = json_object_new_array(); | 633 | json_object *workspaces = json_object_new_array(); |
634 | container_for_each_descendant(&root_container, | 634 | root_for_each_workspace(ipc_get_workspaces_callback, workspaces); |
635 | ipc_get_workspaces_callback, workspaces); | ||
636 | const char *json_string = json_object_to_json_string(workspaces); | 635 | const char *json_string = json_object_to_json_string(workspaces); |
637 | client_valid = | 636 | client_valid = |
638 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 637 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
@@ -729,8 +728,7 @@ void ipc_client_handle_command(struct ipc_client *client) { | |||
729 | case IPC_GET_MARKS: | 728 | case IPC_GET_MARKS: |
730 | { | 729 | { |
731 | json_object *marks = json_object_new_array(); | 730 | json_object *marks = json_object_new_array(); |
732 | container_descendants(&root_container, C_VIEW, ipc_get_marks_callback, | 731 | root_for_each_container(ipc_get_marks_callback, marks); |
733 | marks); | ||
734 | const char *json_string = json_object_to_json_string(marks); | 732 | const char *json_string = json_object_to_json_string(marks); |
735 | client_valid = | 733 | client_valid = |
736 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); | 734 | ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); |
diff --git a/sway/tree/container.c b/sway/tree/container.c index b3f3a344..2a428ca5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -270,7 +270,7 @@ static struct sway_container *container_output_destroy( | |||
270 | container_destroy(workspace); | 270 | container_destroy(workspace); |
271 | } | 271 | } |
272 | 272 | ||
273 | container_sort_workspaces(new_output); | 273 | output_sort_workspaces(new_output); |
274 | } | 274 | } |
275 | } | 275 | } |
276 | } | 276 | } |
@@ -432,8 +432,10 @@ struct sway_container *container_close(struct sway_container *con) { | |||
432 | 432 | ||
433 | if (con->type == C_VIEW) { | 433 | if (con->type == C_VIEW) { |
434 | view_close(con->sway_view); | 434 | view_close(con->sway_view); |
435 | } else { | 435 | } else if (con->type == C_CONTAINER) { |
436 | container_for_each_descendant(con, container_close_func, NULL); | 436 | container_for_each_child(con, container_close_func, NULL); |
437 | } else if (con->type == C_WORKSPACE) { | ||
438 | workspace_for_each_container(con, container_close_func, NULL); | ||
437 | } | 439 | } |
438 | 440 | ||
439 | return parent; | 441 | return parent; |
@@ -465,23 +467,12 @@ struct sway_container *container_view_create(struct sway_container *sibling, | |||
465 | return swayc; | 467 | return swayc; |
466 | } | 468 | } |
467 | 469 | ||
468 | void container_descendants(struct sway_container *root, | 470 | struct sway_container *container_find_child(struct sway_container *container, |
469 | enum sway_container_type type, | ||
470 | void (*func)(struct sway_container *item, void *data), void *data) { | ||
471 | if (!root->children || !root->children->length) { | ||
472 | return; | ||
473 | } | ||
474 | for (int i = 0; i < root->children->length; ++i) { | ||
475 | struct sway_container *item = root->children->items[i]; | ||
476 | if (item->type == type) { | ||
477 | func(item, data); | ||
478 | } | ||
479 | container_descendants(item, type, func, data); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | struct sway_container *container_find(struct sway_container *container, | ||
484 | bool (*test)(struct sway_container *view, void *data), void *data) { | 471 | bool (*test)(struct sway_container *view, void *data), void *data) { |
472 | if (!sway_assert(container->type == C_CONTAINER || | ||
473 | container->type == C_VIEW, "Expected a container or view")) { | ||
474 | return NULL; | ||
475 | } | ||
485 | if (!container->children) { | 476 | if (!container->children) { |
486 | return NULL; | 477 | return NULL; |
487 | } | 478 | } |
@@ -489,15 +480,11 @@ struct sway_container *container_find(struct sway_container *container, | |||
489 | struct sway_container *child = container->children->items[i]; | 480 | struct sway_container *child = container->children->items[i]; |
490 | if (test(child, data)) { | 481 | if (test(child, data)) { |
491 | return child; | 482 | return child; |
492 | } else { | ||
493 | struct sway_container *res = container_find(child, test, data); | ||
494 | if (res) { | ||
495 | return res; | ||
496 | } | ||
497 | } | 483 | } |
498 | } | 484 | struct sway_container *res = container_find_child(child, test, data); |
499 | if (container->type == C_WORKSPACE) { | 485 | if (res) { |
500 | return container_find(container->sway_workspace->floating, test, data); | 486 | return res; |
487 | } | ||
501 | } | 488 | } |
502 | return NULL; | 489 | return NULL; |
503 | } | 490 | } |
@@ -743,26 +730,20 @@ struct sway_container *container_at(struct sway_container *workspace, | |||
743 | return NULL; | 730 | return NULL; |
744 | } | 731 | } |
745 | 732 | ||
746 | void container_for_each_descendant(struct sway_container *container, | 733 | void container_for_each_child(struct sway_container *container, |
747 | void (*f)(struct sway_container *container, void *data), | 734 | void (*f)(struct sway_container *container, void *data), |
748 | void *data) { | 735 | void *data) { |
749 | if (!container) { | 736 | if (!sway_assert(container->type == C_CONTAINER || |
737 | container->type == C_VIEW, "Expected a container or view")) { | ||
750 | return; | 738 | return; |
751 | } | 739 | } |
752 | if (container->children) { | 740 | if (container->children) { |
753 | for (int i = 0; i < container->children->length; ++i) { | 741 | for (int i = 0; i < container->children->length; ++i) { |
754 | struct sway_container *child = container->children->items[i]; | 742 | struct sway_container *child = container->children->items[i]; |
755 | container_for_each_descendant(child, f, data); | 743 | f(child, data); |
756 | } | 744 | container_for_each_child(child, f, data); |
757 | } | ||
758 | if (container->type == C_WORKSPACE) { | ||
759 | struct sway_container *floating = container->sway_workspace->floating; | ||
760 | for (int i = 0; i < floating->children->length; ++i) { | ||
761 | struct sway_container *child = floating->children->items[i]; | ||
762 | container_for_each_descendant(child, f, data); | ||
763 | } | 745 | } |
764 | } | 746 | } |
765 | f(container, data); | ||
766 | } | 747 | } |
767 | 748 | ||
768 | bool container_has_ancestor(struct sway_container *descendant, | 749 | bool container_has_ancestor(struct sway_container *descendant, |
@@ -1199,13 +1180,12 @@ void container_set_dirty(struct sway_container *container) { | |||
1199 | list_add(server.dirty_containers, container); | 1180 | list_add(server.dirty_containers, container); |
1200 | } | 1181 | } |
1201 | 1182 | ||
1202 | static bool find_urgent_iterator(struct sway_container *con, | 1183 | static bool find_urgent_iterator(struct sway_container *con, void *data) { |
1203 | void *data) { | ||
1204 | return con->type == C_VIEW && view_is_urgent(con->sway_view); | 1184 | return con->type == C_VIEW && view_is_urgent(con->sway_view); |
1205 | } | 1185 | } |
1206 | 1186 | ||
1207 | bool container_has_urgent_child(struct sway_container *container) { | 1187 | bool container_has_urgent_child(struct sway_container *container) { |
1208 | return container_find(container, find_urgent_iterator, NULL); | 1188 | return container_find_child(container, find_urgent_iterator, NULL); |
1209 | } | 1189 | } |
1210 | 1190 | ||
1211 | void container_end_mouse_operation(struct sway_container *container) { | 1191 | void container_end_mouse_operation(struct sway_container *container) { |
@@ -1237,7 +1217,7 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { | |||
1237 | container_set_fullscreen(workspace->sway_workspace->fullscreen, false); | 1217 | container_set_fullscreen(workspace->sway_workspace->fullscreen, false); |
1238 | } | 1218 | } |
1239 | 1219 | ||
1240 | container_for_each_descendant(container, set_fullscreen_iterator, &enable); | 1220 | container_for_each_child(container, set_fullscreen_iterator, &enable); |
1241 | 1221 | ||
1242 | container->is_fullscreen = enable; | 1222 | container->is_fullscreen = enable; |
1243 | 1223 | ||
@@ -1306,15 +1286,3 @@ bool container_is_fullscreen_or_child(struct sway_container *container) { | |||
1306 | 1286 | ||
1307 | return false; | 1287 | return false; |
1308 | } | 1288 | } |
1309 | |||
1310 | struct sway_container *container_wrap_children(struct sway_container *parent) { | ||
1311 | struct sway_container *middle = container_create(C_CONTAINER); | ||
1312 | middle->layout = parent->layout; | ||
1313 | while (parent->children->length) { | ||
1314 | struct sway_container *child = parent->children->items[0]; | ||
1315 | container_remove_child(child); | ||
1316 | container_add_child(middle, child); | ||
1317 | } | ||
1318 | container_add_child(parent, middle); | ||
1319 | return middle; | ||
1320 | } | ||
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 2b710403..49ec806e 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 <ctype.h> | ||
3 | #include <math.h> | 2 | #include <math.h> |
4 | #include <stdbool.h> | 3 | #include <stdbool.h> |
5 | #include <stdlib.h> | 4 | #include <stdlib.h> |
@@ -591,28 +590,6 @@ enum sway_container_layout container_get_default_layout( | |||
591 | } | 590 | } |
592 | } | 591 | } |
593 | 592 | ||
594 | static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | ||
595 | struct sway_container *a = *(void **)_a; | ||
596 | struct sway_container *b = *(void **)_b; | ||
597 | int retval = 0; | ||
598 | |||
599 | if (isdigit(a->name[0]) && isdigit(b->name[0])) { | ||
600 | int a_num = strtol(a->name, NULL, 10); | ||
601 | int b_num = strtol(b->name, NULL, 10); | ||
602 | retval = (a_num < b_num) ? -1 : (a_num > b_num); | ||
603 | } else if (isdigit(a->name[0])) { | ||
604 | retval = -1; | ||
605 | } else if (isdigit(b->name[0])) { | ||
606 | retval = 1; | ||
607 | } | ||
608 | |||
609 | return retval; | ||
610 | } | ||
611 | |||
612 | void container_sort_workspaces(struct sway_container *output) { | ||
613 | list_stable_sort(output->children, sort_workspace_cmp_qsort); | ||
614 | } | ||
615 | |||
616 | /** | 593 | /** |
617 | * Get swayc in the direction of newly entered output. | 594 | * Get swayc in the direction of newly entered output. |
618 | */ | 595 | */ |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 31e3bf9b..6da63064 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | 1 | #define _POSIX_C_SOURCE 200809L |
2 | #include <ctype.h> | ||
2 | #include <string.h> | 3 | #include <string.h> |
3 | #include <strings.h> | 4 | #include <strings.h> |
4 | #include "sway/ipc-server.h" | 5 | #include "sway/ipc-server.h" |
@@ -28,7 +29,7 @@ static void restore_workspaces(struct sway_container *output) { | |||
28 | } | 29 | } |
29 | } | 30 | } |
30 | 31 | ||
31 | container_sort_workspaces(output); | 32 | output_sort_workspaces(output); |
32 | } | 33 | } |
33 | 34 | ||
34 | struct sway_container *output_create( | 35 | struct sway_container *output_create( |
@@ -102,3 +103,73 @@ struct sway_container *output_create( | |||
102 | return output; | 103 | return output; |
103 | } | 104 | } |
104 | 105 | ||
106 | void output_for_each_workspace(struct sway_container *output, | ||
107 | void (*f)(struct sway_container *con, void *data), void *data) { | ||
108 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | ||
109 | return; | ||
110 | } | ||
111 | for (int i = 0; i < output->children->length; ++i) { | ||
112 | struct sway_container *workspace = output->children->items[i]; | ||
113 | f(workspace, data); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void output_for_each_container(struct sway_container *output, | ||
118 | void (*f)(struct sway_container *con, void *data), void *data) { | ||
119 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | ||
120 | return; | ||
121 | } | ||
122 | for (int i = 0; i < output->children->length; ++i) { | ||
123 | struct sway_container *workspace = output->children->items[i]; | ||
124 | workspace_for_each_container(workspace, f, data); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | struct sway_container *output_find_workspace(struct sway_container *output, | ||
129 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
130 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | ||
131 | return NULL; | ||
132 | } | ||
133 | for (int i = 0; i < output->children->length; ++i) { | ||
134 | struct sway_container *workspace = output->children->items[i]; | ||
135 | if (test(workspace, data)) { | ||
136 | return workspace; | ||
137 | } | ||
138 | } | ||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | struct sway_container *output_find_container(struct sway_container *output, | ||
143 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
144 | if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { | ||
145 | return NULL; | ||
146 | } | ||
147 | struct sway_container *result = NULL; | ||
148 | for (int i = 0; i < output->children->length; ++i) { | ||
149 | struct sway_container *workspace = output->children->items[i]; | ||
150 | if ((result = workspace_find_container(workspace, test, data))) { | ||
151 | return result; | ||
152 | } | ||
153 | } | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
157 | static int sort_workspace_cmp_qsort(const void *_a, const void *_b) { | ||
158 | struct sway_container *a = *(void **)_a; | ||
159 | struct sway_container *b = *(void **)_b; | ||
160 | |||
161 | if (isdigit(a->name[0]) && isdigit(b->name[0])) { | ||
162 | int a_num = strtol(a->name, NULL, 10); | ||
163 | int b_num = strtol(b->name, NULL, 10); | ||
164 | return (a_num < b_num) ? -1 : (a_num > b_num); | ||
165 | } else if (isdigit(a->name[0])) { | ||
166 | return -1; | ||
167 | } else if (isdigit(b->name[0])) { | ||
168 | return 1; | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | void output_sort_workspaces(struct sway_container *output) { | ||
174 | list_stable_sort(output->children, sort_workspace_cmp_qsort); | ||
175 | } | ||
diff --git a/sway/tree/root.c b/sway/tree/root.c index fc908cc1..8d8f42dc 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c | |||
@@ -256,3 +256,81 @@ void root_record_workspace_pid(pid_t pid) { | |||
256 | &pw->output_destroy); | 256 | &pw->output_destroy); |
257 | wl_list_insert(&pid_workspaces, &pw->link); | 257 | wl_list_insert(&pid_workspaces, &pw->link); |
258 | } | 258 | } |
259 | |||
260 | void root_for_each_workspace(void (*f)(struct sway_container *con, void *data), | ||
261 | void *data) { | ||
262 | for (int i = 0; i < root_container.children->length; ++i) { | ||
263 | struct sway_container *output = root_container.children->items[i]; | ||
264 | output_for_each_workspace(output, f, data); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | void root_for_each_container(void (*f)(struct sway_container *con, void *data), | ||
269 | void *data) { | ||
270 | for (int i = 0; i < root_container.children->length; ++i) { | ||
271 | struct sway_container *output = root_container.children->items[i]; | ||
272 | output_for_each_container(output, f, data); | ||
273 | } | ||
274 | |||
275 | // Scratchpad | ||
276 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
277 | struct sway_container *container = | ||
278 | root_container.sway_root->scratchpad->items[i]; | ||
279 | // If the container has a parent then it's visible on a workspace | ||
280 | // and will have been iterated in the previous for loop. So we only | ||
281 | // iterate the hidden scratchpad containers here. | ||
282 | if (!container->parent) { | ||
283 | f(container, data); | ||
284 | container_for_each_child(container, f, data); | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | |||
289 | struct sway_container *root_find_output( | ||
290 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
291 | for (int i = 0; i < root_container.children->length; ++i) { | ||
292 | struct sway_container *output = root_container.children->items[i]; | ||
293 | if (test(output, data)) { | ||
294 | return output; | ||
295 | } | ||
296 | } | ||
297 | return NULL; | ||
298 | } | ||
299 | |||
300 | struct sway_container *root_find_workspace( | ||
301 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
302 | struct sway_container *result = NULL; | ||
303 | for (int i = 0; i < root_container.children->length; ++i) { | ||
304 | struct sway_container *output = root_container.children->items[i]; | ||
305 | if ((result = output_find_workspace(output, test, data))) { | ||
306 | return result; | ||
307 | } | ||
308 | } | ||
309 | return NULL; | ||
310 | } | ||
311 | |||
312 | struct sway_container *root_find_container( | ||
313 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
314 | struct sway_container *result = NULL; | ||
315 | for (int i = 0; i < root_container.children->length; ++i) { | ||
316 | struct sway_container *output = root_container.children->items[i]; | ||
317 | if ((result = output_find_container(output, test, data))) { | ||
318 | return result; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | // Scratchpad | ||
323 | for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { | ||
324 | struct sway_container *container = | ||
325 | root_container.sway_root->scratchpad->items[i]; | ||
326 | if (!container->parent) { | ||
327 | if (test(container, data)) { | ||
328 | return container; | ||
329 | } | ||
330 | if ((result = container_find_child(container, test, data))) { | ||
331 | return result; | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | return NULL; | ||
336 | } | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index fbe4bc58..1c1fdb47 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -881,8 +881,8 @@ static bool find_by_mark_iterator(struct sway_container *con, | |||
881 | } | 881 | } |
882 | 882 | ||
883 | struct sway_view *view_find_mark(char *mark) { | 883 | struct sway_view *view_find_mark(char *mark) { |
884 | struct sway_container *container = container_find(&root_container, | 884 | struct sway_container *container = root_find_container( |
885 | find_by_mark_iterator, mark); | 885 | find_by_mark_iterator, mark); |
886 | if (!container) { | 886 | if (!container) { |
887 | return NULL; | 887 | return NULL; |
888 | } | 888 | } |
@@ -890,7 +890,7 @@ struct sway_view *view_find_mark(char *mark) { | |||
890 | } | 890 | } |
891 | 891 | ||
892 | bool view_find_and_unmark(char *mark) { | 892 | bool view_find_and_unmark(char *mark) { |
893 | struct sway_container *container = container_find(&root_container, | 893 | struct sway_container *container = root_find_container( |
894 | find_by_mark_iterator, mark); | 894 | find_by_mark_iterator, mark); |
895 | if (!container) { | 895 | if (!container) { |
896 | return false; | 896 | return false; |
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index e7383de0..b7090de6 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c | |||
@@ -75,7 +75,7 @@ struct sway_container *workspace_create(struct sway_container *output, | |||
75 | workspace_output_add_priority(workspace, output); | 75 | workspace_output_add_priority(workspace, output); |
76 | 76 | ||
77 | container_add_child(output, workspace); | 77 | container_add_child(output, workspace); |
78 | container_sort_workspaces(output); | 78 | output_sort_workspaces(output); |
79 | container_create_notify(workspace); | 79 | container_create_notify(workspace); |
80 | 80 | ||
81 | return workspace; | 81 | return workspace; |
@@ -244,8 +244,7 @@ struct sway_container *workspace_by_number(const char* name) { | |||
244 | if (wbnd.len <= 0) { | 244 | if (wbnd.len <= 0) { |
245 | return NULL; | 245 | return NULL; |
246 | } | 246 | } |
247 | return container_find(&root_container, | 247 | return root_find_workspace(_workspace_by_number, (void *) &wbnd); |
248 | _workspace_by_number, (void *) &wbnd); | ||
249 | } | 248 | } |
250 | 249 | ||
251 | static bool _workspace_by_name(struct sway_container *view, void *data) { | 250 | static bool _workspace_by_name(struct sway_container *view, void *data) { |
@@ -274,11 +273,11 @@ struct sway_container *workspace_by_name(const char *name) { | |||
274 | } else if (strcmp(name, "current") == 0) { | 273 | } else if (strcmp(name, "current") == 0) { |
275 | return current_workspace; | 274 | return current_workspace; |
276 | } else if (strcasecmp(name, "back_and_forth") == 0) { | 275 | } else if (strcasecmp(name, "back_and_forth") == 0) { |
277 | return prev_workspace_name ? container_find(&root_container, | 276 | return prev_workspace_name ? |
278 | _workspace_by_name, (void *)prev_workspace_name) : NULL; | 277 | root_find_workspace(_workspace_by_name, (void*)prev_workspace_name) |
278 | : NULL; | ||
279 | } else { | 279 | } else { |
280 | return container_find(&root_container, _workspace_by_name, | 280 | return root_find_workspace(_workspace_by_name, (void*)name); |
281 | (void *)name); | ||
282 | } | 281 | } |
283 | } | 282 | } |
284 | 283 | ||
@@ -518,8 +517,7 @@ struct sway_container *workspace_output_get_highest_available( | |||
518 | continue; | 517 | continue; |
519 | } | 518 | } |
520 | 519 | ||
521 | struct sway_container *output = container_find(&root_container, | 520 | struct sway_container *output = root_find_output(_output_by_name, name); |
522 | _output_by_name, name); | ||
523 | if (output) { | 521 | if (output) { |
524 | return output; | 522 | return output; |
525 | } | 523 | } |
@@ -528,8 +526,13 @@ struct sway_container *workspace_output_get_highest_available( | |||
528 | return NULL; | 526 | return NULL; |
529 | } | 527 | } |
530 | 528 | ||
529 | static bool find_urgent_iterator(struct sway_container *con, void *data) { | ||
530 | return con->type == C_VIEW && view_is_urgent(con->sway_view); | ||
531 | } | ||
532 | |||
531 | void workspace_detect_urgent(struct sway_container *workspace) { | 533 | void workspace_detect_urgent(struct sway_container *workspace) { |
532 | bool new_urgent = container_has_urgent_child(workspace); | 534 | bool new_urgent = (bool)workspace_find_container(workspace, |
535 | find_urgent_iterator, NULL); | ||
533 | 536 | ||
534 | if (workspace->sway_workspace->urgent != new_urgent) { | 537 | if (workspace->sway_workspace->urgent != new_urgent) { |
535 | workspace->sway_workspace->urgent = new_urgent; | 538 | workspace->sway_workspace->urgent = new_urgent; |
@@ -537,3 +540,65 @@ void workspace_detect_urgent(struct sway_container *workspace) { | |||
537 | container_damage_whole(workspace); | 540 | container_damage_whole(workspace); |
538 | } | 541 | } |
539 | } | 542 | } |
543 | |||
544 | void workspace_for_each_container(struct sway_container *ws, | ||
545 | void (*f)(struct sway_container *con, void *data), void *data) { | ||
546 | if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) { | ||
547 | return; | ||
548 | } | ||
549 | // Tiling | ||
550 | for (int i = 0; i < ws->children->length; ++i) { | ||
551 | struct sway_container *container = ws->children->items[i]; | ||
552 | f(container, data); | ||
553 | container_for_each_child(container, f, data); | ||
554 | } | ||
555 | // Floating | ||
556 | for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) { | ||
557 | struct sway_container *container = | ||
558 | ws->sway_workspace->floating->children->items[i]; | ||
559 | f(container, data); | ||
560 | container_for_each_child(container, f, data); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | struct sway_container *workspace_find_container(struct sway_container *ws, | ||
565 | bool (*test)(struct sway_container *con, void *data), void *data) { | ||
566 | if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) { | ||
567 | return NULL; | ||
568 | } | ||
569 | struct sway_container *result = NULL; | ||
570 | // Tiling | ||
571 | for (int i = 0; i < ws->children->length; ++i) { | ||
572 | struct sway_container *child = ws->children->items[i]; | ||
573 | if (test(child, data)) { | ||
574 | return child; | ||
575 | } | ||
576 | if ((result = container_find_child(child, test, data))) { | ||
577 | return result; | ||
578 | } | ||
579 | } | ||
580 | // Floating | ||
581 | for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) { | ||
582 | struct sway_container *child = | ||
583 | ws->sway_workspace->floating->children->items[i]; | ||
584 | if (test(child, data)) { | ||
585 | return child; | ||
586 | } | ||
587 | if ((result = container_find_child(child, test, data))) { | ||
588 | return result; | ||
589 | } | ||
590 | } | ||
591 | return NULL; | ||
592 | } | ||
593 | |||
594 | struct sway_container *workspace_wrap_children(struct sway_container *ws) { | ||
595 | struct sway_container *middle = container_create(C_CONTAINER); | ||
596 | middle->layout = ws->layout; | ||
597 | while (ws->children->length) { | ||
598 | struct sway_container *child = ws->children->items[0]; | ||
599 | container_remove_child(child); | ||
600 | container_add_child(middle, child); | ||
601 | } | ||
602 | container_add_child(ws, middle); | ||
603 | return middle; | ||
604 | } | ||