From f4fab5a2b06c37df08d2d315bcb44d15af1786a4 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 17 Aug 2026 19:08:47 +0200 Subject: wm: keep windows in place when the console scrolls beneath them The console's batched scroll (gop::shift_up_n) shifts the whole shared shadow, which dragged any composited window pixels up with it. Add a scroll hook so the window manager re-composites every visible window after a console scroll, restoring them at their fixed positions. --- rsnix/src/gop.rs | 19 +++++++++++++++++++ rsnix/src/vt.rs | 9 ++------- rsnix/src/wm.rs | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 7 deletions(-) (limited to 'rsnix/src') diff --git a/rsnix/src/gop.rs b/rsnix/src/gop.rs index deff226..cddad22 100644 --- a/rsnix/src/gop.rs +++ b/rsnix/src/gop.rs @@ -104,6 +104,25 @@ pub fn qr_locked() -> bool { QR_LOCKED.load(Ordering::Relaxed) } +/// Hook invoked after the console scrolls, so the window manager can +/// re-composite GUI windows (which sit above the console layer in the +/// shadow and must not scroll with it). +fn scroll_hook_noop() {} + +static mut SCROLL_HOOK: fn() = scroll_hook_noop; + +pub fn set_scroll_hook(f: fn()) { + unsafe { + SCROLL_HOOK = f; + } +} + +pub(crate) fn call_scroll_hook() { + unsafe { + SCROLL_HOOK(); + } +} + #[inline] fn stall_display() { let n = DISPLAY_STALL.load(Ordering::Relaxed); diff --git a/rsnix/src/vt.rs b/rsnix/src/vt.rs index c5fc5fd..4ef568d 100644 --- a/rsnix/src/vt.rs +++ b/rsnix/src/vt.rs @@ -458,13 +458,7 @@ fn put_byte(b: u8) { } fn param(i: usize, default: usize) -> usize { - unsafe { - if i < NPARAMS { - PARAMS[i] - } else { - default - } - } + unsafe { if i < NPARAMS { PARAMS[i] } else { default } } } /// Place a printable glyph at the cursor and advance (wrapping/scrolling). @@ -694,6 +688,7 @@ pub fn sync_scroll() { PENDING_SCROLLS = 0; LAST_SYNC_TICK = crate::interrupts::TICKS.load(core::sync::atomic::Ordering::Relaxed); flush(); + gop::call_scroll_hook(); } } diff --git a/rsnix/src/wm.rs b/rsnix/src/wm.rs index be74f9a..1326696 100644 --- a/rsnix/src/wm.rs +++ b/rsnix/src/wm.rs @@ -90,6 +90,8 @@ pub fn init() { CASCADE_Y = 0; } FOCUSED.store(CONSOLE, Ordering::Relaxed); + // When the console scrolls, re-composite windows so they stay put. + gop::set_scroll_hook(redraw_windows); } /// The focused window, or `None` if the console has focus. @@ -661,6 +663,20 @@ pub fn spawn_input_pump() -> Option { crate::sched::spawn(pump_main, "wm-input") } +/// Re-composite every visible window. Called after the console scrolls so +/// windows stay in place while the text layer beneath them shifts. +pub fn redraw_windows() { + unsafe { + for i in 0..ZLEN { + let id = ZORDER[i]; + let w = WINDOWS[id]; + if w.used && w.state == WinState::Visible { + composite_rect(w.x, w.y, w.w, w.h + TITLE_BAR_H); + } + } + } +} + fn pump_main() { loop { if focused().is_some() { -- cgit v1.2.3