mirror of https://github.com/yshui/picom.git
Merge pull request #551 from yshui/rounded-corners-legacy-xrender
Rounded corners for legacy xrender backend
This commit is contained in:
commit
c634641c20
|
@ -103,6 +103,12 @@ OPTIONS
|
|||
*--inactive-dim* 'VALUE'::
|
||||
Dim inactive windows. (0.0 - 1.0, defaults to 0.0)
|
||||
|
||||
*--corner-radius* 'VALUE'::
|
||||
Sets the radius of rounded window corners. When > 0, the compositor will round the corners of windows. Does not interact well with *--transparent-clipping*. (defaults to 0).
|
||||
|
||||
*--rounded-corners-exclude* 'CONDITION'::
|
||||
Exclude conditions for rounded corners.
|
||||
|
||||
*--mark-wmwin-focused*::
|
||||
Try to detect WM windows (a non-override-redirect window with no child that has 'WM_STATE') and mark them as active.
|
||||
|
||||
|
|
|
@ -133,6 +133,22 @@ focus-exclude = [ "class_g = 'Cairo-clock'" ];
|
|||
# opacity-rule = []
|
||||
|
||||
|
||||
#################################
|
||||
# Corners #
|
||||
#################################
|
||||
|
||||
# Sets the radius of rounded window corners. When > 0, the compositor will
|
||||
# round the corners of windows. Does not interact well with
|
||||
# `transparent-clipping`.
|
||||
corner-radius = 0
|
||||
|
||||
# Exclude conditions for rounded corners.
|
||||
rounded-corners-exclude = [
|
||||
"window_type = 'dock'",
|
||||
"window_type = 'desktop'"
|
||||
];
|
||||
|
||||
|
||||
#################################
|
||||
# Background-Blurring #
|
||||
#################################
|
||||
|
|
|
@ -505,6 +505,7 @@ void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_en
|
|||
|
||||
char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
|
||||
bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask) {
|
||||
// clang-format off
|
||||
*opt = (struct options){
|
||||
.backend = BKEND_XRENDER,
|
||||
.glx_no_stencil = false,
|
||||
|
@ -537,6 +538,8 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
|
|||
.shadow_ignore_shaped = false,
|
||||
.xinerama_shadow_crop = false,
|
||||
|
||||
.corner_radius = 0,
|
||||
|
||||
.fade_in_step = 0.028,
|
||||
.fade_out_step = 0.03,
|
||||
.fade_delta = 10,
|
||||
|
@ -572,7 +575,10 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
|
|||
.no_ewmh_fullscreen = false,
|
||||
|
||||
.track_leader = false,
|
||||
|
||||
.rounded_corners_blacklist = NULL
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
char *ret = NULL;
|
||||
#ifdef CONFIG_LIBCONFIG
|
||||
|
|
|
@ -217,6 +217,10 @@ typedef struct options {
|
|||
c2_lptr_t *opacity_rules;
|
||||
/// Limit window brightness
|
||||
double max_brightness;
|
||||
// Radius of rounded window corners
|
||||
int corner_radius;
|
||||
/// Rounded corners blacklist. A linked list of conditions.
|
||||
c2_lptr_t *rounded_corners_blacklist;
|
||||
|
||||
// === Focus related ===
|
||||
/// Whether to try to detect WM windows and mark them as focused.
|
||||
|
|
|
@ -374,6 +374,10 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
|||
// --active_opacity
|
||||
if (config_lookup_float(&cfg, "active-opacity", &dval))
|
||||
opt->active_opacity = normalize_d(dval);
|
||||
// --corner-radius
|
||||
config_lookup_int(&cfg, "corner-radius", &opt->corner_radius);
|
||||
// --rounded-corners-exclude
|
||||
parse_cfg_condlst(&cfg, &opt->rounded_corners_blacklist, "rounded-corners-exclude");
|
||||
// -e (frame_opacity)
|
||||
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
|
||||
// -c (shadow_enable)
|
||||
|
|
|
@ -117,6 +117,13 @@ static void usage(const char *argv0, int ret) {
|
|||
"--active-opacity opacity\n"
|
||||
" Default opacity for active windows. (0.0 - 1.0)\n"
|
||||
"\n"
|
||||
"--corner-radius value\n"
|
||||
" Sets the radius of rounded window corners. When > 0, the compositor\n"
|
||||
" will round the corners of windows. (defaults to 0).\n"
|
||||
"\n"
|
||||
"--rounded-corners-exclude condition\n"
|
||||
" Exclude conditions for rounded corners.\n"
|
||||
"\n"
|
||||
"--mark-wmwin-focused\n"
|
||||
" Try to detect WM windows and mark them as active.\n"
|
||||
"\n"
|
||||
|
@ -440,6 +447,8 @@ static const struct option longopts[] = {
|
|||
{"blur-deviation", required_argument, NULL, 330},
|
||||
{"blur-strength", required_argument, NULL, 331},
|
||||
{"shadow-color", required_argument, NULL, 332},
|
||||
{"corner-radius", required_argument, NULL, 333},
|
||||
{"rounded-corners-exclude", required_argument, NULL, 334},
|
||||
{"experimental-backends", no_argument, NULL, 733},
|
||||
{"monitor-repaint", no_argument, NULL, 800},
|
||||
{"diagnostics", no_argument, NULL, 801},
|
||||
|
@ -859,7 +868,14 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
|||
// --blur-strength
|
||||
opt->blur_strength = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 333:
|
||||
// --cornor-radius
|
||||
opt->corner_radius = atoi(optarg);
|
||||
break;
|
||||
case 334:
|
||||
// --rounded-corners-exclude
|
||||
condlst_add(&opt->rounded_corners_blacklist, optarg);
|
||||
break;
|
||||
P_CASEBOOL(733, experimental_backends);
|
||||
P_CASEBOOL(800, monitor_repaint);
|
||||
case 801: opt->print_diagnostics = true; break;
|
||||
|
@ -986,6 +1002,13 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
|||
"properly under X Render backend.");
|
||||
}
|
||||
|
||||
if (opt->corner_radius > 0 &&
|
||||
(opt->backend != BKEND_XRENDER || opt->experimental_backends)) {
|
||||
log_warn("Rounded corner is only supported on legacy xrender backend, it "
|
||||
"will be disabled");
|
||||
opt->corner_radius = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -751,10 +751,11 @@ static struct managed_win *paint_preprocess(session_t *ps, bool *fade_running) {
|
|||
// w->mode == WMODE_SOLID or WMODE_FRAME_TRANS
|
||||
region_t *tmp = rc_region_new();
|
||||
if (w->mode == WMODE_SOLID) {
|
||||
*tmp = win_get_bounding_shape_global_by_val(w);
|
||||
*tmp =
|
||||
win_get_bounding_shape_global_without_corners_by_val(w);
|
||||
} else {
|
||||
// w->mode == WMODE_FRAME_TRANS
|
||||
win_get_region_noframe_local(w, tmp);
|
||||
win_get_region_noframe_local_without_corners(w, tmp);
|
||||
pixman_region32_intersect(tmp, tmp, &w->bounding_shape);
|
||||
pixman_region32_translate(tmp, w->g.x, w->g.y);
|
||||
}
|
||||
|
@ -1886,6 +1887,7 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
|||
c2_list_postprocess(ps, ps->o.blur_background_blacklist) &&
|
||||
c2_list_postprocess(ps, ps->o.invert_color_list) &&
|
||||
c2_list_postprocess(ps, ps->o.opacity_rules) &&
|
||||
c2_list_postprocess(ps, ps->o.rounded_corners_blacklist) &&
|
||||
c2_list_postprocess(ps, ps->o.focus_blacklist))) {
|
||||
log_error("Post-processing of conditionals failed, some of your rules "
|
||||
"might not work");
|
||||
|
@ -2263,6 +2265,7 @@ static void session_destroy(session_t *ps) {
|
|||
free_wincondlst(&ps->o.opacity_rules);
|
||||
free_wincondlst(&ps->o.paint_blacklist);
|
||||
free_wincondlst(&ps->o.unredir_if_possible_blacklist);
|
||||
free_wincondlst(&ps->o.rounded_corners_blacklist);
|
||||
|
||||
// Free tracked atom list
|
||||
{
|
||||
|
|
201
src/render.c
201
src/render.c
|
@ -229,21 +229,104 @@ uint32_t make_rectangle(int x, int y, int wid, int hei, xcb_render_trapezoid_t t
|
|||
return 1;
|
||||
}
|
||||
|
||||
void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, double opacity,
|
||||
bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex,
|
||||
const region_t *reg_paint, const glx_prog_main_t *pprogram) {
|
||||
uint32_t make_rounded_window_shape(xcb_render_trapezoid_t traps[], uint32_t max_ntraps,
|
||||
int cr, int wid, int hei) {
|
||||
uint32_t n = make_circle(cr, cr, cr, max_ntraps, traps);
|
||||
n += make_circle(wid - cr, cr, cr, max_ntraps, traps + n);
|
||||
n += make_circle(wid - cr, hei - cr, cr, max_ntraps, traps + n);
|
||||
n += make_circle(cr, hei - cr, cr, max_ntraps, traps + n);
|
||||
n += make_rectangle(0, cr, wid, hei - 2 * cr, traps + n);
|
||||
n += make_rectangle(cr, 0, wid - 2 * cr, cr, traps + n);
|
||||
n += make_rectangle(cr, hei - cr, wid - 2 * cr, cr, traps + n);
|
||||
return n;
|
||||
}
|
||||
|
||||
void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, int fullwid,
|
||||
int fullhei, double opacity, bool argb, bool neg, int cr,
|
||||
xcb_render_picture_t pict, glx_texture_t *ptex, const region_t *reg_paint,
|
||||
const glx_prog_main_t *pprogram, clip_t *clip) {
|
||||
switch (ps->o.backend) {
|
||||
case BKEND_XRENDER:
|
||||
case BKEND_XR_GLX_HYBRID: {
|
||||
auto alpha_step = (int)(opacity * MAX_ALPHA);
|
||||
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
|
||||
if (alpha_step != 0) {
|
||||
uint8_t op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC
|
||||
: XCB_RENDER_PICT_OP_OVER);
|
||||
xcb_render_composite(
|
||||
ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
||||
to_i16_checked(x), to_i16_checked(y), 0, 0, to_i16_checked(dx),
|
||||
to_i16_checked(dy), to_u16_checked(wid), to_u16_checked(hei));
|
||||
if (cr) {
|
||||
xcb_render_picture_t p_tmp = x_create_picture_with_standard(
|
||||
ps->c, ps->root, fullwid, fullhei,
|
||||
XCB_PICT_STANDARD_ARGB_32, 0, 0);
|
||||
xcb_render_color_t trans = {
|
||||
.red = 0, .blue = 0, .green = 0, .alpha = 0};
|
||||
const xcb_rectangle_t rect = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = to_u16_checked(fullwid),
|
||||
.height = to_u16_checked(fullhei)};
|
||||
xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||
p_tmp, trans, 1, &rect);
|
||||
|
||||
uint32_t max_ntraps = to_u32_checked(cr);
|
||||
xcb_render_trapezoid_t traps[4 * max_ntraps + 3];
|
||||
|
||||
uint32_t n = make_rounded_window_shape(
|
||||
traps, max_ntraps, cr, fullwid, fullhei);
|
||||
|
||||
xcb_render_trapezoids(
|
||||
ps->c, XCB_RENDER_PICT_OP_OVER, alpha_pict, p_tmp,
|
||||
x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8),
|
||||
0, 0, n, traps);
|
||||
|
||||
xcb_render_composite(
|
||||
ps->c, XCB_RENDER_PICT_OP_OVER, pict, p_tmp,
|
||||
ps->tgt_buffer.pict, to_i16_checked(x),
|
||||
to_i16_checked(y), to_i16_checked(x), to_i16_checked(y),
|
||||
to_i16_checked(dx), to_i16_checked(dy),
|
||||
to_u16_checked(wid), to_u16_checked(hei));
|
||||
|
||||
xcb_render_free_picture(ps->c, p_tmp);
|
||||
|
||||
} else {
|
||||
xcb_render_picture_t p_tmp = alpha_pict;
|
||||
if (clip) {
|
||||
p_tmp = x_create_picture_with_standard(
|
||||
ps->c, ps->root, wid, hei,
|
||||
XCB_PICT_STANDARD_ARGB_32, 0, 0);
|
||||
|
||||
xcb_render_color_t black = {
|
||||
.red = 255, .blue = 255, .green = 255, .alpha = 255};
|
||||
const xcb_rectangle_t rect = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = to_u16_checked(wid),
|
||||
.height = to_u16_checked(hei)};
|
||||
xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||
p_tmp, black, 1, &rect);
|
||||
if (alpha_pict) {
|
||||
xcb_render_composite(
|
||||
ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||
alpha_pict, XCB_NONE, p_tmp, 0, 0, 0,
|
||||
0, 0, 0, to_u16_checked(wid),
|
||||
to_u16_checked(hei));
|
||||
}
|
||||
xcb_render_composite(
|
||||
ps->c, XCB_RENDER_PICT_OP_OUT_REVERSE,
|
||||
clip->pict, XCB_NONE, p_tmp, 0, 0, 0, 0,
|
||||
to_i16_checked(clip->x), to_i16_checked(clip->y),
|
||||
to_u16_checked(wid), to_u16_checked(hei));
|
||||
}
|
||||
uint8_t op = ((!argb && !alpha_pict && !clip)
|
||||
? XCB_RENDER_PICT_OP_SRC
|
||||
: XCB_RENDER_PICT_OP_OVER);
|
||||
|
||||
xcb_render_composite(
|
||||
ps->c, op, pict, p_tmp, ps->tgt_buffer.pict,
|
||||
to_i16_checked(x), to_i16_checked(y), 0, 0,
|
||||
to_i16_checked(dx), to_i16_checked(dy),
|
||||
to_u16_checked(wid), to_u16_checked(hei));
|
||||
if (clip) {
|
||||
xcb_render_free_picture(ps->c, p_tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -269,17 +352,21 @@ paint_region(session_t *ps, const struct managed_win *w, int x, int y, int wid,
|
|||
double opacity, const region_t *reg_paint, xcb_render_picture_t pict) {
|
||||
const int dx = (w ? w->g.x : 0) + x;
|
||||
const int dy = (w ? w->g.y : 0) + y;
|
||||
const int fullwid = w ? w->widthb : 0;
|
||||
const int fullhei = w ? w->heightb : 0;
|
||||
const bool argb = (w && (win_has_alpha(w) || ps->o.force_win_blend));
|
||||
const bool neg = (w && w->invert_color);
|
||||
|
||||
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict,
|
||||
render(ps, x, y, dx, dy, wid, hei, fullwid, fullhei, opacity, argb, neg,
|
||||
w ? w->corner_radius : 0, pict,
|
||||
(w ? w->paint.ptex : ps->root_tile_paint.ptex), reg_paint,
|
||||
#ifdef CONFIG_OPENGL
|
||||
w ? &ps->glx_prog_win : NULL
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
,
|
||||
XCB_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -655,9 +742,43 @@ win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
|
|||
return;
|
||||
}
|
||||
|
||||
xcb_render_picture_t td = XCB_NONE;
|
||||
bool should_clip =
|
||||
(w->corner_radius > 0) && (!ps->o.wintype_option[w->window_type].full_shadow);
|
||||
if (should_clip) {
|
||||
uint32_t max_ntraps = to_u32_checked(w->corner_radius);
|
||||
xcb_render_trapezoid_t traps[4 * max_ntraps + 3];
|
||||
uint32_t n = make_rounded_window_shape(
|
||||
traps, max_ntraps, w->corner_radius, w->widthb, w->heightb);
|
||||
|
||||
td = x_create_picture_with_standard(ps->c, ps->root, w->widthb, w->heightb,
|
||||
XCB_PICT_STANDARD_ARGB_32, 0, 0);
|
||||
xcb_render_color_t trans = {.red = 0, .blue = 0, .green = 0, .alpha = 0};
|
||||
const xcb_rectangle_t rect = {.x = 0,
|
||||
.y = 0,
|
||||
.width = to_u16_checked(w->widthb),
|
||||
.height = to_u16_checked(w->heightb)};
|
||||
xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, td, trans, 1, &rect);
|
||||
|
||||
auto solid = solid_picture(ps->c, ps->root, false, 1, 0, 0, 0);
|
||||
xcb_render_trapezoids(ps->c, XCB_RENDER_PICT_OP_OVER, solid, td,
|
||||
x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8),
|
||||
0, 0, n, traps);
|
||||
xcb_render_free_picture(ps->c, solid);
|
||||
}
|
||||
|
||||
clip_t clip = {
|
||||
.pict = td,
|
||||
.x = -(w->shadow_dx),
|
||||
.y = -(w->shadow_dy),
|
||||
};
|
||||
render(ps, 0, 0, w->g.x + w->shadow_dx, w->g.y + w->shadow_dy, w->shadow_width,
|
||||
w->shadow_height, w->shadow_opacity, true, false, w->shadow_paint.pict,
|
||||
w->shadow_paint.ptex, reg_paint, NULL);
|
||||
w->shadow_height, w->widthb, w->heightb, w->shadow_opacity, true, false, 0,
|
||||
w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, NULL,
|
||||
should_clip ? &clip : NULL);
|
||||
if (td) {
|
||||
xcb_render_free_picture(ps->c, td);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -675,9 +796,10 @@ win_paint_shadow(session_t *ps, struct managed_win *w, region_t *reg_paint) {
|
|||
*
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y,
|
||||
uint16_t wid, uint16_t hei, struct x_convolution_kernel **blur_kerns,
|
||||
int nkernels, const region_t *reg_clip) {
|
||||
static bool
|
||||
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t x, int16_t y,
|
||||
uint16_t wid, uint16_t hei, struct x_convolution_kernel **blur_kerns,
|
||||
int nkernels, const region_t *reg_clip, xcb_render_picture_t rounded) {
|
||||
assert(blur_kerns);
|
||||
assert(blur_kerns[0]);
|
||||
|
||||
|
@ -722,7 +844,7 @@ static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int16_t
|
|||
}
|
||||
|
||||
if (src_pict != tgt_buffer)
|
||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, src_pict, rounded,
|
||||
tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
||||
|
||||
free_picture(ps->c, &tmp_picture);
|
||||
|
@ -740,6 +862,7 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
|
|||
const int16_t y = w->g.y;
|
||||
const auto wid = to_u16_checked(w->widthb);
|
||||
const auto hei = to_u16_checked(w->heightb);
|
||||
const int cr = w ? w->corner_radius : 0;
|
||||
|
||||
double factor_center = 1.0;
|
||||
// Adjust blur strength according to window opacity, to make it appear
|
||||
|
@ -771,6 +894,33 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
|
|||
&ps->blur_kerns_cache[i]);
|
||||
}
|
||||
|
||||
xcb_render_picture_t td = XCB_NONE;
|
||||
if (cr) {
|
||||
uint32_t max_ntraps = to_u32_checked(cr);
|
||||
xcb_render_trapezoid_t traps[4 * max_ntraps + 3];
|
||||
uint32_t n =
|
||||
make_rounded_window_shape(traps, max_ntraps, cr, wid, hei);
|
||||
|
||||
td = x_create_picture_with_standard(
|
||||
ps->c, ps->root, wid, hei, XCB_PICT_STANDARD_ARGB_32, 0, 0);
|
||||
xcb_render_color_t trans = {
|
||||
.red = 0, .blue = 0, .green = 0, .alpha = 0};
|
||||
const xcb_rectangle_t rect = {.x = 0,
|
||||
.y = 0,
|
||||
.width = to_u16_checked(wid),
|
||||
.height = to_u16_checked(hei)};
|
||||
xcb_render_fill_rectangles(ps->c, XCB_RENDER_PICT_OP_SRC, td,
|
||||
trans, 1, &rect);
|
||||
|
||||
auto solid = solid_picture(ps->c, ps->root, false, 1, 0, 0, 0);
|
||||
|
||||
xcb_render_trapezoids(
|
||||
ps->c, XCB_RENDER_PICT_OP_OVER, solid, td,
|
||||
x_get_pictfmt_for_standard(ps->c, XCB_PICT_STANDARD_A_8), 0,
|
||||
0, n, traps);
|
||||
xcb_render_free_picture(ps->c, solid);
|
||||
}
|
||||
|
||||
// Minimize the region we try to blur, if the window itself is not
|
||||
// opaque, only the frame is.
|
||||
region_t reg_blur = win_get_bounding_shape_global_by_val(w);
|
||||
|
@ -782,10 +932,14 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t
|
|||
pixman_region32_subtract(®_blur, ®_blur, ®_noframe);
|
||||
pixman_region32_fini(®_noframe);
|
||||
}
|
||||
|
||||
// Translate global coordinates to local ones
|
||||
pixman_region32_translate(®_blur, -x, -y);
|
||||
xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache,
|
||||
ps->o.blur_kernel_count, ®_blur);
|
||||
ps->o.blur_kernel_count, ®_blur, td);
|
||||
if (td) {
|
||||
xcb_render_free_picture(ps->c, td);
|
||||
}
|
||||
pixman_region32_clear(®_blur);
|
||||
} break;
|
||||
#ifdef CONFIG_OPENGL
|
||||
|
@ -894,7 +1048,9 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
//
|
||||
// Whether this is beneficial is to be determined XXX
|
||||
for (auto w = t; w; w = w->prev_trans) {
|
||||
region_t bshape = win_get_bounding_shape_global_by_val(w);
|
||||
region_t bshape_no_corners =
|
||||
win_get_bounding_shape_global_without_corners_by_val(w);
|
||||
region_t bshape_corners = win_get_bounding_shape_global_by_val(w);
|
||||
// Painting shadow
|
||||
if (w->shadow) {
|
||||
// Lazy shadow building
|
||||
|
@ -923,7 +1079,7 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
// saving GPU power and handling shaped windows (XXX
|
||||
// unconfirmed)
|
||||
if (!ps->o.wintype_option[w->window_type].full_shadow)
|
||||
pixman_region32_subtract(®_tmp, ®_tmp, &bshape);
|
||||
pixman_region32_subtract(®_tmp, ®_tmp, &bshape_no_corners);
|
||||
|
||||
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
|
||||
w->xinerama_scr < ps->xinerama_nscrs)
|
||||
|
@ -950,8 +1106,9 @@ void paint_all(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
// Remember, reg_ignore is the union of all windows above the current
|
||||
// window.
|
||||
pixman_region32_subtract(®_tmp, ®ion, w->reg_ignore);
|
||||
pixman_region32_intersect(®_tmp, ®_tmp, &bshape);
|
||||
pixman_region32_fini(&bshape);
|
||||
pixman_region32_intersect(®_tmp, ®_tmp, &bshape_corners);
|
||||
pixman_region32_fini(&bshape_corners);
|
||||
pixman_region32_fini(&bshape_no_corners);
|
||||
|
||||
if (pixman_region32_not_empty(®_tmp)) {
|
||||
set_tgt_clip(ps, ®_tmp);
|
||||
|
|
13
src/render.h
13
src/render.h
|
@ -25,9 +25,16 @@ typedef struct paint {
|
|||
#endif
|
||||
} paint_t;
|
||||
|
||||
void render(session_t *ps, int x, int y, int dx, int dy, int w, int h, double opacity,
|
||||
bool argb, bool neg, xcb_render_picture_t pict, glx_texture_t *ptex,
|
||||
const region_t *reg_paint, const glx_prog_main_t *pprogram);
|
||||
typedef struct clip {
|
||||
xcb_render_picture_t pict;
|
||||
int x;
|
||||
int y;
|
||||
} clip_t;
|
||||
|
||||
void render(session_t *ps, int x, int y, int dx, int dy, int w, int h, int fullw,
|
||||
int fullh, double opacity, bool argb, bool neg, int cr,
|
||||
xcb_render_picture_t pict, glx_texture_t *ptex, const region_t *reg_paint,
|
||||
const glx_prog_main_t *pprogram, clip_t *clip);
|
||||
void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint);
|
||||
|
||||
void paint_all(session_t *ps, struct managed_win *const t, bool ignore_damage);
|
||||
|
|
39
src/win.c
39
src/win.c
|
@ -79,9 +79,19 @@ static void win_update_prop_shadow(session_t *ps, struct managed_win *w);
|
|||
*/
|
||||
static void win_update_leader(session_t *ps, struct managed_win *w);
|
||||
|
||||
/// Generate a "no corners" region function, from a function that returns the
|
||||
/// region via a region_t pointer argument. Corners of the window will be removed from
|
||||
/// the returned region.
|
||||
/// Function signature has to be (win *, region_t *)
|
||||
#define gen_without_corners(fun) \
|
||||
void fun##_without_corners(const struct managed_win *w, region_t *res) { \
|
||||
fun(w, res); \
|
||||
win_region_remove_corners(w, res); \
|
||||
}
|
||||
|
||||
/// Generate a "return by value" function, from a function that returns the
|
||||
/// region via a region_t pointer argument.
|
||||
/// Function signature has to be (win *, region_t *)
|
||||
/// Function signature has to be (win *)
|
||||
#define gen_by_val(fun) \
|
||||
region_t fun##_by_val(const struct managed_win *w) { \
|
||||
region_t ret; \
|
||||
|
@ -217,9 +227,13 @@ void win_get_region_noframe_local(const struct managed_win *w, region_t *res) {
|
|||
pixman_region32_fini(res);
|
||||
if (width > 0 && height > 0) {
|
||||
pixman_region32_init_rect(res, x, y, (uint)width, (uint)height);
|
||||
} else {
|
||||
pixman_region32_init(res);
|
||||
}
|
||||
}
|
||||
|
||||
gen_without_corners(win_get_region_noframe_local);
|
||||
|
||||
void win_get_region_frame_local(const struct managed_win *w, region_t *res) {
|
||||
const margin_t extents = win_calc_frame_extents(w);
|
||||
auto outer_width = extents.left + extents.right + w->g.width;
|
||||
|
@ -1019,6 +1033,26 @@ static void win_determine_blur_background(session_t *ps, struct managed_win *w)
|
|||
win_set_blur_background(ps, w, blur_background_new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a window should have rounded corners.
|
||||
*/
|
||||
static void win_determine_rounded_corners(session_t *ps, struct managed_win *w) {
|
||||
if (ps->o.corner_radius == 0) {
|
||||
w->corner_radius = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't round full screen windows & excluded windows
|
||||
if ((w && win_is_fullscreen(ps, w)) ||
|
||||
c2_match(ps, w, ps->o.rounded_corners_blacklist, NULL)) {
|
||||
w->corner_radius = 0;
|
||||
log_debug("Not rounding corners for window %#010x", w->base.id);
|
||||
} else {
|
||||
w->corner_radius = ps->o.corner_radius;
|
||||
log_debug("Rounding corners for window %#010x", w->base.id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update window opacity according to opacity rules.
|
||||
*/
|
||||
|
@ -1053,6 +1087,7 @@ void win_on_factor_change(session_t *ps, struct managed_win *w) {
|
|||
win_determine_shadow(ps, w);
|
||||
win_determine_invert_color(ps, w);
|
||||
win_determine_blur_background(ps, w);
|
||||
win_determine_rounded_corners(ps, w);
|
||||
w->mode = win_calc_mode(w);
|
||||
log_debug("Window mode changed to %d", w->mode);
|
||||
win_update_opacity_rule(ps, w);
|
||||
|
@ -1413,6 +1448,8 @@ struct win *fill_win(session_t *ps, struct win *w) {
|
|||
// Initialized during paint
|
||||
.paint = PAINT_INIT,
|
||||
.shadow_paint = PAINT_INIT,
|
||||
|
||||
.corner_radius = 0,
|
||||
};
|
||||
|
||||
assert(!w->destroyed);
|
||||
|
|
32
src/win.h
32
src/win.h
|
@ -208,6 +208,9 @@ struct managed_win {
|
|||
/// Last window opacity value set by the rules.
|
||||
double opacity_set;
|
||||
|
||||
/// Radius of rounded window corners
|
||||
int corner_radius;
|
||||
|
||||
// Fading-related members
|
||||
/// Override value of window fade state. Set by D-Bus method calls.
|
||||
switch_t fade_force;
|
||||
|
@ -348,6 +351,7 @@ void add_damage_from_win(session_t *ps, const struct managed_win *w);
|
|||
* Return region in global coordinates.
|
||||
*/
|
||||
void win_get_region_noframe_local(const struct managed_win *w, region_t *);
|
||||
void win_get_region_noframe_local_without_corners(const struct managed_win *w, region_t *);
|
||||
|
||||
/// Get the region for the frame of the window
|
||||
void win_get_region_frame_local(const struct managed_win *w, region_t *res);
|
||||
|
@ -438,6 +442,24 @@ static inline attr_unused void win_set_property_stale(struct managed_win *w, xcb
|
|||
/// Free all resources in a struct win
|
||||
void free_win_res(session_t *ps, struct managed_win *w);
|
||||
|
||||
static inline void win_region_remove_corners(const struct managed_win *w, region_t *res) {
|
||||
region_t corners;
|
||||
pixman_region32_init_rects(
|
||||
&corners,
|
||||
(rect_t[]){
|
||||
{.x1 = 0, .y1 = 0, .x2 = w->corner_radius, .y2 = w->corner_radius},
|
||||
{.x1 = 0, .y1 = w->heightb - w->corner_radius, .x2 = w->corner_radius, .y2 = w->heightb},
|
||||
{.x1 = w->widthb - w->corner_radius, .y1 = 0, .x2 = w->widthb, .y2 = w->corner_radius},
|
||||
{.x1 = w->widthb - w->corner_radius,
|
||||
.y1 = w->heightb - w->corner_radius,
|
||||
.x2 = w->widthb,
|
||||
.y2 = w->heightb},
|
||||
},
|
||||
4);
|
||||
pixman_region32_subtract(res, res, &corners);
|
||||
pixman_region32_fini(&corners);
|
||||
}
|
||||
|
||||
static inline region_t attr_unused win_get_bounding_shape_global_by_val(struct managed_win *w) {
|
||||
region_t ret;
|
||||
pixman_region32_init(&ret);
|
||||
|
@ -446,6 +468,16 @@ static inline region_t attr_unused win_get_bounding_shape_global_by_val(struct m
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline region_t
|
||||
win_get_bounding_shape_global_without_corners_by_val(struct managed_win *w) {
|
||||
region_t ret;
|
||||
pixman_region32_init(&ret);
|
||||
pixman_region32_copy(&ret, &w->bounding_shape);
|
||||
win_region_remove_corners(w, &ret);
|
||||
pixman_region32_translate(&ret, w->g.x, w->g.y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the extents of the frame of the given window based on EWMH
|
||||
* _NET_FRAME_EXTENTS and the X window border width.
|
||||
|
|
Loading…
Reference in New Issue