diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 255 |
1 files changed, 135 insertions, 120 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index eb06edc2..a8c6e667 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -67,32 +67,11 @@ void container_update_textures_recursive(struct sway_container *con) { } if (con->type == C_WORKSPACE) { - container_update_textures_recursive(con->sway_workspace->floating); - } - } -} - -static void handle_reparent(struct wl_listener *listener, - void *data) { - struct sway_container *container = - wl_container_of(listener, container, reparent); - struct sway_container *old_parent = data; - - struct sway_container *old_output = old_parent; - if (old_output != NULL && old_output->type != C_OUTPUT) { - old_output = container_parent(old_output, C_OUTPUT); - } - - struct sway_container *new_output = container->parent; - if (new_output != NULL && new_output->type != C_OUTPUT) { - new_output = container_parent(new_output, C_OUTPUT); - } - - if (old_output && new_output) { - float old_scale = old_output->sway_output->wlr_output->scale; - float new_scale = new_output->sway_output->wlr_output->scale; - if (old_scale != new_scale) { - container_update_textures_recursive(container); + for (int i = 0; i < con->sway_workspace->floating->length; ++i) { + struct sway_container *floater = + con->sway_workspace->floating->items[i]; + container_update_textures_recursive(floater); + } } } } @@ -113,12 +92,9 @@ struct sway_container *container_create(enum sway_container_type type) { c->children = create_list(); c->current.children = create_list(); } + c->outputs = create_list(); wl_signal_init(&c->events.destroy); - wl_signal_init(&c->events.reparent); - - wl_signal_add(&c->events.reparent, &c->reparent); - c->reparent.notify = handle_reparent; c->has_gaps = false; c->gaps_inner = 0; @@ -131,6 +107,7 @@ struct sway_container *container_create(enum sway_container_type type) { static void container_workspace_free(struct sway_workspace *ws) { list_foreach(ws->output_priority, free); list_free(ws->output_priority); + list_free(ws->floating); free(ws); } @@ -151,6 +128,7 @@ void container_free(struct sway_container *cont) { wlr_texture_destroy(cont->title_urgent); list_free(cont->children); list_free(cont->current.children); + list_free(cont->outputs); switch (cont->type) { case C_ROOT: @@ -222,18 +200,25 @@ static struct sway_container *container_workspace_destroy( for (int i = 0; i < workspace->children->length; i++) { container_move_to(workspace->children->items[i], new_workspace); } - struct sway_container *floating = workspace->sway_workspace->floating; - for (int i = 0; i < floating->children->length; i++) { - container_move_to(floating->children->items[i], - new_workspace->sway_workspace->floating); + list_t *floating = workspace->sway_workspace->floating; + for (int i = 0; i < floating->length; i++) { + struct sway_container *floater = floating->items[i]; + container_remove_child(floater); + workspace_add_floating(new_workspace, floater); } } - container_destroy_noreaping(workspace->sway_workspace->floating); - return output; } +static void untrack_output(struct sway_container *con, void *data) { + struct sway_output *output = data; + int index = list_find(con->outputs, output); + if (index != -1) { + list_del(con->outputs, index); + } +} + static struct sway_container *container_output_destroy( struct sway_container *output) { if (!sway_assert(output, "cannot destroy null output")) { @@ -270,11 +255,13 @@ static struct sway_container *container_output_destroy( container_destroy(workspace); } - container_sort_workspaces(new_output); + output_sort_workspaces(new_output); } } } + root_for_each_container(untrack_output, output->sway_output); + wl_list_remove(&output->sway_output->mode.link); wl_list_remove(&output->sway_output->transform.link); wl_list_remove(&output->sway_output->scale.link); @@ -339,10 +326,6 @@ static struct sway_container *container_destroy_noreaping( } bool container_reap_empty(struct sway_container *con) { - if (con->layout == L_FLOATING) { - // Don't reap the magical floating container that each workspace has - return false; - } switch (con->type) { case C_ROOT: case C_OUTPUT: @@ -432,8 +415,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 +450,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 +463,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; } @@ -522,8 +492,8 @@ static void surface_at_view(struct sway_container *swayc, double lx, double ly, return; } struct sway_view *sview = swayc->sway_view; - double view_sx = lx - sview->x; - double view_sy = ly - sview->y; + double view_sx = lx - sview->x + sview->geometry.x; + double view_sy = ly - sview->y + sview->geometry.y; double _sx, _sy; struct wlr_surface *_surface = NULL; @@ -639,9 +609,8 @@ static struct sway_container *floating_container_at(double lx, double ly, } // Items at the end of the list are on top, so iterate the list in // reverse. - for (int k = ws->floating->children->length - 1; k >= 0; --k) { - struct sway_container *floater = - ws->floating->children->items[k]; + for (int k = ws->floating->length - 1; k >= 0; --k) { + struct sway_container *floater = ws->floating->items[k]; struct wlr_box box = { .x = floater->x, .y = floater->y, @@ -677,9 +646,6 @@ struct sway_container *tiling_container_at( return container_at_tabbed(con, lx, ly, surface, sx, sy); case L_STACKED: return container_at_stacked(con, lx, ly, surface, sx, sy); - case L_FLOATING: - sway_assert(false, "Didn't expect to see floating here"); - return NULL; case L_NONE: return NULL; } @@ -743,26 +709,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, @@ -800,13 +760,24 @@ void container_damage_whole(struct sway_container *container) { } } +/** + * Return the output which will be used for scale purposes. + * This is the most recently entered output. + */ +struct sway_output *container_get_effective_output(struct sway_container *con) { + if (con->outputs->length == 0) { + return NULL; + } + return con->outputs->items[con->outputs->length - 1]; +} + static void update_title_texture(struct sway_container *con, struct wlr_texture **texture, struct border_colors *class) { if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, "Unexpected type %s", container_type_to_str(con->type))) { return; } - struct sway_container *output = container_parent(con, C_OUTPUT); + struct sway_output *output = container_get_effective_output(con); if (!output) { return; } @@ -818,7 +789,7 @@ static void update_title_texture(struct sway_container *con, return; } - double scale = output->sway_output->wlr_output->scale; + double scale = output->wlr_output->scale; int width = 0; int height = con->title_height * scale; @@ -846,7 +817,7 @@ static void update_title_texture(struct sway_container *con, unsigned char *data = cairo_image_surface_get_data(surface); int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); struct wlr_renderer *renderer = wlr_backend_get_renderer( - output->sway_output->wlr_output->backend); + output->wlr_output->backend); *texture = wlr_texture_from_pixels( renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data); cairo_surface_destroy(surface); @@ -899,9 +870,6 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe case L_STACKED: lenient_strcat(buffer, "S["); break; - case L_FLOATING: - lenient_strcat(buffer, "F["); - break; case L_NONE: lenient_strcat(buffer, "D["); break; @@ -1030,12 +998,13 @@ void container_set_floating(struct sway_container *container, bool enable) { struct sway_container *workspace = container_parent(container, C_WORKSPACE); if (enable) { - container_remove_child(container); - container_add_child(workspace->sway_workspace->floating, container); + struct sway_container *old_parent = container_remove_child(container); + workspace_add_floating(workspace, container); container_init_floating(container); if (container->type == C_VIEW) { view_set_tiled(container->sway_view, false); } + container_reap_empty(old_parent); } else { // Returning to tiled if (container->scratchpad) { @@ -1083,14 +1052,12 @@ void container_set_geometry_from_floating_view(struct sway_container *con) { con->y = view->y - top; con->width = view->width + border_width * 2; con->height = top + view->height + border_width; + container_set_dirty(con); } bool container_is_floating(struct sway_container *container) { - struct sway_container *workspace = container_parent(container, C_WORKSPACE); - if (!workspace) { - return false; - } - return container->parent == workspace->sway_workspace->floating; + return container->parent && container->parent->type == C_WORKSPACE && + list_find(container->parent->sway_workspace->floating, container) != -1; } void container_get_box(struct sway_container *container, struct wlr_box *box) { @@ -1170,7 +1137,7 @@ void container_floating_move_to(struct sway_container *con, output_get_active_workspace(new_output->sway_output); if (old_workspace != new_workspace) { container_remove_child(con); - container_add_child(new_workspace->sway_workspace->floating, con); + workspace_add_floating(new_workspace, con); arrange_windows(old_workspace); arrange_windows(new_workspace); workspace_detect_urgent(old_workspace); @@ -1197,13 +1164,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) { @@ -1235,7 +1201,8 @@ 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); + set_fullscreen_iterator(container, &enable); + container_for_each_child(container, set_fullscreen_iterator, &enable); container->is_fullscreen = enable; @@ -1284,14 +1251,10 @@ void container_set_fullscreen(struct sway_container *container, bool enable) { } bool container_is_floating_or_child(struct sway_container *container) { - do { - if (container->parent && container->parent->layout == L_FLOATING) { - return true; - } + while (container->parent && container->parent->type != C_WORKSPACE) { container = container->parent; - } while (container && container->type != C_WORKSPACE); - - return false; + } + return container_is_floating(container); } bool container_is_fullscreen_or_child(struct sway_container *container) { @@ -1305,14 +1268,66 @@ 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); +static void surface_send_enter_iterator(struct wlr_surface *surface, + int x, int y, void *data) { + struct wlr_output *wlr_output = data; + wlr_surface_send_enter(surface, wlr_output); +} + +static void surface_send_leave_iterator(struct wlr_surface *surface, + int x, int y, void *data) { + struct wlr_output *wlr_output = data; + wlr_surface_send_leave(surface, wlr_output); +} + +void container_discover_outputs(struct sway_container *con) { + if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW, + "Expected a container or view")) { + return; + } + struct wlr_box con_box = { + .x = con->current.swayc_x, + .y = con->current.swayc_y, + .width = con->current.swayc_width, + .height = con->current.swayc_height, + }; + struct sway_output *old_output = container_get_effective_output(con); + + for (int i = 0; i < root_container.children->length; ++i) { + struct sway_container *output = root_container.children->items[i]; + struct sway_output *sway_output = output->sway_output; + struct wlr_box output_box; + container_get_box(output, &output_box); + struct wlr_box intersection; + bool intersects = + wlr_box_intersection(&con_box, &output_box, &intersection); + int index = list_find(con->outputs, sway_output); + + if (intersects && index == -1) { + // Send enter + wlr_log(WLR_DEBUG, "Con %p entered output %p", con, sway_output); + if (con->type == C_VIEW) { + view_for_each_surface(con->sway_view, + surface_send_enter_iterator, sway_output->wlr_output); + } + list_add(con->outputs, sway_output); + } else if (!intersects && index != -1) { + // Send leave + wlr_log(WLR_DEBUG, "Con %p left output %p", con, sway_output); + if (con->type == C_VIEW) { + view_for_each_surface(con->sway_view, + surface_send_leave_iterator, sway_output->wlr_output); + } + list_del(con->outputs, index); + } + } + struct sway_output *new_output = container_get_effective_output(con); + double old_scale = old_output ? old_output->wlr_output->scale : -1; + double new_scale = new_output ? new_output->wlr_output->scale : -1; + if (old_scale != new_scale) { + container_update_title_textures(con); + if (con->type == C_VIEW) { + view_update_marks_textures(con->sway_view); + } } - container_add_child(parent, middle); - return middle; } |