diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/desktop/fx_renderer.c | 94 | ||||
-rw-r--r-- | sway/desktop/render.c | 147 | ||||
-rw-r--r-- | sway/desktop/shaders/meson.build | 4 | ||||
-rw-r--r-- | sway/desktop/shaders/quad_round_tl.frag | 14 | ||||
-rw-r--r-- | sway/desktop/shaders/quad_round_tr.frag | 14 | ||||
-rw-r--r-- | sway/desktop/shaders/tex_external.frag | 15 | ||||
-rw-r--r-- | sway/desktop/shaders/tex_rgba.frag | 17 | ||||
-rw-r--r-- | sway/desktop/shaders/tex_rgbx.frag | 15 | ||||
-rw-r--r-- | sway/sway.5.scd | 5 | ||||
-rw-r--r-- | sway/tree/container.c | 4 |
10 files changed, 266 insertions, 63 deletions
diff --git a/sway/desktop/fx_renderer.c b/sway/desktop/fx_renderer.c index 7af4a313..2b5ba060 100644 --- a/sway/desktop/fx_renderer.c +++ b/sway/desktop/fx_renderer.c @@ -20,6 +20,8 @@ // shaders #include "quad_vert_src.h" #include "quad_frag_src.h" +#include "quad_round_tl_frag_src.h" +#include "quad_round_tr_frag_src.h" #include "corner_frag_src.h" #include "tex_vert_src.h" #include "tex_rgba_frag_src.h" @@ -97,6 +99,22 @@ bool init_frag_shader(struct gles2_tex_shader *shader, GLuint prog) { shader->size = glGetUniformLocation(prog, "size"); shader->position = glGetUniformLocation(prog, "position"); shader->radius = glGetUniformLocation(prog, "radius"); + shader->has_titlebar = glGetUniformLocation(prog, "has_titlebar"); + return true; +} + +// initializes a provided rounded quad shader and returns false if unsuccessful +bool init_rounded_quad_shader(struct rounded_quad_shader *shader, GLuint prog) { + shader->program = prog; + if (!shader->program) { + return false; + } + shader->proj = glGetUniformLocation(prog, "proj"); + shader->color = glGetUniformLocation(prog, "color"); + shader->pos_attrib = glGetAttribLocation(prog, "pos"); + shader->size = glGetUniformLocation(prog, "size"); + shader->position = glGetUniformLocation(prog, "position"); + shader->radius = glGetUniformLocation(prog, "radius"); return true; } @@ -133,6 +151,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { // init shaders GLuint prog; + // quad fragment shader prog = link_program(quad_vert_src, quad_frag_src); renderer->shaders.quad.program = prog; if (!renderer->shaders.quad.program) { @@ -142,7 +161,17 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) { renderer->shaders.quad.color = glGetUniformLocation(prog, "color"); renderer->shaders.quad.pos_attrib = glGetAttribLocation(prog, "pos"); - // Border corners + // rounded quad fragment shaders + prog = link_program(quad_vert_src, quad_round_tl_frag_src); + if (!init_rounded_quad_shader(&renderer->shaders.rounded_tl_quad, prog)) { + goto error; + } + prog = link_program(quad_vert_src, quad_round_tr_frag_src); + if (!init_rounded_quad_shader(&renderer->shaders.rounded_tr_quad, prog)) { + goto error; + } + + // Border corner shader prog = link_program(quad_vert_src, corner_frag_src); renderer->shaders.corner.program = prog; if (!renderer->shaders.corner.program) { @@ -225,7 +254,7 @@ void fx_renderer_scissor(struct wlr_box *box) { bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], - float alpha, int radius) { + float alpha, int radius, const bool has_titlebar) { assert(wlr_texture_is_gles2(wlr_texture)); struct wlr_gles2_texture_attribs texture_attrs; @@ -282,6 +311,7 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_t glUniformMatrix3fv(shader->proj, 1, GL_FALSE, gl_matrix); glUniform1i(shader->tex, 0); glUniform1f(shader->alpha, alpha); + glUniform1f(shader->has_titlebar, has_titlebar); // rounded corners glUniform2f(shader->size, dst_box->width, dst_box->height); @@ -316,14 +346,15 @@ bool fx_render_subtexture_with_matrix(struct fx_renderer *renderer, struct wlr_t } bool fx_render_texture_with_matrix(struct fx_renderer *renderer, struct wlr_texture *wlr_texture, - const struct wlr_box *dst_box, const float matrix[static 9], float alpha, int radius) { + const struct wlr_box *dst_box, const float matrix[static 9], float alpha, int radius, + const bool has_titlebar) { struct wlr_fbox src_box = { .x = 0, .y = 0, .width = wlr_texture->width, .height = wlr_texture->height, }; - return fx_render_subtexture_with_matrix(renderer, wlr_texture, &src_box, dst_box, matrix, alpha, radius); + return fx_render_subtexture_with_matrix(renderer, wlr_texture, &src_box, dst_box, matrix, alpha, radius, has_titlebar); } void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, @@ -364,6 +395,61 @@ void fx_render_rect(struct fx_renderer *renderer, const struct wlr_box *box, glDisableVertexAttribArray(renderer->shaders.quad.pos_attrib); } +void fx_render_rounded_rect(struct fx_renderer *renderer, const struct wlr_box *box, + const float color[static 4], const float projection[static 9], + int radius, enum corner_location corner_location) { + if (box->width == 0 || box->height == 0) { + return; + } + assert(box->width > 0 && box->height > 0); + + struct rounded_quad_shader *shader = NULL; + + switch (corner_location) { + case TOP_LEFT: + shader = &renderer->shaders.rounded_tl_quad; + break; + case TOP_RIGHT: + shader = &renderer->shaders.rounded_tr_quad; + break; + default: + sway_log(SWAY_ERROR, "Invalid Corner Location. Aborting render"); + abort(); + } + + float matrix[9]; + wlr_matrix_project_box(matrix, box, WL_OUTPUT_TRANSFORM_NORMAL, 0, projection); + + float gl_matrix[9]; + wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); + + // TODO: investigate why matrix is flipped prior to this cmd + // wlr_matrix_multiply(gl_matrix, flip_180, gl_matrix); + + wlr_matrix_transpose(gl_matrix, gl_matrix); + + glEnable(GL_BLEND); + + glUseProgram(shader->program); + + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, gl_matrix); + glUniform4f(shader->color, color[0], color[1], color[2], color[3]); + + // rounded corners + glUniform2f(shader->size, box->width, box->height); + glUniform2f(shader->position, box->x, box->y); + glUniform1f(shader->radius, radius); + + glVertexAttribPointer(shader->pos_attrib, 2, GL_FLOAT, GL_FALSE, + 0, verts); + + glEnableVertexAttribArray(shader->pos_attrib); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(shader->pos_attrib); +} + void fx_render_border_corner(struct fx_renderer *renderer, const struct wlr_box *box, const float color[static 4], const float projection[static 9], enum corner_location corner_location, int radius, int border_thickness) { diff --git a/sway/desktop/render.c b/sway/desktop/render.c index d27eb46f..83fe8ca6 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -33,6 +33,7 @@ struct render_data { pixman_region32_t *damage; float alpha; int corner_radius; + bool has_titlebar; struct wlr_box *clip_box; }; @@ -102,7 +103,7 @@ static void set_scale_filter(struct wlr_output *wlr_output, static void render_texture(struct wlr_output *wlr_output, pixman_region32_t *output_damage, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, - const float matrix[static 9], float alpha, int corner_radius) { + const float matrix[static 9], float alpha, int corner_radius, bool has_titlebar) { struct sway_output *output = wlr_output->data; struct fx_renderer *renderer = output->server->renderer; @@ -122,9 +123,9 @@ static void render_texture(struct wlr_output *wlr_output, scissor_output(wlr_output, &rects[i]); set_scale_filter(wlr_output, texture, output->scale_filter); if (src_box != NULL) { - fx_render_subtexture_with_matrix(renderer, texture, src_box, dst_box, matrix, alpha, corner_radius); + fx_render_subtexture_with_matrix(renderer, texture, src_box, dst_box, matrix, alpha, corner_radius, has_titlebar); } else { - fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, alpha, corner_radius); + fx_render_texture_with_matrix(renderer, texture, dst_box, matrix, alpha, corner_radius, has_titlebar); } } @@ -140,6 +141,7 @@ static void render_surface_iterator(struct sway_output *output, pixman_region32_t *output_damage = data->damage; float alpha = data->alpha; int corner_radius = data->corner_radius; + bool has_titlebar = data->has_titlebar; struct wlr_texture *texture = wlr_surface_get_texture(surface); if (!texture) { @@ -167,7 +169,7 @@ 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 * wlr_output->scale); + matrix, alpha, corner_radius * wlr_output->scale, has_titlebar); wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_output); @@ -179,6 +181,7 @@ static void render_layer_toplevel(struct sway_output *output, .damage = damage, .alpha = 1.0f, .corner_radius = 0, + .has_titlebar = false, }; output_layer_for_each_toplevel_surface(output, layer_surfaces, render_surface_iterator, &data); @@ -190,6 +193,7 @@ static void render_layer_popups(struct sway_output *output, .damage = damage, .alpha = 1.0f, .corner_radius = 0, + .has_titlebar = false, }; output_layer_for_each_popup_surface(output, layer_surfaces, render_surface_iterator, &data); @@ -202,6 +206,7 @@ static void render_unmanaged(struct sway_output *output, .damage = damage, .alpha = 1.0f, .corner_radius = 0, + .has_titlebar = false, }; output_unmanaged_for_each_surface(output, unmanaged, render_surface_iterator, &data); @@ -214,6 +219,7 @@ static void render_drag_icons(struct sway_output *output, .damage = damage, .alpha = 1.0f, .corner_radius = 0, + .has_titlebar = false, }; output_drag_icons_for_each_surface(output, drag_icons, render_surface_iterator, &data); @@ -246,8 +252,40 @@ void render_rect(struct sway_output *output, pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(wlr_output, &rects[i]); - fx_render_rect(renderer, &box, color, - wlr_output->transform_matrix); + fx_render_rect(renderer, &box, color, wlr_output->transform_matrix); + } + +damage_finish: + pixman_region32_fini(&damage); +} + +void render_rounded_rect(struct sway_output *output, pixman_region32_t *output_damage, + const struct wlr_box *_box, float color[static 4], int corner_radius, + 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_rounded_rect(renderer, &box, color, wlr_output->transform_matrix, + corner_radius, corner_location); } damage_finish: @@ -257,7 +295,7 @@ damage_finish: // _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 corner_radius, + const struct wlr_box *_box, const float color[static 4], int corner_radius, int border_thickness, enum corner_location corner_location) { struct wlr_output *wlr_output = output->wlr_output; struct fx_renderer *renderer = output->server->renderer; @@ -296,12 +334,13 @@ void premultiply_alpha(float color[4], float opacity) { color[2] *= color[3]; } -static void render_view_toplevels(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha, int corner_radius) { +static void render_view_toplevels(struct sway_view *view, struct sway_output *output, + pixman_region32_t *damage, float alpha, int corner_radius, bool has_titlebar) { struct render_data data = { .damage = damage, .alpha = alpha, .corner_radius = corner_radius, + .has_titlebar = has_titlebar, }; struct wlr_box clip_box; if (!container_is_current_floating(view->container)) { @@ -321,18 +360,19 @@ static void render_view_toplevels(struct sway_view *view, } static void render_view_popups(struct sway_view *view, struct sway_output *output, - pixman_region32_t *damage, float alpha, int corner_radius) { + pixman_region32_t *damage, float alpha, int corner_radius, bool has_titlebar) { struct render_data data = { .damage = damage, .alpha = alpha, .corner_radius = corner_radius, + .has_titlebar = has_titlebar, }; output_view_for_each_popup_surface(output, view, render_surface_iterator, &data); } -static void render_saved_view(struct sway_view *view, - struct sway_output *output, pixman_region32_t *damage, float alpha, int corner_radius) { +static void render_saved_view(struct sway_view *view, struct sway_output *output, + pixman_region32_t *damage, float alpha, int corner_radius, bool has_titlebar) { struct wlr_output *wlr_output = output->wlr_output; if (wl_list_empty(&view->saved_buffers)) { @@ -384,7 +424,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 * wlr_output->scale); + &saved_buf->source_box, &dst_box, matrix, alpha, corner_radius * wlr_output->scale, has_titlebar); } // FIXME: we should set the surface that this saved buffer originates from @@ -399,9 +439,9 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, 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, con->alpha, con->corner_radius); + render_saved_view(view, output, damage, con->alpha, con->corner_radius, has_titlebar); } else if (view->surface) { - render_view_toplevels(view, output, damage, con->alpha, con->corner_radius); + render_view_toplevels(view, output, damage, con->alpha, con->corner_radius, has_titlebar); } if (con->current.border == B_NONE || con->current.border == B_CSD) { @@ -518,25 +558,30 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage, */ static void render_titlebar(struct sway_output *output, pixman_region32_t *output_damage, struct sway_container *con, - int x, int y, int width, - struct border_colors *colors, struct wlr_texture *title_texture, - struct wlr_texture *marks_texture) { + int x, int y, int width, struct border_colors *colors, + struct wlr_texture *title_texture, struct wlr_texture *marks_texture) { struct wlr_box box; float color[4]; float output_scale = output->wlr_output->scale; double output_x = output->lx; double output_y = output->ly; int titlebar_border_thickness = config->titlebar_border_thickness; - int titlebar_h_padding = config->titlebar_h_padding; - int titlebar_v_padding = config->titlebar_v_padding; enum alignment title_align = config->title_align; + int corner_radius = con->corner_radius; + + // titlebar padding should account for corner radius + int titlebar_h_padding = corner_radius > config->titlebar_h_padding ? + corner_radius : config->titlebar_h_padding; + float titlebar_v_padding = corner_radius == (int)container_titlebar_height() ? + (container_titlebar_height() - config->font_height) / 2.0 : config->titlebar_v_padding; // Single pixel bar above title memcpy(&color, colors->border, sizeof(float) * 4); premultiply_alpha(color, con->alpha); - box.x = x; + box.x = corner_radius ? x + corner_radius : x + titlebar_border_thickness; box.y = y; - box.width = width; + box.width = corner_radius ? + width - corner_radius * 2 : width - titlebar_border_thickness * 2; box.height = titlebar_border_thickness; scale_box(&box, output_scale); render_rect(output, output_damage, &box, color); @@ -549,22 +594,43 @@ static void render_titlebar(struct sway_output *output, scale_box(&box, output_scale); render_rect(output, output_damage, &box, color); - // Single pixel left edge + // Single pixel bar left edge box.x = x; - box.y = y + titlebar_border_thickness; + box.y = y + corner_radius; box.width = titlebar_border_thickness; - box.height = container_titlebar_height() - titlebar_border_thickness * 2; + box.height = container_titlebar_height() - titlebar_border_thickness - corner_radius; scale_box(&box, output_scale); render_rect(output, output_damage, &box, color); - // Single pixel right edge + // Single pixel bar right edge box.x = x + width - titlebar_border_thickness; - box.y = y + titlebar_border_thickness; + box.y = y + corner_radius; box.width = titlebar_border_thickness; - box.height = container_titlebar_height() - titlebar_border_thickness * 2; + box.height = container_titlebar_height() - titlebar_border_thickness - corner_radius; scale_box(&box, output_scale); render_rect(output, output_damage, &box, color); + // if corner_radius: single pixel corners + if (corner_radius) { + // left corner + box.x = x; + box.y = y; + box.width = corner_radius * 2; + box.height = corner_radius * 2; + scale_box(&box, output_scale); + render_border_corner(output, output_damage, &box, color, + corner_radius, titlebar_border_thickness, TOP_LEFT); + + // right corner + box.x = x + width - corner_radius * 2; + box.y = y; + box.width = corner_radius * 2; + box.height = corner_radius * 2; + scale_box(&box, output_scale); + render_border_corner(output, output_damage, &box, color, + corner_radius, titlebar_border_thickness, TOP_RIGHT); + } + int inner_x = x - output_x + titlebar_h_padding; int bg_y = y + titlebar_border_thickness; size_t inner_width = width - titlebar_h_padding * 2; @@ -613,7 +679,7 @@ static void render_titlebar(struct sway_output *output, texture_box.width = ob_inner_width; } render_texture(output->wlr_output, output_damage, marks_texture, - NULL, &texture_box, matrix, con->alpha, 0); + NULL, &texture_box, matrix, con->alpha, 0, false); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); @@ -689,7 +755,7 @@ static void render_titlebar(struct sway_output *output, } render_texture(output->wlr_output, output_damage, title_texture, - NULL, &texture_box, matrix, con->alpha, 0); + NULL, &texture_box, matrix, con->alpha, 0, false); // Padding above memcpy(&color, colors->background, sizeof(float) * 4); @@ -751,7 +817,11 @@ static void render_titlebar(struct sway_output *output, if (box.x + box.width < left_x) { box.width += left_x - box.x - box.width; } - render_rect(output, output_damage, &box, color); + if (corner_radius) { + render_rounded_rect(output, output_damage, &box, color, corner_radius, TOP_LEFT); + } else { + render_rect(output, output_damage, &box, color); + } // Padding on right side box.x = x + width - titlebar_h_padding; @@ -765,7 +835,11 @@ static void render_titlebar(struct sway_output *output, box.width += box.x - right_rx; box.x = right_rx; } - render_rect(output, output_damage, &box, color); + if (corner_radius) { + render_rounded_rect(output, output_damage, &box, color, corner_radius, TOP_RIGHT); + } else { + render_rect(output, output_damage, &box, color); + } } /** @@ -1116,7 +1190,6 @@ static void render_floating_container(struct sway_output *soutput, 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); } @@ -1201,10 +1274,9 @@ void output_render(struct sway_output *output, struct timespec *when, if (fullscreen_con->view) { if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { - render_saved_view(fullscreen_con->view, output, damage, 1.0f, 0); + render_saved_view(fullscreen_con->view, output, damage, 1.0f, 0, false); } else if (fullscreen_con->view->surface) { - render_view_toplevels(fullscreen_con->view, - output, damage, 1.0f, 0); + render_view_toplevels(fullscreen_con->view, output, damage, 1.0f, 0, false); } } else { render_container(output, damage, fullscreen_con, @@ -1257,7 +1329,8 @@ void output_render(struct sway_output *output, struct timespec *when, struct sway_seat *seat = input_manager_current_seat(); struct sway_container *focus = seat_get_focused_container(seat); if (focus && focus->view) { - render_view_popups(focus->view, output, damage, focus->alpha, focus->corner_radius); + render_view_popups(focus->view, output, damage, focus->alpha, + focus->corner_radius, focus->current.border == B_NORMAL); } render_overlay: diff --git a/sway/desktop/shaders/meson.build b/sway/desktop/shaders/meson.build index 8eb12079..661ccc35 100644 --- a/sway/desktop/shaders/meson.build +++ b/sway/desktop/shaders/meson.build @@ -3,8 +3,10 @@ embed = find_program('./embed.sh', native: true) shaders = [ 'quad.vert', 'quad.frag', - 'tex.vert', + 'quad_round_tl.frag', + 'quad_round_tr.frag', 'corner.frag', + 'tex.vert', 'tex_rgba.frag', 'tex_rgbx.frag', 'tex_external.frag', diff --git a/sway/desktop/shaders/quad_round_tl.frag b/sway/desktop/shaders/quad_round_tl.frag new file mode 100644 index 00000000..6fd0119c --- /dev/null +++ b/sway/desktop/shaders/quad_round_tl.frag @@ -0,0 +1,14 @@ +precision mediump float; +varying vec4 v_color; +varying vec2 v_texcoord; + +uniform vec2 size; +uniform vec2 position; +uniform float radius; + +void main() { + vec2 q = abs(gl_FragCoord.xy - position - size) - size + radius; + float distance = min(max(q.x,q.y),0.0) + length(max(q,0.0)) - radius; + float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, distance); + gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); +} diff --git a/sway/desktop/shaders/quad_round_tr.frag b/sway/desktop/shaders/quad_round_tr.frag new file mode 100644 index 00000000..ff580045 --- /dev/null +++ b/sway/desktop/shaders/quad_round_tr.frag @@ -0,0 +1,14 @@ +precision mediump float; +varying vec4 v_color; +varying vec2 v_texcoord; + +uniform vec2 size; +uniform vec2 position; +uniform float radius; + +void main() { + vec2 q = abs(gl_FragCoord.xy - position - vec2(0, size.y)) - size + radius; + float distance = min(max(q.x,q.y),0.0) + length(max(q,0.0)) - radius; + float smoothedAlpha = 1.0 - smoothstep(-1.0, 0.5, distance); + gl_FragColor = mix(vec4(0), v_color, smoothedAlpha); +} diff --git a/sway/desktop/shaders/tex_external.frag b/sway/desktop/shaders/tex_external.frag index 404688c2..0703a05f 100644 --- a/sway/desktop/shaders/tex_external.frag +++ b/sway/desktop/shaders/tex_external.frag @@ -8,13 +8,16 @@ uniform float alpha; uniform vec2 size; uniform vec2 position; uniform float radius; +uniform bool has_titlebar; void main() { gl_FragColor = texture2D(texture0, v_texcoord) * alpha; - vec2 corner_distance = min(gl_FragCoord.xy - position, position + size - gl_FragCoord.xy); - if (max(corner_distance.x, corner_distance.y) < radius) { - float d = radius - distance(corner_distance, vec2(radius)); - float smooth = smoothstep(-1.0f, 0.5f, d); - gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - } + if (!has_titlebar || gl_FragCoord.y - position.y > radius) { + vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy); + if (max(corner_distance.x, corner_distance.y) < radius) { + float d = radius - distance(corner_distance, vec2(radius)); + float smooth = smoothstep(-1.0f, 0.5f, d); + gl_FragColor = mix(vec4(0), gl_FragColor, smooth); + } + } } diff --git a/sway/desktop/shaders/tex_rgba.frag b/sway/desktop/shaders/tex_rgba.frag index 1886fab4..95f58987 100644 --- a/sway/desktop/shaders/tex_rgba.frag +++ b/sway/desktop/shaders/tex_rgba.frag @@ -6,13 +6,16 @@ uniform float alpha; uniform vec2 size; uniform vec2 position; uniform float radius; +uniform bool has_titlebar; void main() { - gl_FragColor = texture2D(tex, v_texcoord) * alpha; - vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy); - if (max(corner_distance.x, corner_distance.y) < radius) { - float d = radius - distance(corner_distance, vec2(radius)); - float smooth = smoothstep(-1.0f, 0.5f, d); - gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - } + gl_FragColor = texture2D(tex, v_texcoord) * alpha; + if (!has_titlebar || gl_FragCoord.y - position.y > radius) { + vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy); + if (max(corner_distance.x, corner_distance.y) < radius) { + float d = radius - distance(corner_distance, vec2(radius)); + float smooth = smoothstep(-1.0f, 0.5f, d); + gl_FragColor = mix(vec4(0), gl_FragColor, smooth); + } + } } diff --git a/sway/desktop/shaders/tex_rgbx.frag b/sway/desktop/shaders/tex_rgbx.frag index cb6f1432..4a8b3756 100644 --- a/sway/desktop/shaders/tex_rgbx.frag +++ b/sway/desktop/shaders/tex_rgbx.frag @@ -6,13 +6,16 @@ uniform float alpha; uniform vec2 size; uniform vec2 position; uniform float radius; +uniform bool has_titlebar; void main() { gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha; - vec2 corner_distance = min(gl_FragCoord.xy - position, position + size - gl_FragCoord.xy); - if (max(corner_distance.x, corner_distance.y) < radius) { - float d = radius - distance(corner_distance, vec2(radius)); - float smooth = smoothstep(-1.0f, 0.5f, d); - gl_FragColor = mix(vec4(0), gl_FragColor, smooth); - } + if (!has_titlebar || gl_FragCoord.y - position.y > radius) { + vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy); + if (max(corner_distance.x, corner_distance.y) < radius) { + float d = radius - distance(corner_distance, vec2(radius)); + float smooth = smoothstep(-1.0f, 0.5f, d); + gl_FragColor = mix(vec4(0), gl_FragColor, smooth); + } + } } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 86f250d0..a245ae14 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -663,7 +663,9 @@ The default colors are: padding of the text while _vertical_ value affects vertical padding (space above and below text). Padding includes titlebar borders so their value should be greater than titlebar_border_thickness. If _vertical_ value is - not specified it is set to the _horizontal_ value. + not specified it is set to the _horizontal_ value. If _corner_radius_ is set + to be greater than the _horizontal_ or _vertical_ value, the value will be + treated as that of _corner_radius_. *for_window* <criteria> <command> Whenever a window that matches _criteria_ appears, run list of commands. @@ -960,3 +962,4 @@ The following attributes may be matched with: # SEE ALSO *sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7) + diff --git a/sway/tree/container.c b/sway/tree/container.c index afc6d685..a2aa130b 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -675,7 +675,9 @@ void container_update_representation(struct sway_container *con) { } size_t container_titlebar_height(void) { - return config->font_height + config->titlebar_v_padding * 2; + int config_titlebar_height = config->font_height + config->titlebar_v_padding * 2; + return config->corner_radius > config_titlebar_height ? + config->corner_radius : config_titlebar_height; } void floating_calculate_constraints(int *min_width, int *max_width, |