summaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/desktop/fx_renderer.c94
-rw-r--r--sway/desktop/render.c147
-rw-r--r--sway/desktop/shaders/meson.build4
-rw-r--r--sway/desktop/shaders/quad_round_tl.frag14
-rw-r--r--sway/desktop/shaders/quad_round_tr.frag14
-rw-r--r--sway/desktop/shaders/tex_external.frag15
-rw-r--r--sway/desktop/shaders/tex_rgba.frag17
-rw-r--r--sway/desktop/shaders/tex_rgbx.frag15
-rw-r--r--sway/sway.5.scd5
-rw-r--r--sway/tree/container.c4
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,