Skip to content

fix: autorotate-iio: fix D-Bus events not processed when display is idle#337

Merged
soreau merged 2 commits intoWayfireWM:masterfrom
borisi1:fix/autorotate-iio-idle-display
Apr 23, 2026
Merged

fix: autorotate-iio: fix D-Bus events not processed when display is idle#337
soreau merged 2 commits intoWayfireWM:masterfrom
borisi1:fix/autorotate-iio-idle-display

Conversation

@borisi1
Copy link
Copy Markdown
Contributor

@borisi1 borisi1 commented Apr 22, 2026

Fixes #336.

Problem

The plugin drove the GLib main context from an OUTPUT_EFFECT_PRE hook that only fires while the compositor renders frames. When the display is idle, no frames render, GLib never runs, and iio-sensor-proxy property-change signals queue up unprocessed — rotation silently stops working.

Changes

Main fix: Replace on_frame / OUTPUT_EFFECT_PRE with a wl_event_loop_add_timer(50ms) on the Wayland event loop (wl_display_get_event_loop(wf::get_core().display)). This pumps the GLib main context at a steady rate regardless of display activity.

Null-guard on Glib::Variant: get_cached_property() may leave the variant uninitialized if the D-Bus proxy cache is not yet populated. Calling .get() on it crashes the compositor.

Call update_orientation() after ClaimAccelerometer: Without this the plugin only reacts to orientation changes — it never reads the current orientation at startup.

Asymmetric debounce state machine: Some accelerometers oscillate between the target orientation and "normal" during a physical rotation, resetting the debounce timer on each reading and delaying rotation by 15–20 seconds. The fix:

  • 500ms to commit a non-normal (rotated) orientation
  • 1200ms to return to normal (longer, to survive mid-rotation noise)
  • Rotation timer is not reset on subsequent non-normal readings — delay is measured from the first reading, not the last
  • Return-to-normal timer is cancelled and replaced by a rotation timer if a non-normal reading arrives

Testing

Tested on Lenovo Yoga 9 14IRP8 (Intel Iris Xe, eDP-1 @ 3840×2400 scale 2.4), CachyOS, kernel 7.0.0-1-cachyos, wayfire-git r110, wlroots 0.20, iio-sensor-proxy 3.x.

The plugin used an OUTPUT_EFFECT_PRE hook (on_frame) to pump the GLib
main context. This hook only fires while the compositor is actively
rendering frames for that output. When the display is idle — no damaged
windows, no animations — no frames are rendered, so GLib's main context
never runs and property-change signals from iio-sensor-proxy queue up
unprocessed. Rotation stops working until something triggers a redraw
(e.g. an active terminal window causes continuous repaints).

Fix: replace on_frame with a wl_event_loop_add_timer(50ms) wired into
the Wayland event loop via wl_display_get_event_loop(). This pumps the
GLib main context at a steady rate regardless of display activity.

Additional fixes:
- Guard against a null Glib::Variant from get_cached_property() when
  the D-Bus proxy cache is not yet populated; calling .get() on an
  uninitialized Variant crashes the compositor.
- Call update_orientation() immediately after ClaimAccelerometer so the
  initial device orientation is applied without waiting for a change event.
- Add an asymmetric debounce state machine to handle noisy sensors:
  500ms to commit a rotation, 1200ms to return to normal. The longer
  normal timeout prevents the screen from flipping back during the brief
  "normal" readings that occur mid-rotation on some hardware. The
  rotation timer is not reset on subsequent non-normal readings so the
  delay is measured from the first reading, not the last.
@soreau
Copy link
Copy Markdown
Member

soreau commented Apr 22, 2026

@borisi1 Thank you for the detailed issue report and pull request. You can find a diff to fix the code style in the CI output, then we can merge your work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@soreau
Copy link
Copy Markdown
Member

soreau commented Apr 23, 2026

LGTM, Thanks.

@soreau soreau merged commit a65af25 into WayfireWM:master Apr 23, 2026
3 checks passed
@soreau
Copy link
Copy Markdown
Member

soreau commented Apr 23, 2026

In the kernel per https://docs.kernel.org/process/coding-assistants.html the format for AI attributions is as follows:

Format:
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]

Example:
Assisted-by: Claude:claude-3-opus coccinelle sparse

I think it makes sense to use the same convention.

Thanks to @benjamin-otte for pointing this out.

@soreau
Copy link
Copy Markdown
Member

soreau commented Apr 23, 2026

@borisi1 The last comment is only for informational purposes going forward. Feel free to ignore it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

autorotate-iio: rotation stops working when display is idle

2 participants