aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/input/seat.h20
-rw-r--r--include/sway/output.h14
-rw-r--r--include/sway/tree/container.h19
-rw-r--r--include/sway/tree/layout.h2
-rw-r--r--include/sway/tree/root.h15
-rw-r--r--include/sway/tree/workspace.h13
-rw-r--r--sway/commands/floating.c3
-rw-r--r--sway/commands/fullscreen.c3
-rw-r--r--sway/commands/hide_edge_borders.c2
-rw-r--r--sway/commands/move.c6
-rw-r--r--sway/commands/rename.c3
-rw-r--r--sway/commands/show_marks.c3
-rw-r--r--sway/commands/swap.c6
-rw-r--r--sway/commands/unmark.c3
-rw-r--r--sway/config.c13
-rw-r--r--sway/criteria.c15
-rw-r--r--sway/desktop/output.c9
-rw-r--r--sway/input/cursor.c34
-rw-r--r--sway/input/seat.c33
-rw-r--r--sway/ipc-server.c8
-rw-r--r--sway/tree/container.c76
-rw-r--r--sway/tree/layout.c23
-rw-r--r--sway/tree/output.c73
-rw-r--r--sway/tree/root.c78
-rw-r--r--sway/tree/view.c6
-rw-r--r--sway/tree/workspace.c85
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 {
struct wl_listener destroy;
};
+enum sway_seat_operation {
+ OP_NONE,
+ OP_DOWN,
+ OP_MOVE,
+ OP_RESIZE_FLOATING,
+ OP_RESIZE_TILING,
+};
+
struct sway_seat {
struct wlr_seat *wlr_seat;
struct sway_cursor *cursor;
@@ -54,13 +62,7 @@ struct sway_seat {
double touch_x, touch_y;
// Operations (drag and resize)
- enum {
- OP_NONE,
- OP_MOVE,
- OP_RESIZE_FLOATING,
- OP_RESIZE_TILING,
- } operation;
-
+ enum sway_seat_operation operation;
struct sway_container *op_container;
enum wlr_edges op_resize_edge;
uint32_t op_button;
@@ -68,6 +70,7 @@ struct sway_seat {
double op_ref_lx, op_ref_ly; // cursor's x/y at start of op
double op_ref_width, op_ref_height; // container's size at start of op
double op_ref_con_lx, op_ref_con_ly; // container's x/y at start of op
+ bool op_moved; // if the mouse moved during a down op
uint32_t last_button;
uint32_t last_button_serial;
@@ -157,6 +160,9 @@ bool seat_is_input_allowed(struct sway_seat *seat, struct wlr_surface *surface);
void drag_icon_update_position(struct sway_drag_icon *icon);
+void seat_begin_down(struct sway_seat *seat, struct sway_container *con,
+ uint32_t button, double sx, double sy);
+
void seat_begin_move(struct sway_seat *seat, struct sway_container *con,
uint32_t button);
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,
struct sway_container *output_by_name(const char *name);
+void output_sort_workspaces(struct sway_container *output);
+
void output_enable(struct sway_output *output);
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,
struct wl_list *drag_icons, sway_surface_iterator_func_t iterator,
void *user_data);
+void output_for_each_workspace(struct sway_container *output,
+ void (*f)(struct sway_container *con, void *data), void *data);
+
+void output_for_each_container(struct sway_container *output,
+ void (*f)(struct sway_container *con, void *data), void *data);
+
+struct sway_container *output_find_workspace(struct sway_container *output,
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
+struct sway_container *output_find_container(struct sway_container *output,
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
#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);
struct sway_container *container_close(struct sway_container *container);
-void container_descendants(struct sway_container *root,
- enum sway_container_type type,
- void (*func)(struct sway_container *item, void *data), void *data);
-
/**
* Search a container's descendants a container based on test criteria. Returns
* the first container that passes the test.
*/
-struct sway_container *container_find(struct sway_container *container,
+struct sway_container *container_find_child(struct sway_container *container,
bool (*test)(struct sway_container *view, void *data), void *data);
/**
@@ -244,10 +240,7 @@ struct sway_container *tiling_container_at(
struct sway_container *con, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy);
-/**
- * Apply the function for each child of the container depth first.
- */
-void container_for_each_descendant(struct sway_container *container,
+void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data), void *data);
/**
@@ -361,12 +354,4 @@ bool container_is_floating_or_child(struct sway_container *container);
*/
bool container_is_fullscreen_or_child(struct sway_container *container);
-/**
- * Wrap the children of parent in a new container. The new container will be the
- * only child of parent.
- *
- * The new container is returned.
- */
-struct sway_container *container_wrap_children(struct sway_container *parent);
-
#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,
enum sway_container_layout container_get_default_layout(
struct sway_container *con);
-void container_sort_workspaces(struct sway_container *output);
-
struct sway_container *container_get_in_direction(struct sway_container
*container, struct sway_seat *seat, enum movement_direction dir);
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);
void root_record_workspace_pid(pid_t pid);
+void root_for_each_workspace(void (*f)(struct sway_container *con, void *data),
+ void *data);
+
+void root_for_each_container(void (*f)(struct sway_container *con, void *data),
+ void *data);
+
+struct sway_container *root_find_output(
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
+struct sway_container *root_find_workspace(
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
+struct sway_container *root_find_container(
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
#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(
void workspace_detect_urgent(struct sway_container *workspace);
+void workspace_for_each_container(struct sway_container *ws,
+ void (*f)(struct sway_container *con, void *data), void *data);
+
+struct sway_container *workspace_find_container(struct sway_container *ws,
+ bool (*test)(struct sway_container *con, void *data), void *data);
+
+/**
+ * Wrap the workspace's tiling children in a new container.
+ * The new container will be the only direct tiling child of the workspace.
+ * The new container is returned.
+ */
+struct sway_container *workspace_wrap_children(struct sway_container *ws);
+
#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 @@
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
+#include "sway/tree/workspace.h"
#include "list.h"
struct cmd_results *cmd_floating(int argc, char **argv) {
@@ -24,7 +25,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) {
if (container->type == C_WORKSPACE) {
// Wrap the workspace's children in a container so we can float it
struct sway_container *workspace = container;
- container = container_wrap_children(container);
+ container = workspace_wrap_children(container);
workspace->layout = L_HORIZ;
seat_set_focus(config->handler_context.seat, container);
}
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 @@
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"
+#include "sway/tree/workspace.h"
#include "sway/tree/layout.h"
#include "util.h"
@@ -21,7 +22,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
if (container->type == C_WORKSPACE) {
// Wrap the workspace's children in a container so we can fullscreen it
struct sway_container *workspace = container;
- container = container_wrap_children(container);
+ container = workspace_wrap_children(container);
workspace->layout = L_HORIZ;
seat_set_focus(config->handler_context.seat, container);
}
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) {
"<none|vertical|horizontal|both|smart>'");
}
- container_for_each_descendant(&root_container, _configure_view, NULL);
+ root_for_each_container(_configure_view, NULL);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
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,
return cmd_results_new(CMD_FAILURE, "move",
"Can't move an empty workspace");
}
- current = container_wrap_children(current);
+ current = workspace_wrap_children(current);
} else if (current->type != C_CONTAINER && current->type != C_VIEW) {
return cmd_results_new(CMD_FAILURE, "move",
"Can only move containers and views.");
@@ -245,7 +245,7 @@ static void workspace_move_to_output(struct sway_container *workspace,
// Try to remove an empty workspace from the destination output.
container_reap_empty_recursive(new_output_focus);
- container_sort_workspaces(output);
+ output_sort_workspaces(output);
seat_set_focus(seat, output);
workspace_output_raise_priority(workspace, old_output, output);
ipc_event_workspace(NULL, workspace, "move");
@@ -437,7 +437,7 @@ static struct cmd_results *move_to_scratchpad(struct sway_container *con) {
if (con->type == C_WORKSPACE) {
// Wrap the workspace's children in a container
struct sway_container *workspace = con;
- con = container_wrap_children(con);
+ con = workspace_wrap_children(con);
workspace->layout = L_HORIZ;
}
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 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/ipc-server.h"
+#include "sway/output.h"
#include "sway/tree/container.h"
#include "sway/tree/workspace.h"
@@ -82,7 +83,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
free(workspace->name);
workspace->name = new_name;
- container_sort_workspaces(workspace->parent);
+ output_sort_workspaces(workspace->parent);
ipc_event_workspace(NULL, workspace, "rename");
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) {
config->show_marks = parse_boolean(argv[0], config->show_marks);
if (config->show_marks) {
- container_for_each_descendant(&root_container,
- rebuild_marks_iterator, NULL);
+ root_for_each_container(rebuild_marks_iterator, NULL);
}
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) {
if (strcasecmp(argv[2], "id") == 0) {
#ifdef HAVE_XWAYLAND
xcb_window_t id = strtol(value, NULL, 0);
- other = container_find(&root_container, test_id, (void *)&id);
+ other = root_find_container(test_id, (void *)&id);
#endif
} else if (strcasecmp(argv[2], "con_id") == 0) {
size_t con_id = atoi(value);
- other = container_find(&root_container, test_con_id, (void *)con_id);
+ other = root_find_container(test_con_id, (void *)con_id);
} else if (strcasecmp(argv[2], "mark") == 0) {
- other = container_find(&root_container, test_mark, (void *)value);
+ other = root_find_container(test_mark, (void *)value);
} else {
free(value);
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) {
view_find_and_unmark(mark);
} else {
// Remove all marks from all views
- container_for_each_descendant(&root_container,
- remove_all_marks_iterator, NULL);
+ root_for_each_container(remove_all_marks_iterator, NULL);
}
free(mark);
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) {
size_t prev_max_height = config->font_height;
config->font_height = 0;
- container_for_each_descendant(&root_container,
- find_font_height_iterator, &recalculate);
-
- // Also consider floating views
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
- for (int j = 0; j < output->children->length; ++j) {
- struct sway_container *ws = output->children->items[j];
- container_for_each_descendant(ws->sway_workspace->floating,
- find_font_height_iterator, &recalculate);
- }
- }
+ root_for_each_container(find_font_height_iterator, &recalculate);
if (config->font_height != prev_max_height) {
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,
return false;
}
list_t *urgent_views = create_list();
- container_for_each_descendant(&root_container,
- find_urgent_iterator, urgent_views);
+ root_for_each_container(find_urgent_iterator, urgent_views);
list_stable_sort(urgent_views, cmp_urgent);
struct sway_view *target;
if (criteria->urgent == 'o') { // oldest
@@ -228,17 +227,7 @@ list_t *criteria_get_views(struct criteria *criteria) {
.criteria = criteria,
.matches = matches,
};
- container_for_each_descendant(&root_container,
- criteria_get_views_iterator, &data);
-
- // Scratchpad items which are hidden are not in the tree.
- for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) {
- struct sway_container *con =
- root_container.sway_root->scratchpad->items[i];
- if (!con->parent) {
- criteria_get_views_iterator(con, &data);
- }
- }
+ root_for_each_container(criteria_get_views_iterator, &data);
return matches;
}
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 {
static void send_frame_done_container_iterator(struct sway_container *con,
void *_data) {
- struct send_frame_done_data *data = _data;
- if (!sway_assert(con->type == C_VIEW, "expected a view")) {
+ if (con->type != C_VIEW) {
return;
}
-
if (!view_is_visible(con->sway_view)) {
return;
}
+ struct send_frame_done_data *data = _data;
output_view_for_each_surface(data->output, con->sway_view,
send_frame_done_iterator, data->when);
}
@@ -323,8 +322,8 @@ static void send_frame_done_container(struct sway_output *output,
.output = output,
.when = when,
};
- container_descendants(con, C_VIEW,
- send_frame_done_container_iterator, &data);
+ output_for_each_container(output->swayc,
+ send_frame_done_container_iterator, &data);
}
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,
return edge;
}
+static void handle_down_motion(struct sway_seat *seat,
+ struct sway_cursor *cursor, uint32_t time_msec) {
+ struct sway_container *con = seat->op_container;
+ if (seat_is_input_allowed(seat, con->sway_view->surface)) {
+ double moved_x = cursor->cursor->x - seat->op_ref_lx;
+ double moved_y = cursor->cursor->y - seat->op_ref_ly;
+ double sx = seat->op_ref_con_lx + moved_x;
+ double sy = seat->op_ref_con_ly + moved_y;
+ wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
+ }
+ seat->op_moved = true;
+}
+
static void handle_move_motion(struct sway_seat *seat,
struct sway_cursor *cursor) {
struct sway_container *con = seat->op_container;
@@ -397,6 +410,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
if (seat->operation != OP_NONE) {
switch (seat->operation) {
+ case OP_DOWN:
+ handle_down_motion(seat, cursor, time_msec);
+ break;
case OP_MOVE:
handle_move_motion(seat, cursor);
break;
@@ -726,13 +742,13 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
}
// Via mod+click
- struct sway_container *floater = cont;
- while (floater->parent->layout != L_FLOATING) {
- floater = floater->parent;
- }
uint32_t btn_resize = config->floating_mod_inverse ?
BTN_LEFT : BTN_RIGHT;
- if (button == btn_resize) {
+ if (mod_pressed && button == btn_resize) {
+ struct sway_container *floater = cont;
+ while (floater->parent->layout != L_FLOATING) {
+ floater = floater->parent;
+ }
edge = 0;
edge |= cursor->cursor->x > floater->x + floater->width / 2 ?
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
@@ -743,6 +759,14 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
}
}
+ // Handle mousedown on a container surface
+ if (surface && cont && state == WLR_BUTTON_PRESSED) {
+ seat_set_focus(seat, cont);
+ seat_pointer_notify_button(seat, time_msec, button, state);
+ seat_begin_down(seat, cont, button, sx, sy);
+ return;
+ }
+
// Handle clicking a container surface
if (cont) {
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) {
static void collect_focus_iter(struct sway_container *con, void *data) {
struct sway_seat *seat = data;
- if (con->type > C_WORKSPACE) {
- return;
- }
struct sway_seat_container *seat_con =
seat_container_from_container(seat, con);
if (!seat_con) {
@@ -349,7 +346,8 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
// init the focus stack
wl_list_init(&seat->focus_stack);
- container_for_each_descendant(&root_container, collect_focus_iter, seat);
+ root_for_each_workspace(collect_focus_iter, seat);
+ root_for_each_container(collect_focus_iter, seat);
wl_signal_add(&root_container.sway_root->events.new_container,
&seat->new_container);
@@ -954,6 +952,18 @@ struct seat_config *seat_get_config(struct sway_seat *seat) {
return NULL;
}
+void seat_begin_down(struct sway_seat *seat, struct sway_container *con,
+ uint32_t button, double sx, double sy) {
+ seat->operation = OP_DOWN;
+ seat->op_container = con;
+ seat->op_button = button;
+ seat->op_ref_lx = seat->cursor->cursor->x;
+ seat->op_ref_ly = seat->cursor->cursor->y;
+ seat->op_ref_con_lx = sx;
+ seat->op_ref_con_ly = sy;
+ seat->op_moved = false;
+}
+
void seat_begin_move(struct sway_seat *seat, struct sway_container *con,
uint32_t button) {
if (!seat->cursor) {
@@ -1007,6 +1017,7 @@ void seat_begin_resize_tiling(struct sway_seat *seat,
}
void seat_end_mouse_operation(struct sway_seat *seat) {
+ enum sway_seat_operation operation = seat->operation;
if (seat->operation == OP_MOVE) {
// We "move" the container to its own location so it discovers its
// output again.
@@ -1015,7 +1026,19 @@ void seat_end_mouse_operation(struct sway_seat *seat) {
}
seat->operation = OP_NONE;
seat->op_container = NULL;
- cursor_set_image(seat->cursor, "left_ptr", NULL);
+ if (operation == OP_DOWN) {
+ // Set the cursor's previous coords to the x/y at the start of the
+ // operation, so the container change will be detected if using
+ // focus_follows_mouse and the cursor moved off the original container
+ // during the operation.
+ seat->cursor->previous.x = seat->op_ref_lx;
+ seat->cursor->previous.y = seat->op_ref_ly;
+ if (seat->op_moved) {
+ cursor_send_pointer_motion(seat->cursor, 0, true);
+ }
+ } else {
+ cursor_set_image(seat->cursor, "left_ptr", NULL);
+ }
}
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) {
static void ipc_get_workspaces_callback(struct sway_container *workspace,
void *data) {
- if (workspace->type != C_WORKSPACE) {
+ if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
return;
}
json_object *workspace_json = ipc_json_describe_container(workspace);
@@ -631,8 +631,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
case IPC_GET_WORKSPACES:
{
json_object *workspaces = json_object_new_array();
- container_for_each_descendant(&root_container,
- ipc_get_workspaces_callback, workspaces);
+ root_for_each_workspace(ipc_get_workspaces_callback, workspaces);
const char *json_string = json_object_to_json_string(workspaces);
client_valid =
ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));
@@ -729,8 +728,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
case IPC_GET_MARKS:
{
json_object *marks = json_object_new_array();
- container_descendants(&root_container, C_VIEW, ipc_get_marks_callback,
- marks);
+ root_for_each_container(ipc_get_marks_callback, marks);
const char *json_string = json_object_to_json_string(marks);
client_valid =
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(
container_destroy(workspace);
}
- container_sort_workspaces(new_output);
+ output_sort_workspaces(new_output);
}
}
}
@@ -432,8 +432,10 @@ struct sway_container *container_close(struct sway_container *con) {
if (con->type == C_VIEW) {
view_close(con->sway_view);
- } else {
- container_for_each_descendant(con, container_close_func, NULL);
+ } else if (con->type == C_CONTAINER) {
+ container_for_each_child(con, container_close_func, NULL);
+ } else if (con->type == C_WORKSPACE) {
+ workspace_for_each_container(con, container_close_func, NULL);
}
return parent;
@@ -465,23 +467,12 @@ struct sway_container *container_view_create(struct sway_container *sibling,
return swayc;
}
-void container_descendants(struct sway_container *root,
- enum sway_container_type type,
- void (*func)(struct sway_container *item, void *data), void *data) {
- if (!root->children || !root->children->length) {
- return;
- }
- for (int i = 0; i < root->children->length; ++i) {
- struct sway_container *item = root->children->items[i];
- if (item->type == type) {
- func(item, data);
- }
- container_descendants(item, type, func, data);
- }
-}
-
-struct sway_container *container_find(struct sway_container *container,
+struct sway_container *container_find_child(struct sway_container *container,
bool (*test)(struct sway_container *view, void *data), void *data) {
+ if (!sway_assert(container->type == C_CONTAINER ||
+ container->type == C_VIEW, "Expected a container or view")) {
+ return NULL;
+ }
if (!container->children) {
return NULL;
}
@@ -489,15 +480,11 @@ struct sway_container *container_find(struct sway_container *container,
struct sway_container *child = container->children->items[i];
if (test(child, data)) {
return child;
- } else {
- struct sway_container *res = container_find(child, test, data);
- if (res) {
- return res;
- }
}
- }
- if (container->type == C_WORKSPACE) {
- return container_find(container->sway_workspace->floating, test, data);
+ struct sway_container *res = container_find_child(child, test, data);
+ if (res) {
+ return res;
+ }
}
return NULL;
}
@@ -743,26 +730,20 @@ struct sway_container *container_at(struct sway_container *workspace,
return NULL;
}
-void container_for_each_descendant(struct sway_container *container,
+void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data),
void *data) {
- if (!container) {
+ if (!sway_assert(container->type == C_CONTAINER ||
+ container->type == C_VIEW, "Expected a container or view")) {
return;
}
if (container->children) {
for (int i = 0; i < container->children->length; ++i) {
struct sway_container *child = container->children->items[i];
- container_for_each_descendant(child, f, data);
- }
- }
- if (container->type == C_WORKSPACE) {
- struct sway_container *floating = container->sway_workspace->floating;
- for (int i = 0; i < floating->children->length; ++i) {
- struct sway_container *child = floating->children->items[i];
- container_for_each_descendant(child, f, data);
+ f(child, data);
+ container_for_each_child(child, f, data);
}
}
- f(container, data);
}
bool container_has_ancestor(struct sway_container *descendant,
@@ -1199,13 +1180,12 @@ void container_set_dirty(struct sway_container *container) {
list_add(server.dirty_containers, container);
}
-static bool find_urgent_iterator(struct sway_container *con,
- void *data) {
+static bool find_urgent_iterator(struct sway_container *con, void *data) {
return con->type == C_VIEW && view_is_urgent(con->sway_view);
}
bool container_has_urgent_child(struct sway_container *container) {
- return container_find(container, find_urgent_iterator, NULL);
+ return container_find_child(container, find_urgent_iterator, NULL);
}
void container_end_mouse_operation(struct sway_container *container) {
@@ -1237,7 +1217,7 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
container_set_fullscreen(workspace->sway_workspace->fullscreen, false);
}
- container_for_each_descendant(container, set_fullscreen_iterator, &enable);
+ container_for_each_child(container, set_fullscreen_iterator, &enable);
container->is_fullscreen = enable;
@@ -1306,15 +1286,3 @@ bool container_is_fullscreen_or_child(struct sway_container *container) {
return false;
}
-
-struct sway_container *container_wrap_children(struct sway_container *parent) {
- struct sway_container *middle = container_create(C_CONTAINER);
- middle->layout = parent->layout;
- while (parent->children->length) {
- struct sway_container *child = parent->children->items[0];
- container_remove_child(child);
- container_add_child(middle, child);
- }
- container_add_child(parent, middle);
- return middle;
-}
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 @@
#define _POSIX_C_SOURCE 200809L
-#include <ctype.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -591,28 +590,6 @@ enum sway_container_layout container_get_default_layout(
}
}
-static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
- struct sway_container *a = *(void **)_a;
- struct sway_container *b = *(void **)_b;
- int retval = 0;
-
- if (isdigit(a->name[0]) && isdigit(b->name[0])) {
- int a_num = strtol(a->name, NULL, 10);
- int b_num = strtol(b->name, NULL, 10);
- retval = (a_num < b_num) ? -1 : (a_num > b_num);
- } else if (isdigit(a->name[0])) {
- retval = -1;
- } else if (isdigit(b->name[0])) {
- retval = 1;
- }
-
- return retval;
-}
-
-void container_sort_workspaces(struct sway_container *output) {
- list_stable_sort(output->children, sort_workspace_cmp_qsort);
-}
-
/**
* Get swayc in the direction of newly entered output.
*/
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 @@
#define _POSIX_C_SOURCE 200809L
+#include <ctype.h>
#include <string.h>
#include <strings.h>
#include "sway/ipc-server.h"
@@ -28,7 +29,7 @@ static void restore_workspaces(struct sway_container *output) {
}
}
- container_sort_workspaces(output);
+ output_sort_workspaces(output);
}
struct sway_container *output_create(
@@ -102,3 +103,73 @@ struct sway_container *output_create(
return output;
}
+void output_for_each_workspace(struct sway_container *output,
+ void (*f)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+ return;
+ }
+ for (int i = 0; i < output->children->length; ++i) {
+ struct sway_container *workspace = output->children->items[i];
+ f(workspace, data);
+ }
+}
+
+void output_for_each_container(struct sway_container *output,
+ void (*f)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+ return;
+ }
+ for (int i = 0; i < output->children->length; ++i) {
+ struct sway_container *workspace = output->children->items[i];
+ workspace_for_each_container(workspace, f, data);
+ }
+}
+
+struct sway_container *output_find_workspace(struct sway_container *output,
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+ return NULL;
+ }
+ for (int i = 0; i < output->children->length; ++i) {
+ struct sway_container *workspace = output->children->items[i];
+ if (test(workspace, data)) {
+ return workspace;
+ }
+ }
+ return NULL;
+}
+
+struct sway_container *output_find_container(struct sway_container *output,
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+ return NULL;
+ }
+ struct sway_container *result = NULL;
+ for (int i = 0; i < output->children->length; ++i) {
+ struct sway_container *workspace = output->children->items[i];
+ if ((result = workspace_find_container(workspace, test, data))) {
+ return result;
+ }
+ }
+ return NULL;
+}
+
+static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
+ struct sway_container *a = *(void **)_a;
+ struct sway_container *b = *(void **)_b;
+
+ if (isdigit(a->name[0]) && isdigit(b->name[0])) {
+ int a_num = strtol(a->name, NULL, 10);
+ int b_num = strtol(b->name, NULL, 10);
+ return (a_num < b_num) ? -1 : (a_num > b_num);
+ } else if (isdigit(a->name[0])) {
+ return -1;
+ } else if (isdigit(b->name[0])) {
+ return 1;
+ }
+ return 0;
+}
+
+void output_sort_workspaces(struct sway_container *output) {
+ list_stable_sort(output->children, sort_workspace_cmp_qsort);
+}
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) {
&pw->output_destroy);
wl_list_insert(&pid_workspaces, &pw->link);
}
+
+void root_for_each_workspace(void (*f)(struct sway_container *con, void *data),
+ void *data) {
+ for (int i = 0; i < root_container.children->length; ++i) {
+ struct sway_container *output = root_container.children->items[i];
+ output_for_each_workspace(output, f, data);
+ }
+}
+
+void root_for_each_container(void (*f)(struct sway_container *con, void *data),
+ void *data) {
+ for (int i = 0; i < root_container.children->length; ++i) {
+ struct sway_container *output = root_container.children->items[i];
+ output_for_each_container(output, f, data);
+ }
+
+ // Scratchpad
+ for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) {
+ struct sway_container *container =
+ root_container.sway_root->scratchpad->items[i];
+ // If the container has a parent then it's visible on a workspace
+ // and will have been iterated in the previous for loop. So we only
+ // iterate the hidden scratchpad containers here.
+ if (!container->parent) {
+ f(container, data);
+ container_for_each_child(container, f, data);
+ }
+ }
+}
+
+struct sway_container *root_find_output(
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ for (int i = 0; i < root_container.children->length; ++i) {
+ struct sway_container *output = root_container.children->items[i];
+ if (test(output, data)) {
+ return output;
+ }
+ }
+ return NULL;
+}
+
+struct sway_container *root_find_workspace(
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ struct sway_container *result = NULL;
+ for (int i = 0; i < root_container.children->length; ++i) {
+ struct sway_container *output = root_container.children->items[i];
+ if ((result = output_find_workspace(output, test, data))) {
+ return result;
+ }
+ }
+ return NULL;
+}
+
+struct sway_container *root_find_container(
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ struct sway_container *result = NULL;
+ for (int i = 0; i < root_container.children->length; ++i) {
+ struct sway_container *output = root_container.children->items[i];
+ if ((result = output_find_container(output, test, data))) {
+ return result;
+ }
+ }
+
+ // Scratchpad
+ for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) {
+ struct sway_container *container =
+ root_container.sway_root->scratchpad->items[i];
+ if (!container->parent) {
+ if (test(container, data)) {
+ return container;
+ }
+ if ((result = container_find_child(container, test, data))) {
+ return result;
+ }
+ }
+ }
+ return NULL;
+}
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,
}
struct sway_view *view_find_mark(char *mark) {
- struct sway_container *container = container_find(&root_container,
- find_by_mark_iterator, mark);
+ struct sway_container *container = root_find_container(
+ find_by_mark_iterator, mark);
if (!container) {
return NULL;
}
@@ -890,7 +890,7 @@ struct sway_view *view_find_mark(char *mark) {
}
bool view_find_and_unmark(char *mark) {
- struct sway_container *container = container_find(&root_container,
+ struct sway_container *container = root_find_container(
find_by_mark_iterator, mark);
if (!container) {
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,
workspace_output_add_priority(workspace, output);
container_add_child(output, workspace);
- container_sort_workspaces(output);
+ output_sort_workspaces(output);
container_create_notify(workspace);
return workspace;
@@ -244,8 +244,7 @@ struct sway_container *workspace_by_number(const char* name) {
if (wbnd.len <= 0) {
return NULL;
}
- return container_find(&root_container,
- _workspace_by_number, (void *) &wbnd);
+ return root_find_workspace(_workspace_by_number, (void *) &wbnd);
}
static bool _workspace_by_name(struct sway_container *view, void *data) {
@@ -274,11 +273,11 @@ struct sway_container *workspace_by_name(const char *name) {
} else if (strcmp(name, "current") == 0) {
return current_workspace;
} else if (strcasecmp(name, "back_and_forth") == 0) {
- return prev_workspace_name ? container_find(&root_container,
- _workspace_by_name, (void *)prev_workspace_name) : NULL;
+ return prev_workspace_name ?
+ root_find_workspace(_workspace_by_name, (void*)prev_workspace_name)
+ : NULL;
} else {
- return container_find(&root_container, _workspace_by_name,
- (void *)name);
+ return root_find_workspace(_workspace_by_name, (void*)name);
}
}
@@ -518,8 +517,7 @@ struct sway_container *workspace_output_get_highest_available(
continue;
}
- struct sway_container *output = container_find(&root_container,
- _output_by_name, name);
+ struct sway_container *output = root_find_output(_output_by_name, name);
if (output) {
return output;
}
@@ -528,8 +526,13 @@ struct sway_container *workspace_output_get_highest_available(
return NULL;
}
+static bool find_urgent_iterator(struct sway_container *con, void *data) {
+ return con->type == C_VIEW && view_is_urgent(con->sway_view);
+}
+
void workspace_detect_urgent(struct sway_container *workspace) {
- bool new_urgent = container_has_urgent_child(workspace);
+ bool new_urgent = (bool)workspace_find_container(workspace,
+ find_urgent_iterator, NULL);
if (workspace->sway_workspace->urgent != new_urgent) {
workspace->sway_workspace->urgent = new_urgent;
@@ -537,3 +540,65 @@ void workspace_detect_urgent(struct sway_container *workspace) {
container_damage_whole(workspace);
}
}
+
+void workspace_for_each_container(struct sway_container *ws,
+ void (*f)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
+ return;
+ }
+ // Tiling
+ for (int i = 0; i < ws->children->length; ++i) {
+ struct sway_container *container = ws->children->items[i];
+ f(container, data);
+ container_for_each_child(container, f, data);
+ }
+ // Floating
+ for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) {
+ struct sway_container *container =
+ ws->sway_workspace->floating->children->items[i];
+ f(container, data);
+ container_for_each_child(container, f, data);
+ }
+}
+
+struct sway_container *workspace_find_container(struct sway_container *ws,
+ bool (*test)(struct sway_container *con, void *data), void *data) {
+ if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
+ return NULL;
+ }
+ struct sway_container *result = NULL;
+ // Tiling
+ for (int i = 0; i < ws->children->length; ++i) {
+ struct sway_container *child = ws->children->items[i];
+ if (test(child, data)) {
+ return child;
+ }
+ if ((result = container_find_child(child, test, data))) {
+ return result;
+ }
+ }
+ // Floating
+ for (int i = 0; i < ws->sway_workspace->floating->children->length; ++i) {
+ struct sway_container *child =
+ ws->sway_workspace->floating->children->items[i];
+ if (test(child, data)) {
+ return child;
+ }
+ if ((result = container_find_child(child, test, data))) {
+ return result;
+ }
+ }
+ return NULL;
+}
+
+struct sway_container *workspace_wrap_children(struct sway_container *ws) {
+ struct sway_container *middle = container_create(C_CONTAINER);
+ middle->layout = ws->layout;
+ while (ws->children->length) {
+ struct sway_container *child = ws->children->items[0];
+ container_remove_child(child);
+ container_add_child(middle, child);
+ }
+ container_add_child(ws, middle);
+ return middle;
+}