From 9092e0f7558ea78b3db84eafe532fd5521095671 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 5 Sep 2024 18:24:01 +0200 Subject: [PATCH] desktop/output: Use temporary configs for output_manager The current logic created a new output_config for each output according to config_head posted by an output managing client. These configurations would then be attempted applied, and if successful, be stored as active configuration. However, some of the state tested depend on fields not set by the output manager. If 'output * power off' is in effect, and an output manager enables a config_head, then the expected result is that power off is respected and outputs remain off, but becuase only the config_head configuration is considered, the output is powered on. The configuration when stored is then no longer consistent with the current state. Instead of trying to handle merging configurations and appropriate precedence within the output manager, simply store the configuration temporarily and apply all output configurations. If the result is successful, we remove the temporary configuration and add it permanently. --- sway/desktop/output.c | 60 ++++++++++++------------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0b54cb4dd..00d84268b 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -544,9 +544,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { } static struct output_config *output_config_for_config_head( - struct wlr_output_configuration_head_v1 *config_head, - struct sway_output *output) { - struct output_config *oc = new_output_config(output->wlr_output->name); + struct wlr_output_configuration_head_v1 *config_head) { + struct output_config *oc = new_output_config(config_head->state.output->name); oc->enabled = config_head->state.enabled; if (!oc->enabled) { return oc; @@ -573,56 +572,31 @@ static struct output_config *output_config_for_config_head( static void output_manager_apply(struct sway_server *server, struct wlr_output_configuration_v1 *config, bool test_only) { - size_t configs_len = wl_list_length(&root->all_outputs); - struct matched_output_config *configs = calloc(configs_len, sizeof(*configs)); + size_t configs_len = wl_list_length(&config->heads); + struct output_config **configs = calloc(configs_len, sizeof(*configs)); if (!configs) { return; } int config_idx = 0; - struct sway_output *sway_output; - wl_list_for_each(sway_output, &root->all_outputs, link) { - if (sway_output == root->fallback_output) { - configs_len--; - continue; - } - - struct matched_output_config *cfg = &configs[config_idx++]; - cfg->output = sway_output; - - struct wlr_output_configuration_head_v1 *config_head; - wl_list_for_each(config_head, &config->heads, link) { - if (config_head->state.output == sway_output->wlr_output) { - cfg->config = output_config_for_config_head(config_head, sway_output); - break; - } - } - if (!cfg->config) { - cfg->config = find_output_config(sway_output); - } + struct wlr_output_configuration_head_v1 *config_head; + wl_list_for_each(config_head, &config->heads, link) { + // Generate the configuration and store it as a temporary + // config. We keep a record of it so we can remove it later. + struct output_config *oc = output_config_for_config_head(config_head); + store_temp_output_config(oc); + configs[config_idx++] = oc; } + configs_len = config_idx; - sort_output_configs_by_priority(configs, configs_len); - bool ok = apply_output_configs(configs, configs_len, test_only, false); + bool ok = apply_all_output_configs(test_only, false); for (size_t idx = 0; idx < configs_len; idx++) { - struct matched_output_config *cfg = &configs[idx]; - - // Only store new configs for successful non-test commits. Old configs, - // test-only and failed commits just get freed. - bool store_config = false; + struct output_config *cfg = configs[idx]; + remove_temp_output_config(cfg); if (!test_only && ok) { - struct wlr_output_configuration_head_v1 *config_head; - wl_list_for_each(config_head, &config->heads, link) { - if (config_head->state.output == cfg->output->wlr_output) { - store_config = true; - break; - } - } - } - if (store_config) { - store_output_config(cfg->config); + store_output_config(cfg); } else { - free_output_config(cfg->config); + free_output_config(cfg); } } free(configs);