diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 90ec3c77..0f25cff1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -1,8 +1,8 @@ #define _POSIX_C_SOURCE 200809L #include #include -#include #include +#include #include #include #include @@ -12,6 +12,7 @@ #include #include #include +#include #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" @@ -95,13 +96,13 @@ static bool get_surface_box(struct root_geometry *geo, } static void output_surface_for_each_surface(struct wlr_surface *surface, - double ox, double oy, float rotation, struct root_geometry *geo, + double ox, double oy, struct root_geometry *geo, wlr_surface_iterator_func_t iterator, void *user_data) { geo->x = ox; geo->y = oy; geo->width = surface->current->width; geo->height = surface->current->height; - geo->rotation = rotation; + geo->rotation = 0; wlr_surface_for_each_surface(surface, iterator, user_data); } @@ -174,14 +175,14 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, } static void render_surface(struct sway_output *output, struct timespec *when, - struct wlr_surface *surface, double ox, double oy, float rotation) { + struct wlr_surface *surface, double ox, double oy) { struct render_data data = { .output = output, .when = when, .alpha = 1.0f, }; - output_surface_for_each_surface(surface, ox, oy, rotation, &data.root_geo, + output_surface_for_each_surface(surface, ox, oy, &data.root_geo, render_surface_iterator, &data); } @@ -204,7 +205,7 @@ static void render_layer(struct sway_output *output, struct timespec *when, struct wlr_layer_surface *wlr_layer_surface = layer_surface->layer_surface; render_surface(output, when, wlr_layer_surface->surface, - layer_surface->geo.x, layer_surface->geo.y, 0); + layer_surface->geo.x, layer_surface->geo.y); } } @@ -241,6 +242,11 @@ static void render_output(struct sway_output *output, struct timespec *when, goto renderer_end; } + // TODO: don't damage the whole output + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(damage, damage, 0, 0, width, height); + float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; wlr_renderer_clear(renderer, clear_color); @@ -270,7 +276,7 @@ static void render_output(struct sway_output *output, struct timespec *when, unmanaged_surface->wlr_xwayland_surface; double ox = unmanaged_surface->lx - output->swayc->x; double oy = unmanaged_surface->ly - output->swayc->y; - render_surface(output, when, xsurface->surface, ox, oy, 0); + render_surface(output, when, xsurface->surface, ox, oy); } // TODO: consider revising this when fullscreen windows are supported @@ -318,22 +324,93 @@ void output_damage_whole(struct sway_output *output) { wlr_output_damage_add_whole(output->damage); } +struct damage_data { + struct root_geometry root_geo; + struct sway_output *output; + bool whole; +}; + +static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, + void *_data) { + struct damage_data *data = _data; + struct sway_output *output = data->output; + float rotation = data->root_geo.rotation; + bool whole = data->whole; + + if (!wlr_surface_has_buffer(surface)) { + return; + } + + struct wlr_box box; + bool intersects = get_surface_box(&data->root_geo, data->output, surface, + sx, sy, &box); + if (!intersects) { + return; + } + + scale_box(&box, output->wlr_output->scale); + + if (whole) { + wlr_box_rotated_bounds(&box, rotation, &box); + wlr_output_damage_add_box(output->damage, &box); + } else { + int center_x = box.x + box.width/2; + int center_y = box.y + box.height/2; + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_copy(&damage, &surface->current->surface_damage); + wlr_region_scale(&damage, &damage, output->wlr_output->scale); + if (ceil(output->wlr_output->scale) > surface->current->scale) { + // When scaling up a surface, it'll become blurry so we need to + // expand the damage region + wlr_region_expand(&damage, &damage, + ceil(output->wlr_output->scale) - surface->current->scale); + } + pixman_region32_translate(&damage, box.x, box.y); + wlr_region_rotated_bounds(&damage, &damage, rotation, + center_x, center_y); + wlr_output_damage_add(output->damage, &damage); + pixman_region32_fini(&damage); + } +} + void output_damage_surface(struct sway_output *output, double ox, double oy, struct wlr_surface *surface, bool whole) { - // TODO - output_damage_whole(output); + struct damage_data data = { + .output = output, + .whole = whole, + }; + + output_surface_for_each_surface(surface, ox, oy, &data.root_geo, + damage_surface_iterator, &data); } void output_damage_view(struct sway_output *output, struct sway_view *view, bool whole) { - // TODO - output_damage_whole(output); + if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { + return; + } + + struct damage_data data = { + .output = output, + .whole = whole, + }; + + output_view_for_each_surface(view, &data.root_geo, + damage_surface_iterator, &data); } void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { - // TODO - output_damage_whole(output); + float scale = output->wlr_output->scale; + struct wlr_box box = { + .x = con->x * scale, + .y = con->y * scale, + .width = con->width * scale, + .height = con->height * scale, + }; + wlr_output_damage_add_box(output->damage, &box); } static void damage_handle_destroy(struct wl_listener *listener, void *data) { diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index b82eec8f..e4703040 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -143,9 +143,7 @@ static void destroy(struct sway_view *view) { if (xdg_shell_v6_view == NULL) { return; } - wl_list_remove(&xdg_shell_v6_view->commit.link); wl_list_remove(&xdg_shell_v6_view->destroy.link); - wl_list_remove(&xdg_shell_v6_view->new_popup.link); wl_list_remove(&xdg_shell_v6_view->map.link); wl_list_remove(&xdg_shell_v6_view->unmap.link); free(xdg_shell_v6_view); @@ -182,14 +180,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { static void handle_unmap(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, unmap); + view_unmap(&xdg_shell_v6_view->view); + + wl_list_remove(&xdg_shell_v6_view->commit.link); + wl_list_remove(&xdg_shell_v6_view->new_popup.link); } static void handle_map(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, map); struct sway_view *view = &xdg_shell_v6_view->view; + struct wlr_xdg_surface_v6 *xdg_surface = view->wlr_xdg_surface_v6; + view_map(view, view->wlr_xdg_surface_v6->surface); + + xdg_shell_v6_view->commit.notify = handle_commit; + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_shell_v6_view->commit); + + xdg_shell_v6_view->new_popup.notify = handle_new_popup; + wl_signal_add(&xdg_surface->events.new_popup, + &xdg_shell_v6_view->new_popup); } static void handle_destroy(struct wl_listener *listener, void *data) { @@ -226,14 +238,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { // - Look up pid and open on appropriate workspace // - Criteria - xdg_shell_v6_view->commit.notify = handle_commit; - wl_signal_add(&xdg_surface->surface->events.commit, - &xdg_shell_v6_view->commit); - - xdg_shell_v6_view->new_popup.notify = handle_new_popup; - wl_signal_add(&xdg_surface->events.new_popup, - &xdg_shell_v6_view->new_popup); - xdg_shell_v6_view->map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);