Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config: try to convert legacy parameters to rules #1327

Open
wants to merge 5 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ bool load_plugin(const char *name, const char *include_dir) {
return handle != NULL;
}

bool parse_config(options_t *opt, const char *config_file) {
bool parse_config(options_t *opt, const char *config_file, config_t *release_cfg) {
// clang-format off
*opt = (struct options){
.legacy_backend = BKEND_XRENDER,
Expand Down Expand Up @@ -738,5 +738,5 @@ bool parse_config(options_t *opt, const char *config_file) {
list_init_head(&opt->rules);

opt->all_scripts = dynarr_new(struct script *, 4);
return parse_config_libconfig(opt, config_file);
return parse_config_libconfig(opt, config_file, release_cfg);
}
17 changes: 15 additions & 2 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ typedef struct options {
switch_t stoppaint_force;
/// Whether to enable D-Bus support.
bool dbus;
/// Dump configuration file to stdout.
bool dump_config;
/// Path to log file.
char *logpath;
/// Number of cycles to paint in benchmark mode. 0 for disabled.
Expand Down Expand Up @@ -442,6 +444,17 @@ typedef struct options {
bool has_both_style_of_rules;
} options_t;

// compatibility of *-exclude parameters with rules
typedef struct rule_replacement {
const char *exclude;
const char *parameter;
int type;
union {
bool boolean;
double floating;
} value;
} rule_replacement_t;

extern const char *const BACKEND_STRS[NUM_BKEND + 1];

bool load_plugin(const char *name, const char *include_dir);
Expand Down Expand Up @@ -472,13 +485,13 @@ char **xdg_config_dirs(void);
/// win_option_mask = whether option overrides for specific window type is set for given
/// options
/// hasneg = whether the convolution kernel has negative values
bool parse_config_libconfig(options_t *, const char *config_file);
bool parse_config_libconfig(options_t *, const char *config_file, config_t *release_cfg);

/// Parse a configuration file is that is enabled, also initialize the winopt_mask with
/// default values
/// Outputs and returns:
/// same as parse_config_libconfig
bool parse_config(options_t *, const char *config_file);
bool parse_config(options_t *, const char *config_file, config_t *release_cfg);

/**
* Parse a backend option argument.
Expand Down
136 changes: 119 additions & 17 deletions src/config_libconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,103 @@ FILE *open_config_file(const char *cpath, char **ppath) {
return NULL;
}

/**
* Convert legacy *-exclude parameters into rules.
*
* For example:
* shadow-exclude = [
* "name = 'Program'"
* ];
*
* will be added to rules as entry:
*
* { match = "name = 'Program'", shadow = false; }
*/
void create_rules_compat(const config_t *pcfg, config_setting_t *rules_setting,
const rule_replacement_t *replacement) {
config_setting_t *setting = config_lookup(pcfg, replacement->exclude);
if (setting == NULL) {
return;
}

if (config_setting_is_array(setting)) {
int len = config_setting_length(setting);

if (len > 0) {
log_warn("Trying to convert parameters of \"%s\" into rules.",
replacement->exclude);
}

for (int i = 0; i < len; i++) {
auto rule =
config_setting_add(rules_setting, NULL, CONFIG_TYPE_GROUP);
auto match = config_setting_add(rule, "match", CONFIG_TYPE_STRING);
config_setting_set_string(
match, config_setting_get_string_elem(setting, i));
auto param = config_setting_add(rule, replacement->parameter,
replacement->type);
if (replacement->type == CONFIG_TYPE_BOOL) {
config_setting_set_bool(param, replacement->value.boolean);
} else if (replacement->type == CONFIG_TYPE_FLOAT) {
config_setting_set_float(param, replacement->value.floating);
}
}
} else if (config_setting_is_group(setting) &&
!strcmp(config_setting_name(setting), "wintypes")) {
int len = config_setting_length(setting);

if (len > 0) {
log_warn("Trying to convert wintypes into rules.");
}

for (unsigned i = 0; i < (unsigned)len; i++) {
auto wintype = config_setting_get_elem(setting, i);

auto rule =
config_setting_add(rules_setting, NULL, CONFIG_TYPE_GROUP);
auto match = config_setting_add(rule, "match", CONFIG_TYPE_STRING);
char *match_str;
asprintf(&match_str, "window_type = '%s'",
config_setting_name(wintype));
config_setting_set_string(match, match_str);
free(match_str);

for (unsigned j = 0; j < (unsigned)config_setting_length(wintype); j++) {
auto param = config_setting_get_elem(wintype, j);
const char *param_name = config_setting_name(param);

if (!strcmp(param_name, "redir-ignore")) {
param_name = "unredir";
} else if (!strcmp(param_name, "focus")) {
log_warn("Rules have no equevalent for wintypes' "
"\"focus\" parameter.");
continue;
}

auto new_param = config_setting_add(
rule, param_name, config_setting_type(param));

if (config_setting_type(param) == CONFIG_TYPE_BOOL) {
bool val = config_setting_get_bool(param);

if (!strcmp(param_name, "unredir")) {
val = !val;
}

config_setting_set_bool(new_param, val);
} else if (config_setting_type(param) == CONFIG_TYPE_FLOAT) {
config_setting_set_float(
new_param, config_setting_get_float(param));
} else {
log_warn("Data type %d is not yet implemented "
"for converting wintypes!",
config_setting_type(param));
}
}
}
}
}

/**
* Parse a condition list in configuration file.
*/
Expand Down Expand Up @@ -671,7 +768,7 @@ resolve_include(config_t *cfg, const char *include_dir, const char *path, const
*
* Returns if config is successfully parsed.
*/
bool parse_config_libconfig(options_t *opt, const char *config_file) {
bool parse_config_libconfig(options_t *opt, const char *config_file, config_t *release_cfg) {

const char *deprecation_message =
"option has been deprecated. Please remove it from your configuration file. "
Expand Down Expand Up @@ -765,6 +862,23 @@ bool parse_config_libconfig(options_t *opt, const char *config_file) {

config_setting_t *rules = config_lookup(&cfg, "rules");
if (rules) {
static const rule_replacement_t replacements[] = {
{"blur-background-exclude", "blur-background", CONFIG_TYPE_BOOL, {.boolean = false}},
{"shadow-exclude", "shadow", CONFIG_TYPE_BOOL, {.boolean = false}},
{"fade-exclude", "fade", CONFIG_TYPE_BOOL, {.boolean = false}},
{"rounded-corners-exclude", "corner-radius", CONFIG_TYPE_FLOAT, {.floating = 0.0f}},
{"unredir-if-possible-exclude", "unredir", CONFIG_TYPE_BOOL, {.boolean = false}},
{"invert-color-include", "invert-color", CONFIG_TYPE_BOOL, {.boolean = true}},
{"transparent-clipping-exclude",
"transparent-clipping",
CONFIG_TYPE_BOOL,
{.boolean = false}},
{"wintypes", NULL, 0, 0}};

for (size_t i = 0; i < sizeof(replacements) / sizeof(*replacements); i++) {
create_rules_compat(&cfg, rules, &replacements[i]);
}

parse_rules(&opt->rules, rules, &opt->all_scripts);
c2_condition_list_foreach(&opt->rules, i) {
auto data = (struct window_maybe_options *)c2_condition_get_data(i);
Expand Down Expand Up @@ -974,21 +1088,9 @@ bool parse_config_libconfig(options_t *opt, const char *config_file) {
lcfg_lookup_bool(&cfg, "dithered-present", &opt->dithered_present);

if (!list_is_empty(&opt->rules)) {
static const char *rule_list[] = {
"transparent-clipping-exclude",
"shadow-exclude",
"clip-shadow-above",
"fade-exclude",
"focus-exclude",
"invert-color-include",
"blur-background-exclude",
"unredir-if-possible-exclude",
"rounded-corners-exclude",
"corner-radius-rules",
"opacity-rule",
"window-shader-fg-rule",
"wintypes",
};
static const char *rule_list[] = {"clip-shadow-above", "focus-exclude",
"corner-radius-rules", "opacity-rule",
"window-shader-fg-rule"};
for (size_t i = 0; i < sizeof(rule_list) / sizeof(rule_list[0]); i++) {
if (config_lookup(&cfg, rule_list[i])) {
log_warn_both_style_of_rules(rule_list[i]);
Expand Down Expand Up @@ -1168,7 +1270,7 @@ bool parse_config_libconfig(options_t *opt, const char *config_file) {
succeeded = true;

out:
config_destroy(&cfg);
*release_cfg = cfg;
free(path);
return succeeded;
}
3 changes: 3 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ static const struct picom_option picom_options[] = {
"transparent clipping applied. Useful for screenshot tools, where you "
"need to be able to see through transparent parts of the window."},

[342] = {"dump-config" , ENABLE(dump_config), "Dump config file to stdout. "
"Useful when you want to get legacy parameter conversions."},

// Rules that are too long to fit in one line
[304] = {"opacity-rule" , NUMERIC_RULES(opacity_rules, "OPACITY", 0, 100),
"Specify a list of opacity rules, see man page for more details"},
Expand Down
14 changes: 13 additions & 1 deletion src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -2184,18 +2184,30 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
ps->glx_event = ext_info->first_event;
}

// The value to which the config will be written after loading
config_t cfg;
memset(&cfg, 0, sizeof(config_t));

// Parse configuration file
if (!parse_config(&ps->o, config_file)) {
if (!parse_config(&ps->o, config_file, &cfg)) {
config_destroy(&cfg);
return NULL;
}

// Parse all of the rest command line options
if (!get_cfg(&ps->o, argc, argv)) {
config_destroy(&cfg);
log_fatal("Failed to get configuration, usually mean you have specified "
"invalid options.");
return NULL;
}

if (ps->o.dump_config && cfg.root) {
config_write(&cfg, stdout);
}

config_destroy(&cfg);

const char *basename = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];

if (strcmp(basename, "picom-inspect") == 0) {
Expand Down