Skip to content

Commit 51e4bf8

Browse files
committed
Avoid no-op output reconfiguring
When an output command doesn't actually change anything in the output config the processing will still all be done and cause other changes. Notably if you run a command like: output * dpms on even if it does nothing it will still cause all the inputs to be reconfigured and very noticeable amounts of input latency to occur. To fix this save the current output config in the output data and on configure, if the config is the same just return without doing anything else. Fixes swaywm#6280
1 parent 7eab2bf commit 51e4bf8

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

include/sway/config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,10 @@ struct output_config *new_output_config(const char *name);
638638

639639
void merge_output_config(struct output_config *dst, struct output_config *src);
640640

641+
struct output_config *duplicate_output_config(const struct output_config *src);
642+
643+
bool compare_output_config(const struct output_config *dst, const struct output_config *src);
644+
641645
bool apply_output_config(struct output_config *oc, struct sway_output *output);
642646

643647
bool test_output_config(struct output_config *oc, struct sway_output *output);

include/sway/output.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ struct sway_output {
5757
uint32_t refresh_nsec;
5858
int max_render_time; // In milliseconds
5959
struct wl_event_source *repaint_timer;
60+
61+
struct output_config *current_config;
6062
};
6163

6264
struct sway_output *output_create(struct wlr_output *wlr_output);

sway/config/output.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,67 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
119119
}
120120
}
121121

122+
struct output_config *duplicate_output_config(const struct output_config *src) {
123+
struct output_config *oc = calloc(1, sizeof(struct output_config));
124+
if (oc == NULL) {
125+
return NULL;
126+
}
127+
oc->name = strdup(src->name);
128+
if (oc->name == NULL) {
129+
free(oc);
130+
return NULL;
131+
}
132+
oc->enabled = src->enabled;
133+
oc->width = src->width;
134+
oc->height = src->height;
135+
oc->refresh_rate = src->refresh_rate;
136+
oc->custom_mode = src->custom_mode;
137+
oc->x = src->x;
138+
oc->y = src->y;
139+
oc->scale = src->scale;
140+
oc->scale_filter = src->scale_filter;
141+
oc->transform = src->transform;
142+
oc->subpixel = src->subpixel;
143+
oc->max_render_time = src->max_render_time;
144+
oc->adaptive_sync = src->adaptive_sync;
145+
if (src->background) {
146+
oc->background = strdup(src->background);
147+
}
148+
if (src->background_option) {
149+
oc->background_option = strdup(src->background_option);
150+
}
151+
if (src->background_fallback) {
152+
oc->background_fallback = strdup(src->background_fallback);
153+
}
154+
oc->dpms_state = src->dpms_state;
155+
return oc;
156+
}
157+
158+
bool compare_linked_strings(const char *first, const char *second) {
159+
return (first == NULL && second == NULL) ||
160+
(first != NULL && second != NULL && !strcmp(first, second));
161+
}
162+
163+
bool compare_output_config(const struct output_config *dst, const struct output_config *src) {
164+
return dst->enabled == src->enabled &&
165+
dst->width == src->width &&
166+
dst->height == src->height &&
167+
dst->x == src->x &&
168+
dst->y == src->y &&
169+
dst->scale == src->scale &&
170+
dst->scale_filter == src->scale_filter &&
171+
dst->subpixel == src->subpixel &&
172+
dst->refresh_rate == src->refresh_rate &&
173+
dst->custom_mode == src->custom_mode &&
174+
dst->transform == src->transform &&
175+
dst->max_render_time == src->max_render_time &&
176+
dst->adaptive_sync == src->adaptive_sync &&
177+
compare_linked_strings(dst->background, src->background) &&
178+
compare_linked_strings(dst->background_option, src->background_option) &&
179+
compare_linked_strings(dst->background_fallback, src->background_fallback) &&
180+
dst->dpms_state == src->dpms_state;
181+
}
182+
122183
enum output_config_changes {
123184
OUTPUT_CONFIG_ENABLED = 1 << 1,
124185
OUTPUT_CONFIG_WIDTH = 1 << 2,
@@ -389,6 +450,16 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
389450

390451
struct wlr_output *wlr_output = output->wlr_output;
391452

453+
if (output->current_config && compare_output_config(oc, output->current_config)) {
454+
// The output config is unchanged so bail out early
455+
sway_log(SWAY_DEBUG, "Config for output %s is unchanged", wlr_output->name);
456+
return true;
457+
}
458+
if (output->current_config) {
459+
free_output_config(output->current_config);
460+
}
461+
output->current_config = duplicate_output_config(oc);
462+
392463
// Flag to prevent the output mode event handler from calling us
393464
output->enabling = (!oc || oc->enabled);
394465

0 commit comments

Comments
 (0)