diff options
Diffstat (limited to 'sway/tree/container.c')
-rw-r--r-- | sway/tree/container.c | 122 |
1 files changed, 90 insertions, 32 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c index ea20991c..6ea0cc94 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -76,31 +76,6 @@ void container_update_textures_recursive(struct sway_container *con) { } } -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); - } - } -} - struct sway_container *container_create(enum sway_container_type type) { // next id starts at 1 because 0 is assigned to root_container in layout.c static size_t next_id = 1; @@ -117,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; @@ -156,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: @@ -238,6 +211,14 @@ static struct sway_container *container_workspace_destroy( 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")) { @@ -279,6 +260,8 @@ static struct sway_container *container_output_destroy( } } + 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); @@ -777,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; } @@ -795,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; @@ -823,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); @@ -1272,3 +1266,67 @@ bool container_is_fullscreen_or_child(struct sway_container *container) { return false; } + +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); + } + } +} |