Skip to content

fix(g6): a window created hidden stops rendering once its page loads - #991

Merged
runyourempire merged 1 commit into
mainfrom
fix/g6-initial-hidden
Oct 18, 2026
Merged

runyourempire merged 1 commit into
mainfrom
fix/g6-initial-hidden

Conversation

@runyourempire

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #967 (G6 idle). A window created hidden never receives WM_SHOWWINDOW or WM_SIZE until it is first shown. So webview_visibility (which left the initial state alone and only followed messages) never touched its WebView2 controller, which kept wry's creation-time IsVisible = true.

Found live on the operator app (main 4d257b9): the never-shown brief window read visibilityState "visible", with requestAnimationFrame at ~240 fps (595–601 frames in 2.5 s), while hidden.

Fix

webview_visibility now also listens for Tauri's page-load event:

  • Once a webview's page has finished loading, it applies the host window's real state: IsVisible = IsWindowVisible && !IsIconic.
  • This goes through the same per-window tracker (found with GetWindowSubclass), so the message-driven transitions stay in step.
  • Nothing is set before the page has loaded, so loading is never throttled.
  • It is one rule for every window, with no per-window ready signal: the pre-warmed toast and brief windows, and the main window before first light.
  • Unit test: a_page_that_loads_in_a_hidden_window_stops_rendering. It covers loading in a hidden window, in a minimised window, and in a visible window (a reload of the shown main window).

Live check

Isolated debug instance: identifier com.4da.app.g6rel, ports 4448/4449, FOURDA_DATA_DIR on a read-only VACUUM INTO copy of the live DB, LLM provider none.

  • After startup, nothing shown (the log has no toast or brief shown):
    • brief window: visibilityState "hidden", 0 rAF frames in 2.5 s;
    • toast window: hidden, 0;
    • main window (shown): visible, 357.
  • First toast (alert): displayed correctly (screenshot checked), visible with 600 rAF while on screen. The card was dark on screen within ~45 ms of the command returning.
  • Second toast right after (critical): the script hid the first one 6.4 s after it showed. Every captured frame after the second show was the new card fading in; no frame of the previous card. The S2 behaviour from fix(g6): hidden windows stop rendering; judge leaves VRAM between cycles; DB budget #967 is preserved.
  • First brief: displayed correctly (screenshot checked), visible with 601 rAF. After its close button: native hidden, hidden, 0 rAF.

Side finding (not the same mechanism; not fixed here)

In two release runs, the toast window's script never reported ready at startup. The app then destroyed and recreated the window, and the first toast did not show. This is not the IsVisible problem; it looks like a lost notification-ready event.

  • In app_setup.rs the toast window is created (line 1688) before the notification-ready listener is registered (line 1698).
  • In between, the brief window is created (line 1693). WebView2 creation pumps messages, so the toast page can load and emit notification-ready before anyone listens.
  • The brief window, whose listener is registered right after its own creation, never showed the problem.
  • Suggested fix, in app_setup.rs, which another lane owns: register the notification-ready and briefing-ready listeners before creating the windows.
  • This is a hypothesis from the code order and logs; I did not reproduce it.

Checks

cargo fmt clean; webview_visibility tests pass; the pre-push hooks pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7

A window created hidden (the pre-warmed toast and brief windows, the main
window before first light) gets no WM_SHOWWINDOW / WM_SIZE until it is
first shown, so its WebView2 controller kept wry's creation-time
IsVisible = true: the never-shown brief window read visibilityState
"visible" with requestAnimationFrame at ~240 fps (operator app,
2026-10-18). On Tauri's page-load Finished event the plugin now applies
the host window's real state (visible && !minimised) through the same
per-window tracker; nothing is set before the page has loaded.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hjX3pEMmC7CHfG41PiPj7
@runyourempire
runyourempire added this pull request to the merge queue Oct 18, 2026
Merged via the queue into main with commit b6468e3 Oct 18, 2026
24 checks passed
@runyourempire
runyourempire deleted the fix/g6-initial-hidden branch October 18, 2026 12:42
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.

1 participant