aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/config.h9
-rw-r--r--sway/config/output.c296
2 files changed, 143 insertions, 162 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index 40710199..0be1cd22 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -693,7 +693,14 @@ bool apply_output_configs(struct matched_output_config *configs,
void apply_all_output_configs(void);
-struct output_config *store_output_config(struct output_config *oc);
+/**
+ * store_output_config stores a new output config. An output may be matched by
+ * three different config types, in order of precedence: Identifier, name and
+ * wildcard. When storing a config type of lower precedence, assume that the
+ * user wants the config to take immediate effect by superseding (clearing) the
+ * same values from higher presedence configuration.
+ */
+void store_output_config(struct output_config *oc);
struct output_config *find_output_config(struct sway_output *output);
diff --git a/sway/config/output.c b/sway/config/output.c
index 3f1c3126..e5ff240a 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -79,6 +79,71 @@ struct output_config *new_output_config(const char *name) {
return oc;
}
+// 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) {
+ if (src->enabled != -1) {
+ dst->enabled = -1;
+ }
+ if (src->width != -1) {
+ dst->width = -1;
+ }
+ if (src->height != -1) {
+ dst->height = -1;
+ }
+ if (src->x != -1) {
+ dst->x = -1;
+ }
+ if (src->y != -1) {
+ dst->y = -1;
+ }
+ if (src->scale != -1) {
+ dst->scale = -1;
+ }
+ if (src->scale_filter != SCALE_FILTER_DEFAULT) {
+ dst->scale_filter = SCALE_FILTER_DEFAULT;
+ }
+ if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) {
+ dst->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
+ }
+ if (src->refresh_rate != -1) {
+ dst->refresh_rate = -1;
+ }
+ if (src->custom_mode != -1) {
+ dst->custom_mode = -1;
+ }
+ if (src->drm_mode.type != (uint32_t) -1) {
+ dst->drm_mode.type = -1;
+ }
+ if (src->transform != -1) {
+ dst->transform = -1;
+ }
+ if (src->max_render_time != -1) {
+ dst->max_render_time = -1;
+ }
+ if (src->adaptive_sync != -1) {
+ dst->adaptive_sync = -1;
+ }
+ if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
+ dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
+ }
+ if (src->background) {
+ free(dst->background);
+ dst->background = NULL;
+ }
+ if (src->background_option) {
+ free(dst->background_option);
+ dst->background_option = NULL;
+ }
+ if (src->background_fallback) {
+ free(dst->background_fallback);
+ dst->background_fallback = NULL;
+ }
+ if (src->power != -1) {
+ dst->power = -1;
+ }
+}
+
+// merge_output_config sets all fields in dst that were set in src
static void merge_output_config(struct output_config *dst, struct output_config *src) {
if (src->enabled != -1) {
dst->enabled = src->enabled;
@@ -142,96 +207,46 @@ static void merge_output_config(struct output_config *dst, struct output_config
}
}
-static void merge_wildcard_on_all(struct output_config *wildcard) {
- for (int i = 0; i < config->output_configs->length; i++) {
- struct output_config *oc = config->output_configs->items[i];
- if (strcmp(wildcard->name, oc->name) != 0) {
- sway_log(SWAY_DEBUG, "Merging output * config on %s", oc->name);
- merge_output_config(oc, wildcard);
- }
- }
-}
-
-static void merge_id_on_name(struct output_config *oc) {
- struct sway_output *output = all_output_by_name_or_id(oc->name);
- if (output == NULL) {
- return;
+void store_output_config(struct output_config *oc) {
+ bool merged = false;
+ bool wildcard = strcmp(oc->name, "*") == 0;
+ struct sway_output *output = wildcard ? NULL : output_by_name_or_id(oc->name);
+ if (!output && !wildcard) {
+ // There is no config by this name, just add it in
+ goto done;
}
- const char *name = output->wlr_output->name;
char id[128];
output_get_identifier(id, sizeof(id), output);
-
- char *id_on_name = format_str("%s on %s", id, name);
- if (!id_on_name) {
- return;
- }
-
- int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
- if (i >= 0) {
- sway_log(SWAY_DEBUG, "Merging on top of existing id on name config");
- merge_output_config(config->output_configs->items[i], oc);
- } else {
- // If both a name and identifier config, exist generate an id on name
- int ni = list_seq_find(config->output_configs, output_name_cmp, name);
- int ii = list_seq_find(config->output_configs, output_name_cmp, id);
- if ((ni >= 0 && ii >= 0) || (ni >= 0 && strcmp(oc->name, id) == 0)
- || (ii >= 0 && strcmp(oc->name, name) == 0)) {
- struct output_config *ion_oc = new_output_config(id_on_name);
- if (ni >= 0) {
- merge_output_config(ion_oc, config->output_configs->items[ni]);
- }
- if (ii >= 0) {
- merge_output_config(ion_oc, config->output_configs->items[ii]);
- }
- merge_output_config(ion_oc, oc);
- list_add(config->output_configs, ion_oc);
- sway_log(SWAY_DEBUG, "Generated id on name output config \"%s\""
- " (enabled: %d) (%dx%d@%fHz position %d,%d scale %f "
- "transform %d) (bg %s %s) (power %d) (max render time: %d)",
- ion_oc->name, ion_oc->enabled, ion_oc->width, ion_oc->height,
- ion_oc->refresh_rate, ion_oc->x, ion_oc->y, ion_oc->scale,
- ion_oc->transform, ion_oc->background,
- ion_oc->background_option, ion_oc->power,
- ion_oc->max_render_time);
+ for (int i = 0; i < config->output_configs->length; i++) {
+ struct output_config *old = config->output_configs->items[i];
+
+ // 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;
}
- }
- free(id_on_name);
-}
-struct output_config *store_output_config(struct output_config *oc) {
- bool wildcard = strcmp(oc->name, "*") == 0;
- if (wildcard) {
- merge_wildcard_on_all(oc);
- } else {
- merge_id_on_name(oc);
- }
+ // 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;
+ }
- int i = list_seq_find(config->output_configs, output_name_cmp, oc->name);
- if (i >= 0) {
- sway_log(SWAY_DEBUG, "Merging on top of existing output config");
- struct output_config *current = config->output_configs->items[i];
- merge_output_config(current, oc);
- free_output_config(oc);
- oc = current;
- } else if (!wildcard) {
- sway_log(SWAY_DEBUG, "Adding non-wildcard output config");
- i = list_seq_find(config->output_configs, output_name_cmp, "*");
- if (i >= 0) {
- sway_log(SWAY_DEBUG, "Merging on top of output * config");
- struct output_config *current = new_output_config(oc->name);
- merge_output_config(current, config->output_configs->items[i]);
- merge_output_config(current, oc);
- free_output_config(oc);
- oc = current;
+ // If the new config matches an output's name, and the old config
+ // matches on that output's identifier, supersede it.
+ if (strcmp(old->name, id) == 0 &&
+ strcmp(oc->name, output->wlr_output->name) == 0) {
+ supersede_output_config(old, oc);
}
- list_add(config->output_configs, oc);
- } else {
- // New wildcard config. Just add it
- sway_log(SWAY_DEBUG, "Adding output * config");
- list_add(config->output_configs, oc);
}
+done:
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) "
"(max render time: %d)",
@@ -240,7 +255,13 @@ struct output_config *store_output_config(struct output_config *oc) {
oc->transform, oc->background, oc->background_option, oc->power,
oc->max_render_time);
- return oc;
+ // 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);
+ }
}
static void set_mode(struct wlr_output *output, struct wlr_output_state *pending,
@@ -587,96 +608,49 @@ static void default_output_config(struct output_config *oc,
oc->max_render_time = 0;
}
-static struct output_config *get_output_config(char *identifier,
- struct sway_output *sway_output) {
+// find_output_config returns a merged output_config containing all stored
+// configuration that applies to the specified output.
+struct output_config *find_output_config(struct sway_output *sway_output) {
const char *name = sway_output->wlr_output->name;
+ struct output_config *oc = NULL;
- struct output_config *oc_id_on_name = NULL;
- struct output_config *oc_name = NULL;
- struct output_config *oc_id = NULL;
-
- char *id_on_name = format_str("%s on %s", identifier, name);
- int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
- if (i >= 0) {
- oc_id_on_name = config->output_configs->items[i];
- } else {
- i = list_seq_find(config->output_configs, output_name_cmp, name);
- if (i >= 0) {
- oc_name = config->output_configs->items[i];
- }
-
- i = list_seq_find(config->output_configs, output_name_cmp, identifier);
- if (i >= 0) {
- oc_id = config->output_configs->items[i];
- }
- }
-
- struct output_config *result = new_output_config("temp");
+ struct output_config *result = new_output_config(name);
if (config->reloading) {
default_output_config(result, sway_output->wlr_output);
}
- if (oc_id_on_name) {
- // Already have an identifier on name config, use that
- free(result->name);
- result->name = strdup(id_on_name);
- merge_output_config(result, oc_id_on_name);
- } else if (oc_name && oc_id) {
- // Generate a config named `<identifier> on <name>` which contains a
- // merged copy of the identifier on name. This will make sure that both
- // identifier and name configs are respected, with identifier getting
- // priority
- struct output_config *temp = new_output_config(id_on_name);
- merge_output_config(temp, oc_name);
- merge_output_config(temp, oc_id);
- list_add(config->output_configs, temp);
-
- free(result->name);
- result->name = strdup(id_on_name);
- merge_output_config(result, temp);
-
- sway_log(SWAY_DEBUG, "Generated output config \"%s\" (enabled: %d)"
- " (%dx%d@%fHz position %d,%d scale %f transform %d) (bg %s %s)"
- " (power %d) (max render time: %d)", result->name, result->enabled,
- result->width, result->height, result->refresh_rate,
- result->x, result->y, result->scale, result->transform,
- result->background, result->background_option, result->power,
- result->max_render_time);
- } else if (oc_name) {
- // No identifier config, just return a copy of the name config
- free(result->name);
- result->name = strdup(name);
- merge_output_config(result, oc_name);
- } else if (oc_id) {
- // No name config, just return a copy of the identifier config
- free(result->name);
- result->name = strdup(identifier);
- merge_output_config(result, oc_id);
- } else {
- i = list_seq_find(config->output_configs, output_name_cmp, "*");
- if (i >= 0) {
- // No name or identifier config, but there is a wildcard config
- free(result->name);
- result->name = strdup("*");
- merge_output_config(result, config->output_configs->items[i]);
- } else if (!config->reloading) {
- // No name, identifier, or wildcard config. Since we are not
- // reloading with defaults, the output config will be empty, so
- // just return NULL
- free_output_config(result);
- result = NULL;
- }
+
+ char id[128];
+ output_get_identifier(id, sizeof(id), sway_output);
+
+ int i;
+ bool match = false;
+ if ((i = list_seq_find(config->output_configs, output_name_cmp, "*")) >= 0) {
+ match = true;
+ oc = config->output_configs->items[i];
+ merge_output_config(result, oc);
+ }
+ if ((i = list_seq_find(config->output_configs, output_name_cmp, name)) >= 0) {
+ match = true;
+ oc = config->output_configs->items[i];
+ merge_output_config(result, oc);
+ }
+ if ((i = list_seq_find(config->output_configs, output_name_cmp, id)) >= 0) {
+ match = true;
+ oc = config->output_configs->items[i];
+ merge_output_config(result, oc);
+ }
+
+ if (!match && !config->reloading) {
+ // No name, identifier, or wildcard config. Since we are not
+ // reloading with defaults, the output config will be empty, so
+ // just return NULL
+ free_output_config(result);
+ return NULL;
}
- free(id_on_name);
return result;
}
-struct output_config *find_output_config(struct sway_output *output) {
- char id[128];
- output_get_identifier(id, sizeof(id), output);
- return get_output_config(id, output);
-}
-
bool apply_output_configs(struct matched_output_config *configs,
size_t configs_len, bool test_only) {
struct wlr_backend_output_state *states = calloc(configs_len, sizeof(*states));