diff --git a/include/sway/config.h b/include/sway/config.h index 5ad240d34..7dd47500a 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -636,6 +636,10 @@ struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); +struct output_config *duplicate_output_config(const struct output_config *src); + +bool compare_output_config(const struct output_config *dst, const struct output_config *src); + bool apply_output_config(struct output_config *oc, struct sway_output *output); bool test_output_config(struct output_config *oc, struct sway_output *output); diff --git a/include/sway/output.h b/include/sway/output.h index f27f6344a..b2d93a71f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -57,6 +57,8 @@ struct sway_output { uint32_t refresh_nsec; int max_render_time; // In milliseconds struct wl_event_source *repaint_timer; + + struct output_config *current_config; }; struct sway_output *output_create(struct wlr_output *wlr_output); diff --git a/sway/config/output.c b/sway/config/output.c index b59cabd4e..10f46844f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -14,6 +14,7 @@ #include "sway/tree/root.h" #include "log.h" #include "util.h" +#include "stringop.h" int output_name_cmp(const void *item, const void *data) { const struct output_config *output = item; @@ -125,6 +126,63 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { } } +struct output_config *duplicate_output_config(const struct output_config *src) { + struct output_config *oc = calloc(1, sizeof(struct output_config)); + if (oc == NULL) { + return NULL; + } + oc->name = strdup(src->name); + if (oc->name == NULL) { + free(oc); + return NULL; + } + oc->enabled = src->enabled; + oc->width = src->width; + oc->height = src->height; + oc->refresh_rate = src->refresh_rate; + oc->custom_mode = src->custom_mode; + oc->x = src->x; + oc->y = src->y; + oc->scale = src->scale; + oc->scale_filter = src->scale_filter; + oc->transform = src->transform; + oc->subpixel = src->subpixel; + oc->max_render_time = src->max_render_time; + oc->adaptive_sync = src->adaptive_sync; + if (src->background) { + oc->background = strdup(src->background); + } + if (src->background_option) { + oc->background_option = strdup(src->background_option); + } + if (src->background_fallback) { + oc->background_fallback = strdup(src->background_fallback); + } + oc->dpms_state = src->dpms_state; + return oc; +} + +bool compare_output_config(const struct output_config *dst, const struct output_config *src) { + return dst && src && + dst->enabled == src->enabled && + dst->width == src->width && + dst->height == src->height && + dst->x == src->x && + dst->y == src->y && + dst->scale == src->scale && + dst->scale_filter == src->scale_filter && + dst->subpixel == src->subpixel && + dst->refresh_rate == src->refresh_rate && + dst->custom_mode == src->custom_mode && + dst->transform == src->transform && + dst->max_render_time == src->max_render_time && + dst->adaptive_sync == src->adaptive_sync && + !lenient_strcmp(dst->background, src->background) && + !lenient_strcmp(dst->background_option, src->background_option) && + !lenient_strcmp(dst->background_fallback, src->background_fallback) && + dst->dpms_state == src->dpms_state; +} + 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]; @@ -397,6 +455,16 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { struct wlr_output *wlr_output = output->wlr_output; + if (oc && output->current_config && compare_output_config(oc, output->current_config)) { + // The output config is unchanged so bail out early + sway_log(SWAY_DEBUG, "Config for output %s is unchanged", wlr_output->name); + return true; + } + if (output->current_config) { + free_output_config(output->current_config); + } + output->current_config = duplicate_output_config(oc); + // Flag to prevent the output mode event handler from calling us output->enabling = (!oc || oc->enabled);