mirror of
https://github.com/swaywm/sway.git
synced 2026-04-17 06:46:32 -04:00
config/output: Store output configs sequentially
The current output configuration system merges configurations such that only one configuration per match is stored. This is a simplification of a previous design and has the benefit that a minimal number of output configurations are retained, but to correctly merge and supersede configurations it is required that an identifier can be resolved from a connector, which leads to differences in how output configurations are interpreted based on whether a display is currently connected or not. Instead, append all new output configurations to the list as they are made, and remove old output configurations once all their settings have been overwritten by newer configurations. Based on ideas from https://github.com/swaywm/sway/pull/5629 Fixes: https://github.com/swaywm/sway/issues/5632
This commit is contained in:
parent
7e7994dbb2
commit
4225cebdf9
1 changed files with 55 additions and 52 deletions
|
|
@ -82,6 +82,30 @@ struct output_config *new_output_config(const char *name) {
|
||||||
return oc;
|
return oc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool empty_output_config(struct output_config *oc) {
|
||||||
|
return oc->enabled == -1 &&
|
||||||
|
oc->width == -1 &&
|
||||||
|
oc->height == -1 &&
|
||||||
|
oc->x == INT_MAX &&
|
||||||
|
oc->y == INT_MAX &&
|
||||||
|
oc->scale == -1 &&
|
||||||
|
oc->scale_filter == SCALE_FILTER_DEFAULT &&
|
||||||
|
oc->subpixel == WL_OUTPUT_SUBPIXEL_UNKNOWN &&
|
||||||
|
oc->refresh_rate == -1 &&
|
||||||
|
oc->custom_mode == -1 &&
|
||||||
|
oc->drm_mode.type == (uint32_t)-1 &&
|
||||||
|
oc->transform == -1 &&
|
||||||
|
oc->max_render_time == -1 &&
|
||||||
|
oc->adaptive_sync == -1 &&
|
||||||
|
oc->render_bit_depth == RENDER_BIT_DEPTH_DEFAULT &&
|
||||||
|
oc->set_color_transform == false &&
|
||||||
|
oc->background == NULL &&
|
||||||
|
oc->background_option == NULL &&
|
||||||
|
oc->background_fallback == NULL &&
|
||||||
|
oc->power == -1 &&
|
||||||
|
oc->allow_tearing == -1;
|
||||||
|
}
|
||||||
|
|
||||||
// supersede_output_config clears all fields in dst that were set in src
|
// supersede_output_config clears all fields in dst that were set in src
|
||||||
static void supersede_output_config(struct output_config *dst, struct output_config *src) {
|
static void supersede_output_config(struct output_config *dst, struct output_config *src) {
|
||||||
if (src->enabled != -1) {
|
if (src->enabled != -1) {
|
||||||
|
|
@ -232,57 +256,37 @@ static void merge_output_config(struct output_config *dst, struct output_config
|
||||||
}
|
}
|
||||||
|
|
||||||
void store_output_config(struct output_config *oc) {
|
void store_output_config(struct output_config *oc) {
|
||||||
bool merged = false;
|
|
||||||
bool wildcard = strcmp(oc->name, "*") == 0;
|
bool wildcard = strcmp(oc->name, "*") == 0;
|
||||||
struct sway_output *output = wildcard ? NULL : all_output_by_name_or_id(oc->name);
|
|
||||||
|
|
||||||
char id[128];
|
// Supersede any existing configurations that match by clearing settings
|
||||||
if (output) {
|
// that can no longer be reached anyway, which allows us to later garbage
|
||||||
output_get_identifier(id, sizeof(id), output);
|
// collect configurations that no longer have any value
|
||||||
}
|
struct output_config *old = NULL;
|
||||||
|
for (int idx = 0; idx < config->output_configs->length; idx++) {
|
||||||
for (int i = 0; i < config->output_configs->length; i++) {
|
old = config->output_configs->items[idx];
|
||||||
struct output_config *old = config->output_configs->items[i];
|
if (wildcard || strcmp(old->name, oc->name) == 0) {
|
||||||
|
|
||||||
// If the old config matches the new config's name, regardless of
|
|
||||||
// whether it was name or identifier, merge on top of the existing
|
|
||||||
// config. If the new config is a wildcard, this also merges on top of
|
|
||||||
// old wildcard configs.
|
|
||||||
if (strcmp(old->name, oc->name) == 0) {
|
|
||||||
merge_output_config(old, oc);
|
|
||||||
merged = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the new config is a wildcard config we supersede all non-wildcard
|
|
||||||
// configs. Old wildcard configs have already been handled above.
|
|
||||||
if (wildcard) {
|
|
||||||
supersede_output_config(old, oc);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the new config matches an output's name, and the old config
|
|
||||||
// matches on that output's identifier, supersede it.
|
|
||||||
if (output && strcmp(old->name, id) == 0 &&
|
|
||||||
strcmp(oc->name, output->wlr_output->name) == 0) {
|
|
||||||
supersede_output_config(old, oc);
|
supersede_output_config(old, oc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
|
// As a very minor optimization, if the last config is for the same name,
|
||||||
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) "
|
// we can merge with that instead of adding a new config, reducing the
|
||||||
"(max render time: %d) (allow tearing: %d)",
|
// number of configs when sequentially changing different settings
|
||||||
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
|
if (old != NULL && strcmp(old->name, oc->name) == 0) {
|
||||||
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
|
merge_output_config(old, oc);
|
||||||
oc->transform, oc->background, oc->background_option, oc->power,
|
|
||||||
oc->max_render_time, oc->allow_tearing);
|
|
||||||
|
|
||||||
// If the configuration was not merged into an existing configuration, add
|
|
||||||
// it to the list. Otherwise we're done with it and can free it.
|
|
||||||
if (!merged) {
|
|
||||||
list_add(config->output_configs, oc);
|
|
||||||
} else {
|
|
||||||
free_output_config(oc);
|
free_output_config(oc);
|
||||||
|
} else {
|
||||||
|
list_add(config->output_configs, oc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any configurations that have had all their settings removed
|
||||||
|
for (int idx = 0; idx < config->output_configs->length; idx++) {
|
||||||
|
old = config->output_configs->items[idx];
|
||||||
|
if (empty_output_config(old)) {
|
||||||
|
list_del(config->output_configs, idx);
|
||||||
|
free_output_config(old);
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,14 +592,13 @@ static struct output_config *find_output_config_from_list(
|
||||||
char id[128];
|
char id[128];
|
||||||
output_get_identifier(id, sizeof(id), sway_output);
|
output_get_identifier(id, sizeof(id), sway_output);
|
||||||
|
|
||||||
// We take a new config and merge on top, in order, the wildcard config,
|
// To create the output config for this output, we merge all configurations
|
||||||
// output config by name, and output config by identifier to form the final
|
// that match the output in the order they were stored, such that later
|
||||||
// config. If there are multiple matches, they are merged in order.
|
// configurations override earlier ones
|
||||||
struct output_config *oc = NULL;
|
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||||
const char *names[] = {"*", name, id, NULL};
|
struct output_config *oc = configs[idx];
|
||||||
for (const char **name = &names[0]; *name; name++) {
|
const char *names[] = {"*", name, id, NULL};
|
||||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
for (const char **name = &names[0]; *name; name++) {
|
||||||
oc = configs[idx];
|
|
||||||
if (strcmp(oc->name, *name) == 0) {
|
if (strcmp(oc->name, *name) == 0) {
|
||||||
merge_output_config(result, oc);
|
merge_output_config(result, oc);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue