Merge pull request #2473 from RyanDwyer/iterators-per-type

Implement iterators per container type
This commit is contained in:
Drew DeVault 2018-08-18 10:29:46 -04:00 committed by GitHub
commit 744724b3cb
Failed to generate hash of commit
18 changed files with 268 additions and 110 deletions

View file

@ -95,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, struct wl_list *drag_icons, sway_surface_iterator_func_t iterator,
void *user_data); 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 #endif

View file

@ -214,15 +214,11 @@ struct sway_container *container_destroy(struct sway_container *container);
struct sway_container *container_close(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 * Search a container's descendants a container based on test criteria. Returns
* the first container that passes the test. * 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); 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 sway_container *con, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy); struct wlr_surface **surface, double *sx, double *sy);
/** void container_for_each_child(struct sway_container *container,
* Apply the function for each child of the container depth first.
*/
void container_for_each_descendant(struct sway_container *container,
void (*f)(struct sway_container *container, void *data), void *data); void (*f)(struct sway_container *container, void *data), void *data);
/** /**

View file

@ -58,4 +58,19 @@ struct sway_container *root_workspace_for_pid(pid_t pid);
void root_record_workspace_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 #endif

View file

@ -50,6 +50,12 @@ struct sway_container *workspace_output_get_highest_available(
void workspace_detect_urgent(struct sway_container *workspace); 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. * 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 will be the only direct tiling child of the workspace.

View file

@ -31,7 +31,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
"<none|vertical|horizontal|both|smart>'"); "<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); return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} }

View file

@ -24,8 +24,7 @@ struct cmd_results *cmd_show_marks(int argc, char **argv) {
config->show_marks = parse_boolean(argv[0], config->show_marks); config->show_marks = parse_boolean(argv[0], config->show_marks);
if (config->show_marks) { if (config->show_marks) {
container_for_each_descendant(&root_container, root_for_each_container(rebuild_marks_iterator, NULL);
rebuild_marks_iterator, NULL);
} }
for (int i = 0; i < root_container.children->length; ++i) { for (int i = 0; i < root_container.children->length; ++i) {

View file

@ -50,13 +50,13 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
if (strcasecmp(argv[2], "id") == 0) { if (strcasecmp(argv[2], "id") == 0) {
#ifdef HAVE_XWAYLAND #ifdef HAVE_XWAYLAND
xcb_window_t id = strtol(value, NULL, 0); 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 #endif
} else if (strcasecmp(argv[2], "con_id") == 0) { } else if (strcasecmp(argv[2], "con_id") == 0) {
size_t con_id = atoi(value); 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) { } 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 { } else {
free(value); free(value);
return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX);

View file

@ -52,8 +52,7 @@ struct cmd_results *cmd_unmark(int argc, char **argv) {
view_find_and_unmark(mark); view_find_and_unmark(mark);
} else { } else {
// Remove all marks from all views // Remove all marks from all views
container_for_each_descendant(&root_container, root_for_each_container(remove_all_marks_iterator, NULL);
remove_all_marks_iterator, NULL);
} }
free(mark); free(mark);

View file

@ -822,18 +822,7 @@ void config_update_font_height(bool recalculate) {
size_t prev_max_height = config->font_height; size_t prev_max_height = config->font_height;
config->font_height = 0; config->font_height = 0;
container_for_each_descendant(&root_container, root_for_each_container(find_font_height_iterator, &recalculate);
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);
}
}
if (config->font_height != prev_max_height) { if (config->font_height != prev_max_height) {
arrange_windows(&root_container); arrange_windows(&root_container);

View file

@ -167,8 +167,7 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
list_t *urgent_views = create_list(); list_t *urgent_views = create_list();
container_for_each_descendant(&root_container, root_for_each_container(find_urgent_iterator, urgent_views);
find_urgent_iterator, urgent_views);
list_stable_sort(urgent_views, cmp_urgent); list_stable_sort(urgent_views, cmp_urgent);
struct sway_view *target; struct sway_view *target;
if (criteria->urgent == 'o') { // oldest if (criteria->urgent == 'o') { // oldest
@ -228,17 +227,7 @@ list_t *criteria_get_views(struct criteria *criteria) {
.criteria = criteria, .criteria = criteria,
.matches = matches, .matches = matches,
}; };
container_for_each_descendant(&root_container, root_for_each_container(criteria_get_views_iterator, &data);
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);
}
}
return matches; return matches;
} }

View file

@ -303,15 +303,14 @@ struct send_frame_done_data {
static void send_frame_done_container_iterator(struct sway_container *con, static void send_frame_done_container_iterator(struct sway_container *con,
void *_data) { void *_data) {
struct send_frame_done_data *data = _data; if (con->type != C_VIEW) {
if (!sway_assert(con->type == C_VIEW, "expected a view")) {
return; return;
} }
if (!view_is_visible(con->sway_view)) { if (!view_is_visible(con->sway_view)) {
return; return;
} }
struct send_frame_done_data *data = _data;
output_view_for_each_surface(data->output, con->sway_view, output_view_for_each_surface(data->output, con->sway_view,
send_frame_done_iterator, data->when); send_frame_done_iterator, data->when);
} }
@ -322,8 +321,8 @@ static void send_frame_done_container(struct sway_output *output,
.output = output, .output = output,
.when = when, .when = when,
}; };
container_descendants(con, C_VIEW, output_for_each_container(output->swayc,
send_frame_done_container_iterator, &data); send_frame_done_container_iterator, &data);
} }
static void send_frame_done(struct sway_output *output, struct timespec *when) { static void send_frame_done(struct sway_output *output, struct timespec *when) {

View file

@ -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) { static void collect_focus_iter(struct sway_container *con, void *data) {
struct sway_seat *seat = data; struct sway_seat *seat = data;
if (con->type > C_WORKSPACE) {
return;
}
struct sway_seat_container *seat_con = struct sway_seat_container *seat_con =
seat_container_from_container(seat, con); seat_container_from_container(seat, con);
if (!seat_con) { if (!seat_con) {
@ -349,7 +346,8 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
// init the focus stack // init the focus stack
wl_list_init(&seat->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, wl_signal_add(&root_container.sway_root->events.new_container,
&seat->new_container); &seat->new_container);

View file

@ -522,7 +522,7 @@ void ipc_client_disconnect(struct ipc_client *client) {
static void ipc_get_workspaces_callback(struct sway_container *workspace, static void ipc_get_workspaces_callback(struct sway_container *workspace,
void *data) { void *data) {
if (workspace->type != C_WORKSPACE) { if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
return; return;
} }
json_object *workspace_json = ipc_json_describe_container(workspace); 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: case IPC_GET_WORKSPACES:
{ {
json_object *workspaces = json_object_new_array(); json_object *workspaces = json_object_new_array();
container_for_each_descendant(&root_container, root_for_each_workspace(ipc_get_workspaces_callback, workspaces);
ipc_get_workspaces_callback, workspaces);
const char *json_string = json_object_to_json_string(workspaces); const char *json_string = json_object_to_json_string(workspaces);
client_valid = client_valid =
ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); 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: case IPC_GET_MARKS:
{ {
json_object *marks = json_object_new_array(); json_object *marks = json_object_new_array();
container_descendants(&root_container, C_VIEW, ipc_get_marks_callback, root_for_each_container(ipc_get_marks_callback, marks);
marks);
const char *json_string = json_object_to_json_string(marks); const char *json_string = json_object_to_json_string(marks);
client_valid = client_valid =
ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); ipc_send_reply(client, json_string, (uint32_t)strlen(json_string));

View file

@ -432,8 +432,10 @@ struct sway_container *container_close(struct sway_container *con) {
if (con->type == C_VIEW) { if (con->type == C_VIEW) {
view_close(con->sway_view); view_close(con->sway_view);
} else { } else if (con->type == C_CONTAINER) {
container_for_each_descendant(con, container_close_func, NULL); 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; return parent;
@ -465,23 +467,12 @@ struct sway_container *container_view_create(struct sway_container *sibling,
return swayc; return swayc;
} }
void container_descendants(struct sway_container *root, struct sway_container *container_find_child(struct sway_container *container,
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,
bool (*test)(struct sway_container *view, void *data), void *data) { 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) { if (!container->children) {
return NULL; return NULL;
} }
@ -489,15 +480,11 @@ struct sway_container *container_find(struct sway_container *container,
struct sway_container *child = container->children->items[i]; struct sway_container *child = container->children->items[i];
if (test(child, data)) { if (test(child, data)) {
return child; return child;
} else {
struct sway_container *res = container_find(child, test, data);
if (res) {
return res;
}
} }
} struct sway_container *res = container_find_child(child, test, data);
if (container->type == C_WORKSPACE) { if (res) {
return container_find(container->sway_workspace->floating, test, data); return res;
}
} }
return NULL; return NULL;
} }
@ -743,26 +730,20 @@ struct sway_container *container_at(struct sway_container *workspace,
return NULL; 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 (*f)(struct sway_container *container, void *data),
void *data) { void *data) {
if (!container) { if (!sway_assert(container->type == C_CONTAINER ||
container->type == C_VIEW, "Expected a container or view")) {
return; return;
} }
f(container, data);
if (container->children) { if (container->children) {
for (int i = 0; i < container->children->length; ++i) { for (int i = 0; i < container->children->length; ++i) {
struct sway_container *child = container->children->items[i]; struct sway_container *child = container->children->items[i];
container_for_each_descendant(child, f, data); container_for_each_child(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(container, data);
} }
bool container_has_ancestor(struct sway_container *descendant, bool container_has_ancestor(struct sway_container *descendant,
@ -1198,13 +1179,12 @@ void container_set_dirty(struct sway_container *container) {
list_add(server.dirty_containers, container); list_add(server.dirty_containers, container);
} }
static bool find_urgent_iterator(struct sway_container *con, static bool find_urgent_iterator(struct sway_container *con, void *data) {
void *data) {
return con->type == C_VIEW && view_is_urgent(con->sway_view); return con->type == C_VIEW && view_is_urgent(con->sway_view);
} }
bool container_has_urgent_child(struct sway_container *container) { 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) { void container_end_mouse_operation(struct sway_container *container) {
@ -1236,7 +1216,7 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
container_set_fullscreen(workspace->sway_workspace->fullscreen, false); 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; container->is_fullscreen = enable;

View file

@ -103,6 +103,57 @@ struct sway_container *output_create(
return output; 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) { static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
struct sway_container *a = *(void **)_a; struct sway_container *a = *(void **)_a;
struct sway_container *b = *(void **)_b; struct sway_container *b = *(void **)_b;
@ -122,4 +173,3 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
void output_sort_workspaces(struct sway_container *output) { void output_sort_workspaces(struct sway_container *output) {
list_stable_sort(output->children, sort_workspace_cmp_qsort); list_stable_sort(output->children, sort_workspace_cmp_qsort);
} }

View file

@ -256,3 +256,81 @@ void root_record_workspace_pid(pid_t pid) {
&pw->output_destroy); &pw->output_destroy);
wl_list_insert(&pid_workspaces, &pw->link); 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;
}

View file

@ -899,8 +899,8 @@ static bool find_by_mark_iterator(struct sway_container *con,
} }
struct sway_view *view_find_mark(char *mark) { struct sway_view *view_find_mark(char *mark) {
struct sway_container *container = container_find(&root_container, struct sway_container *container = root_find_container(
find_by_mark_iterator, mark); find_by_mark_iterator, mark);
if (!container) { if (!container) {
return NULL; return NULL;
} }
@ -908,7 +908,7 @@ struct sway_view *view_find_mark(char *mark) {
} }
bool view_find_and_unmark(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); find_by_mark_iterator, mark);
if (!container) { if (!container) {
return false; return false;

View file

@ -244,8 +244,7 @@ struct sway_container *workspace_by_number(const char* name) {
if (wbnd.len <= 0) { if (wbnd.len <= 0) {
return NULL; return NULL;
} }
return container_find(&root_container, return root_find_workspace(_workspace_by_number, (void *) &wbnd);
_workspace_by_number, (void *) &wbnd);
} }
static bool _workspace_by_name(struct sway_container *view, void *data) { 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) { } else if (strcmp(name, "current") == 0) {
return current_workspace; return current_workspace;
} else if (strcasecmp(name, "back_and_forth") == 0) { } else if (strcasecmp(name, "back_and_forth") == 0) {
return prev_workspace_name ? container_find(&root_container, return prev_workspace_name ?
_workspace_by_name, (void *)prev_workspace_name) : NULL; root_find_workspace(_workspace_by_name, (void*)prev_workspace_name)
: NULL;
} else { } else {
return container_find(&root_container, _workspace_by_name, return root_find_workspace(_workspace_by_name, (void*)name);
(void *)name);
} }
} }
@ -518,8 +517,7 @@ struct sway_container *workspace_output_get_highest_available(
continue; continue;
} }
struct sway_container *output = container_find(&root_container, struct sway_container *output = root_find_output(_output_by_name, name);
_output_by_name, name);
if (output) { if (output) {
return output; return output;
} }
@ -528,8 +526,13 @@ struct sway_container *workspace_output_get_highest_available(
return NULL; 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) { 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) { if (workspace->sway_workspace->urgent != new_urgent) {
workspace->sway_workspace->urgent = new_urgent; workspace->sway_workspace->urgent = new_urgent;
@ -538,6 +541,56 @@ 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) {
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 *workspace_wrap_children(struct sway_container *ws) {
struct sway_container *middle = container_create(C_CONTAINER); struct sway_container *middle = container_create(C_CONTAINER);
middle->layout = ws->layout; middle->layout = ws->layout;