mirror of
https://github.com/yshui/picom.git
synced 2024-11-25 14:06:08 -05:00
Add corner-radius-rules configuration option
This option accepts a list of patterns and overrides the corner radii of matching windows Authored-by: oofsauce <alanpanayotov@gmail.com> Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
cee1287562
commit
6d459badbc
6 changed files with 76 additions and 19 deletions
|
@ -103,6 +103,9 @@ OPTIONS
|
||||||
*--corner-radius* 'VALUE'::
|
*--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).
|
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).
|
||||||
|
|
||||||
|
*--corner-radius-rules* 'RADIUS':'CONDITION'::
|
||||||
|
Specify a list of corner radius rules. Overrides the corner radii of matching windows. This option takes precedence over the *--rounded-corners-exclude* option, and also overrides the default exclusion of fullscreen windows. The condition has the same format as *--opacity-rule*.
|
||||||
|
|
||||||
*--rounded-corners-exclude* 'CONDITION'::
|
*--rounded-corners-exclude* 'CONDITION'::
|
||||||
Exclude conditions for rounded corners.
|
Exclude conditions for rounded corners.
|
||||||
|
|
||||||
|
|
23
src/config.c
23
src/config.c
|
@ -509,32 +509,37 @@ parse_geometry_end:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a list of opacity rules.
|
* Parse a list of window rules, prefixed with a number, separated by a ':'
|
||||||
*/
|
*/
|
||||||
bool parse_rule_opacity(c2_lptr_t **res, const char *src) {
|
bool parse_numeric_window_rule(c2_lptr_t **res, const char *src, long min, long max) {
|
||||||
// Find opacity value
|
if (!src) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find numeric value
|
||||||
char *endptr = NULL;
|
char *endptr = NULL;
|
||||||
long val = strtol(src, &endptr, 0);
|
long val = strtol(src, &endptr, 0);
|
||||||
if (!endptr || endptr == src) {
|
if (!endptr || endptr == src) {
|
||||||
log_error("No opacity specified: %s", src);
|
log_error("No number specified: %s", src);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (val > 100 || val < 0) {
|
|
||||||
log_error("Opacity %ld invalid: %s", val, src);
|
if (val < min || val > max) {
|
||||||
|
log_error("Number not in range (%ld <= n <= %ld): %s", min, max, src);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip over spaces
|
// Skip over spaces
|
||||||
while (*endptr && isspace((unsigned char)*endptr))
|
while (*endptr && isspace((unsigned char)*endptr)) {
|
||||||
++endptr;
|
++endptr;
|
||||||
|
}
|
||||||
if (':' != *endptr) {
|
if (':' != *endptr) {
|
||||||
log_error("Opacity terminator not found: %s", src);
|
log_error("Number separator (':') not found: %s", src);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
++endptr;
|
++endptr;
|
||||||
|
|
||||||
// Parse pattern
|
// Parse pattern
|
||||||
// I hope 1-100 is acceptable for (void *)
|
|
||||||
return c2_parse(res, endptr, (void *)val);
|
return c2_parse(res, endptr, (void *)val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,8 @@ typedef struct options {
|
||||||
int corner_radius;
|
int corner_radius;
|
||||||
/// Rounded corners blacklist. A linked list of conditions.
|
/// Rounded corners blacklist. A linked list of conditions.
|
||||||
c2_lptr_t *rounded_corners_blacklist;
|
c2_lptr_t *rounded_corners_blacklist;
|
||||||
|
/// Rounded corner rules. A linked list of conditions.
|
||||||
|
c2_lptr_t *corner_radius_rules;
|
||||||
|
|
||||||
// === Focus related ===
|
// === Focus related ===
|
||||||
/// Whether to try to detect WM windows and mark them as focused.
|
/// Whether to try to detect WM windows and mark them as focused.
|
||||||
|
@ -266,7 +268,7 @@ bool must_use parse_long(const char *, long *);
|
||||||
bool must_use parse_int(const char *, int *);
|
bool must_use parse_int(const char *, int *);
|
||||||
struct conv **must_use parse_blur_kern_lst(const char *, bool *hasneg, int *count);
|
struct conv **must_use parse_blur_kern_lst(const char *, bool *hasneg, int *count);
|
||||||
bool must_use parse_geometry(session_t *, const char *, region_t *);
|
bool must_use parse_geometry(session_t *, const char *, region_t *);
|
||||||
bool must_use parse_rule_opacity(c2_lptr_t **, const char *);
|
bool must_use parse_numeric_window_rule(c2_lptr_t **, const char *, long, long);
|
||||||
bool must_use parse_rule_window_shader(c2_lptr_t **, const char *, const char *);
|
bool must_use parse_rule_window_shader(c2_lptr_t **, const char *, const char *);
|
||||||
char *must_use locate_auxiliary_file(const char *scope, const char *path,
|
char *must_use locate_auxiliary_file(const char *scope, const char *path,
|
||||||
const char *include_dir);
|
const char *include_dir);
|
||||||
|
|
|
@ -135,6 +135,32 @@ void parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, const char *n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a window corner radius rule list in configuration file.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
parse_cfg_condlst_corner(options_t *opt, const config_t *pcfg, const char *name) {
|
||||||
|
config_setting_t *setting = config_lookup(pcfg, name);
|
||||||
|
if (setting) {
|
||||||
|
// Parse an array of options
|
||||||
|
if (config_setting_is_array(setting)) {
|
||||||
|
int i = config_setting_length(setting);
|
||||||
|
while (i--)
|
||||||
|
if (!parse_numeric_window_rule(
|
||||||
|
&opt->corner_radius_rules,
|
||||||
|
config_setting_get_string_elem(setting, i), 0, INT_MAX))
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// Treat it as a single pattern if it's a string
|
||||||
|
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||||
|
if (!parse_numeric_window_rule(&opt->corner_radius_rules,
|
||||||
|
config_setting_get_string(setting),
|
||||||
|
0, INT_MAX))
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an opacity rule list in configuration file.
|
* Parse an opacity rule list in configuration file.
|
||||||
*/
|
*/
|
||||||
|
@ -146,15 +172,15 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
|
||||||
if (config_setting_is_array(setting)) {
|
if (config_setting_is_array(setting)) {
|
||||||
int i = config_setting_length(setting);
|
int i = config_setting_length(setting);
|
||||||
while (i--)
|
while (i--)
|
||||||
if (!parse_rule_opacity(
|
if (!parse_numeric_window_rule(
|
||||||
&opt->opacity_rules,
|
&opt->opacity_rules,
|
||||||
config_setting_get_string_elem(setting, i)))
|
config_setting_get_string_elem(setting, i), 0, 100))
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
// Treat it as a single pattern if it's a string
|
// Treat it as a single pattern if it's a string
|
||||||
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||||
if (!parse_rule_opacity(&opt->opacity_rules,
|
if (!parse_numeric_window_rule(
|
||||||
config_setting_get_string(setting)))
|
&opt->opacity_rules, config_setting_get_string(setting), 0, 100))
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,6 +360,9 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
config_lookup_int(&cfg, "corner-radius", &opt->corner_radius);
|
config_lookup_int(&cfg, "corner-radius", &opt->corner_radius);
|
||||||
// --rounded-corners-exclude
|
// --rounded-corners-exclude
|
||||||
parse_cfg_condlst(&cfg, &opt->rounded_corners_blacklist, "rounded-corners-exclude");
|
parse_cfg_condlst(&cfg, &opt->rounded_corners_blacklist, "rounded-corners-exclude");
|
||||||
|
// --corner-radius-rules
|
||||||
|
parse_cfg_condlst_corner(opt, &cfg, "corner-radius-rules");
|
||||||
|
|
||||||
// -e (frame_opacity)
|
// -e (frame_opacity)
|
||||||
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
|
config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
|
||||||
// -c (shadow_enable)
|
// -c (shadow_enable)
|
||||||
|
|
|
@ -161,6 +161,7 @@ static const struct picom_option picom_options[] = {
|
||||||
{"corner-radius" , required_argument, 333, NULL , "Sets the radius of rounded window corners. When > 0, the compositor will "
|
{"corner-radius" , required_argument, 333, NULL , "Sets the radius of rounded window corners. When > 0, the compositor will "
|
||||||
"round the corners of windows. (defaults to 0)."},
|
"round the corners of windows. (defaults to 0)."},
|
||||||
{"rounded-corners-exclude" , required_argument, 334, "COND" , "Exclude conditions for rounded corners."},
|
{"rounded-corners-exclude" , required_argument, 334, "COND" , "Exclude conditions for rounded corners."},
|
||||||
|
{"corner-radius-rules" , required_argument, 340, "RADIUS:COND" , "Window rules for specific rounded corner radii."},
|
||||||
{"clip-shadow-above" , required_argument, 335, NULL , "Specify a list of conditions of windows to not paint a shadow over, such "
|
{"clip-shadow-above" , required_argument, 335, NULL , "Specify a list of conditions of windows to not paint a shadow over, such "
|
||||||
"as a dock window."},
|
"as a dock window."},
|
||||||
{"window-shader-fg" , required_argument, 336, "PATH" , "Specify GLSL fragment shader path for rendering window contents. Does not"
|
{"window-shader-fg" , required_argument, 336, "PATH" , "Specify GLSL fragment shader path for rendering window contents. Does not"
|
||||||
|
@ -174,6 +175,7 @@ static const struct picom_option picom_options[] = {
|
||||||
{"dithered-present" , no_argument , 339, NULL , "Use higher precision during rendering, and apply dither when presenting the "
|
{"dithered-present" , no_argument , 339, NULL , "Use higher precision during rendering, and apply dither when presenting the "
|
||||||
"rendered screen. Reduces banding artifacts, but might cause performance "
|
"rendered screen. Reduces banding artifacts, but might cause performance "
|
||||||
"degradation. Only works with OpenGL."},
|
"degradation. Only works with OpenGL."},
|
||||||
|
// 340 is corner-radius-rules
|
||||||
{"legacy-backends" , no_argument , 733, NULL , "Use deprecated version of the backends."},
|
{"legacy-backends" , no_argument , 733, NULL , "Use deprecated version of the backends."},
|
||||||
{"monitor-repaint" , no_argument , 800, NULL , "Highlight the updated area of the screen. For debugging."},
|
{"monitor-repaint" , no_argument , 800, NULL , "Highlight the updated area of the screen. For debugging."},
|
||||||
{"diagnostics" , no_argument , 801, NULL , "Print diagnostic information"},
|
{"diagnostics" , no_argument , 801, NULL , "Print diagnostic information"},
|
||||||
|
@ -619,7 +621,7 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
break;
|
break;
|
||||||
case 304:
|
case 304:
|
||||||
// --opacity-rule
|
// --opacity-rule
|
||||||
if (!parse_rule_opacity(&opt->opacity_rules, optarg))
|
if (!parse_numeric_window_rule(&opt->opacity_rules, optarg, 0, 100))
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
case 305:
|
case 305:
|
||||||
|
@ -723,6 +725,11 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
|
||||||
// --rounded-corners-exclude
|
// --rounded-corners-exclude
|
||||||
condlst_add(&opt->rounded_corners_blacklist, optarg);
|
condlst_add(&opt->rounded_corners_blacklist, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 340:
|
||||||
|
// --corner-radius-rules
|
||||||
|
if (!parse_numeric_window_rule(&opt->corner_radius_rules, optarg, 0, INT_MAX))
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
case 335:
|
case 335:
|
||||||
// --clip-shadow-above
|
// --clip-shadow-above
|
||||||
condlst_add(&opt->shadow_clip_list, optarg);
|
condlst_add(&opt->shadow_clip_list, optarg);
|
||||||
|
|
19
src/win.c
19
src/win.c
|
@ -1139,13 +1139,24 @@ static void win_determine_rounded_corners(session_t *ps, struct managed_win *w)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't round full screen windows & excluded windows
|
void *radius_override = NULL;
|
||||||
if ((w && win_is_fullscreen(ps, w)) ||
|
if (c2_match(ps, w, ps->o.corner_radius_rules, &radius_override)) {
|
||||||
c2_match(ps, w, ps->o.rounded_corners_blacklist, NULL)) {
|
log_debug("Matched corner rule! %d", w->corner_radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't round full screen windows & excluded windows,
|
||||||
|
// unless we find a corner override in corner_radius_rules
|
||||||
|
if (!radius_override && ((w && win_is_fullscreen(ps, w)) ||
|
||||||
|
c2_match(ps, w, ps->o.rounded_corners_blacklist, NULL))) {
|
||||||
w->corner_radius = 0;
|
w->corner_radius = 0;
|
||||||
log_debug("Not rounding corners for window %#010x", w->base.id);
|
log_debug("Not rounding corners for window %#010x", w->base.id);
|
||||||
} else {
|
} else {
|
||||||
w->corner_radius = ps->o.corner_radius;
|
if (radius_override) {
|
||||||
|
w->corner_radius = (int)(long)radius_override;
|
||||||
|
} else {
|
||||||
|
w->corner_radius = ps->o.corner_radius;
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("Rounding corners for window %#010x", w->base.id);
|
log_debug("Rounding corners for window %#010x", w->base.id);
|
||||||
// Initialize the border color to an invalid value
|
// Initialize the border color to an invalid value
|
||||||
w->border_col[0] = w->border_col[1] = w->border_col[2] =
|
w->border_col[0] = w->border_col[1] = w->border_col[2] =
|
||||||
|
|
Loading…
Reference in a new issue