diff options
author | William McKinnon <[email protected]> | 2022-10-09 11:47:34 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2022-10-09 11:47:34 -0400 |
commit | 90a80e70417528f41700a2874b75c8e6d133307e (patch) | |
tree | e47928834f61844acb05a42eb3998efa93a64267 /sway/desktop/render.c | |
parent | 22a6aba9f00314d4e44f7e3d99e83db6b44c4ea2 (diff) |
feat: add round borders (#22)
Co-authored-by: Erik Reider <[email protected]>
Diffstat (limited to 'sway/desktop/render.c')
-rw-r--r-- | sway/desktop/render.c | 132 |
1 files changed, 123 insertions, 9 deletions
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 09a99e02..422991f7 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -166,7 +166,8 @@ static void render_surface_iterator(struct sway_output *output, } scale_box(&dst_box, wlr_output->scale); - render_texture(wlr_output, output_damage, texture, &src_box, &dst_box, matrix, alpha, corner_radius); + render_texture(wlr_output, output_damage, texture, &src_box, &dst_box, + matrix, alpha, corner_radius * wlr_output->scale); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); @@ -253,6 +254,41 @@ damage_finish: pixman_region32_fini(&damage); } +// _box.x and .y are expected to be layout-local +// _box.width and .height are expected to be output-buffer-local +void render_border_corner(struct sway_output *output, pixman_region32_t *output_damage, + const struct wlr_box *_box, float color[static 4], int border_thickness, + enum corner_location corner_location) { + struct wlr_output *wlr_output = output->wlr_output; + struct fx_renderer *renderer = output->server->renderer; + + struct wlr_box box; + memcpy(&box, _box, sizeof(struct wlr_box)); + box.x -= output->lx * wlr_output->scale; + box.y -= output->ly * wlr_output->scale; + + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_union_rect(&damage, &damage, box.x, box.y, + box.width, box.height); + pixman_region32_intersect(&damage, &damage, output_damage); + bool damaged = pixman_region32_not_empty(&damage); + if (!damaged) { + goto damage_finish; + } + + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + for (int i = 0; i < nrects; ++i) { + scissor_output(wlr_output, &rects[i]); + fx_render_border_corner(renderer, &box, color, wlr_output->transform_matrix, + corner_location, config->corner_radius * wlr_output->scale, border_thickness); + } + +damage_finish: + pixman_region32_fini(&damage); +} + void premultiply_alpha(float color[4], float opacity) { color[3] *= opacity; color[0] *= color[3]; @@ -348,7 +384,7 @@ static void render_saved_view(struct sway_view *view, scale_box(&dst_box, wlr_output->scale); render_texture(wlr_output, damage, saved_buf->buffer->texture, - &saved_buf->source_box, &dst_box, matrix, alpha, corner_radius); + &saved_buf->source_box, &dst_box, matrix, alpha, corner_radius * wlr_output->scale); } // FIXME: we should set the surface that this saved buffer originates from @@ -360,7 +396,7 @@ static void render_saved_view(struct sway_view *view, * Render a view's surface and left/bottom/right borders. */ static void render_view(struct sway_output *output, pixman_region32_t *damage, - struct sway_container *con, struct border_colors *colors) { + struct sway_container *con, struct border_colors *colors, bool has_titlebar) { struct sway_view *view = con->view; if (!wl_list_empty(&view->saved_buffers)) { render_saved_view(view, output, damage, view->container->alpha, config->corner_radius); @@ -384,6 +420,15 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, box.y = floor(state->content_y); box.width = state->border_thickness; box.height = state->content_height; + // adjust sizing for rounded border corners + if (config->corner_radius) { + if (!has_titlebar) { + box.y += config->corner_radius; + box.height -= 2 * config->corner_radius; + } else { + box.height -= config->corner_radius; + } + } scale_box(&box, output_scale); render_rect(output, damage, &box, color); } @@ -403,6 +448,15 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, box.y = floor(state->content_y); box.width = state->border_thickness; box.height = state->content_height; + // adjust sizing for rounded border corners + if (config->corner_radius) { + if (!has_titlebar) { + box.y += config->corner_radius; + box.height -= 2 * config->corner_radius; + } else { + box.height -= config->corner_radius; + } + } scale_box(&box, output_scale); render_rect(output, damage, &box, color); } @@ -418,8 +472,35 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, box.y = floor(state->content_y + state->content_height); box.width = state->width; box.height = state->border_thickness; + // adjust sizing for rounded border corners + if (config->corner_radius) { + box.x += config->corner_radius; + box.width -= 2 * config->corner_radius; + } scale_box(&box, output_scale); render_rect(output, damage, &box, color); + + // rounded bottom left & bottom right border corners + if (config->corner_radius) { + int size = 2 * (config->corner_radius + state->border_thickness); + int scaled_thickness = state->border_thickness * output_scale; + if (state->border_left) { + box.width = size; + box.height = size; + box.x = floor(state->x); + box.y = floor(state->y + state->height - size); + scale_box(&box, output_scale); + render_border_corner(output, damage, &box, color, scaled_thickness, BOTTOM_LEFT); + } + if (state->border_right) { + box.width = size; + box.height = size; + box.x = floor(state->x + state->width - size); + box.y = floor(state->y + state->height - size); + scale_box(&box, output_scale); + render_border_corner(output, damage, &box, color, scaled_thickness, BOTTOM_RIGHT); + } + } } } @@ -705,8 +786,38 @@ static void render_top_border(struct sway_output *output, box.y = floor(state->y); box.width = state->width; box.height = state->border_thickness; + // adjust sizing for rounded border corners + if (config->corner_radius) { + box.x += config->corner_radius; + box.width -= 2 * config->corner_radius; + } scale_box(&box, output_scale); render_rect(output, output_damage, &box, color); + + // render rounded top corner borders if corner_radius is set > 0 + if (config->corner_radius) { + int size = 2 * (config->corner_radius + state->border_thickness); + int scaled_thickness = state->border_thickness * output_scale; + + // top left + if (state->border_left) { + box.width = size; + box.height = size; + box.x = floor(state->x); + box.y = floor(state->y); + scale_box(&box, output_scale); + render_border_corner(output, output_damage, &box, color, scaled_thickness, TOP_LEFT); + } + // top right + if (state->border_right) { + box.width = size; + box.height = size; + box.x = floor(state->x + state->width - size); + box.y = floor(state->y); + scale_box(&box, output_scale); + render_border_corner(output, output_damage, &box, color, scaled_thickness, TOP_RIGHT); + } + } } struct parent_data { @@ -756,14 +867,15 @@ static void render_containers_linear(struct sway_output *output, marks_texture = child->marks_unfocused; } - if (state->border == B_NORMAL) { + bool has_titlebar = state->border == B_NORMAL; + render_view(output, damage, child, colors, has_titlebar); + if (has_titlebar) { render_titlebar(output, damage, child, floor(state->x), floor(state->y), state->width, colors, title_texture, marks_texture); } else if (state->border == B_PIXEL) { render_top_border(output, damage, child, colors); } - render_view(output, damage, child, colors); } else { render_container(output, damage, child, parent->focused || child->current.focused); @@ -841,7 +953,7 @@ static void render_containers_tabbed(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(output, damage, current, current_colors, true); } else { render_container(output, damage, current, parent->focused || current->current.focused); @@ -904,7 +1016,7 @@ static void render_containers_stacked(struct sway_output *output, // Render surface and left/right/bottom borders if (current->view) { - render_view(output, damage, current, current_colors); + render_view(output, damage, current, current_colors, true); } else { render_container(output, damage, current, parent->focused || current->current.focused); @@ -992,14 +1104,16 @@ static void render_floating_container(struct sway_output *soutput, marks_texture = con->marks_unfocused; } - if (con->current.border == B_NORMAL) { + bool has_titlebar = con->current.border == B_NORMAL; + render_view(soutput, damage, con, colors, has_titlebar); + if (has_titlebar) { render_titlebar(soutput, damage, con, floor(con->current.x), floor(con->current.y), con->current.width, colors, title_texture, marks_texture); + has_titlebar = true; } else if (con->current.border == B_PIXEL) { render_top_border(soutput, damage, con, colors); } - render_view(soutput, damage, con, colors); } else { render_container(soutput, damage, con, con->current.focused); } |