diff options
| author | srdusr <[email protected]> | 2025-03-03 01:47:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-03-03 01:47:00 +0200 |
| commit | f83082a3b9b75e6f1bc4187850bea1b7408cffca (patch) | |
| tree | 4135aaa04f4aeea60a597062883d0bcf9c7f2867 /crates/wayland/src/udev/session.rs | |
| parent | d303c276e289c9c7146cf74ccad2743246922248 (diff) | |
| download | srdwm-f83082a3b9b75e6f1bc4187850bea1b7408cffca.tar.gz srdwm-f83082a3b9b75e6f1bc4187850bea1b7408cffca.zip | |
Fix VT-switch DPMS blank-screen and CSD corner-crop staircase bugs
VT-switch resume: reasserting the CRTC's mode-setting state was never
enough on its own - display power (DPMS) is separate KMS state, and
nothing here ever touched it after a real switch-away-and-back. Page
flips kept succeeding with zero errors logged for the rest of a real
30+ minute session while the panel itself simply stayed dark, which is
what actually explains a user report of the screen and keyboard input
never recovering after one VT switch. Sets DPMS-on unconditionally on
every resume now, the same property zwlr_output_power_v1 already
writes for an explicit client request.
Corner rendering: both backends' side-strip crop (the fix that keeps a
window's flat left/right border strips from poking a solid-coloured
square through the top/bottom strip's own rounded curve) only ever
activated for `w.decorated` windows. An undecorated/CSD window's crop
depends on its *content* actually getting masked to match - the
winit backend never checked that at all, so every CSD window with a
nonzero border_width got the uncropped, "staircase" artifact
unconditionally, confirmed live via a highlighted border colour and
raw pixel sampling. Ported the udev backend's own `border_curve_is_safe`
check (decorated OR content-will-be-masked) into winit, using the
cheap "does this surface have subsurface children" test both content-
masking code paths already gate success on, rather than duplicating
either one's real (comparatively expensive) rendering work just to
probe it.
Full workspace build + clippy -D warnings + test suite (378 tests) green.
Diffstat (limited to 'crates/wayland/src/udev/session.rs')
| -rw-r--r-- | crates/wayland/src/udev/session.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/crates/wayland/src/udev/session.rs b/crates/wayland/src/udev/session.rs index e39c578..a6b7349 100644 --- a/crates/wayland/src/udev/session.rs +++ b/crates/wayland/src/udev/session.rs @@ -102,6 +102,39 @@ pub(crate) fn register_session_notifier(handle: &LoopHandle<'static, CompState>, if let Err(e) = card.set_crtc(head.crtc, Some(fb), (0, 0), &[head.connector], Some(head.mode)) { log::warn!("udev: failed to reassert crtc on resume: {e}"); } + // A real VT-switch-back can leave the panel itself + // powered down (DPMS off/standby) even once the CRTC + // above is genuinely re-driving it - mode-setting + // and display power are two separate pieces of KMS + // state, and only the former was ever touched here. + // Confirmed live: page flips kept succeeding with no + // error logged anywhere (this backend's own + // `copy_and_flip` never saw a failure) for the rest + // of a 30+ minute session after a real switch-away- + // and-back, and neither the screen nor keyboard + // input ever recovered on their own - every frame + // was genuinely being composited and flipped to a + // CRTC the panel simply wasn't lit to show. Setting + // "DPMS" straight to on here, unconditionally, is + // the same property `set_output_power` already + // writes for `zwlr_output_power_v1` - this is just + // that same write happening automatically on every + // resume instead of only when a client explicitly + // asks, since nothing else in this codebase ever + // calls it after a VT switch. A no-op on hardware + // that never needed it (the property is simply + // already `on`, or genuinely absent on some virtual/ + // headless outputs - `find` below just yields + // nothing and this silently continues to the next + // head either way). + const DRM_MODE_DPMS_ON: u64 = 0; + if let Ok(props) = card.get_properties(head.connector) { + if let Some(dpms_prop) = props.as_props_and_values().0.iter().copied().find(|&h| card.get_property(h).is_ok_and(|info| info.name().to_str() == Ok("DPMS"))) { + if let Err(e) = card.set_property(head.connector, dpms_prop, DRM_MODE_DPMS_ON) { + log::warn!("udev: failed to reassert DPMS-on for output {} on resume: {e}", head.output.name()); + } + } + } // Force a full repaint: contents are undefined after // the VT switch (another VT's session may have // scanned out something else entirely in between). |