aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFurkan Sahin <furkan-dev@proton.me>2024-10-28 11:47:10 +0100
committerFurkan Sahin <furkan-dev@proton.me>2024-10-28 11:47:10 +0100
commitdc8bdc5be44959cb62cf274987b7f75dc0af4985 (patch)
treed8ac3d821acc6d741682da778cb3b9714f2579bc
parent9f92bbca45dda7e0ac8d960ae13db3b10c01260f (diff)
desktop/output: Store output config on request_state
An output backend might request any change to an output state at any time, although currently only this is currently only used for changing window size on the wayland and x11 backend. Applying the configuration directly means that the current output state becomes inconsistent with the configured state, which can cause the new state to be reverted later if apply_stored_output_configs is called. Before 3a85bd68bc15. the output geometry would be updated by arrange_outputs, but this is only done by the modeset logic now, resulting in the stored geometry never being updated on wayland backend window resize. This was not discovered as the stored geometry is not used particularly often. Solve both by storing a new output configuration and relying on the modeset logic to apply a new state. Fixes: 3a85bd68bc15 ("tree/arrange: Remove redundant output geometry update")
-rw-r--r--sway/desktop/output.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 18a04c09..394c545d 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -457,19 +457,47 @@ static void handle_request_state(struct wl_listener *listener, void *data) {
struct sway_output *output =
wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data;
+ const struct wlr_output_state *state = event->state;
- uint32_t committed = event->state->committed;
- wlr_output_commit_state(output->wlr_output, event->state);
+ // Store the requested changes so that the active configuration is
+ // consistent with the current state, and to avoid duplicate logic to apply
+ // the changes.
+ struct output_config *oc = new_output_config(output->wlr_output->name);
+ if (!oc) {
+ sway_log(SWAY_ERROR, "Allocation failed");
+ return;
+ }
- if (committed & (
- WLR_OUTPUT_STATE_MODE |
- WLR_OUTPUT_STATE_TRANSFORM |
- WLR_OUTPUT_STATE_SCALE)) {
- arrange_layers(output);
- arrange_output(output);
- transaction_commit_dirty();
+ int committed = state->committed;
+ if (committed & WLR_OUTPUT_STATE_MODE) {
+ if (state->mode != NULL) {
+ oc->width = state->mode->width;
+ oc->height = state->mode->height;
+ oc->refresh_rate = state->mode->refresh / 1000.f;
+ } else {
+ oc->width = state->custom_mode.width;
+ oc->height = state->custom_mode.height;
+ oc->refresh_rate = state->custom_mode.refresh / 1000.f;
+ }
+ committed &= ~WLR_OUTPUT_STATE_MODE;
+ }
+ if (committed & WLR_OUTPUT_STATE_SCALE) {
+ oc->scale = state->scale;
+ committed &= ~WLR_OUTPUT_STATE_SCALE;
+ }
+ if (committed & WLR_OUTPUT_STATE_TRANSFORM) {
+ oc->transform = state->transform;
+ committed &= ~WLR_OUTPUT_STATE_TRANSFORM;
+ }
+
+ // We do not expect or support any other changes here
+ assert(committed == 0);
+ store_output_config(oc);
+ apply_stored_output_configs();
- update_output_manager_config(output->server);
+ if (server.delayed_modeset != NULL) {
+ wl_event_source_remove(server.delayed_modeset);
+ server.delayed_modeset = NULL;
}
}