This commit is contained in:
Kenny Levinsen 2025-07-04 10:39:01 +08:00 committed by GitHub
commit eb875a49e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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);
} }