Skip to content

fix(tao): repaint satellites Win32 re-shows on their owner's restore - #895

Merged
kdroidFilter merged 1 commit into
nucleus-3.0from
fix/satellite-restore-white
Nov 1, 2026
Merged

kdroidFilter merged 1 commit into
nucleus-3.0from
fix/satellite-restore-white

Conversation

@kdroidFilter

Copy link
Copy Markdown
Collaborator

Summary

On Windows, if a satellite is torn off and the main window is then minimized and restored, the satellite comes back all white until the pointer passes over it.

  • Cause: minimizing a window hides the windows it owns (satellites, dialogs), and restoring it shows them again via WM_SHOWWINDOW / SW_PARENTOPENING, without TaoWindow.show() ever running. As a result, showHook never arms forcePresentOnce. DWM has dropped the hidden window's frame and the scene is clean, so no present happens.
  • Fix: the deco WndProc arms a flag on SW_PARENTOPENING. Once the window is really mapped (WM_WINDOWPOSCHANGED + SWP_SHOWWINDOW), it calls NativeTaoWindowsDecoBridge.onShownWithOwner, and the scene host then forces its next present. Calling back from WM_SHOWWINDOW itself is too early: the window is still hidden and DWM drops that present too (measured: still white).
  • onShownWithOwner is declared in the reachability metadata, so the upcall survives native image.
  • This covers every owned window (dialogs of a minimized window included), not just satellites.

Test plan

  • New headful case windows a satellite is painted after its parent is restored (SatelliteRestorePaintHeadfulCases): 3 minimize/restore rounds, reading the satellite back through PrintWindow (DWM's copy) without moving the pointer
    • without the fix: #FFFFFFFF, 0% of the content visible
    • with the fix: 100%, on all 3 rounds
  • Neighbouring satellite headful cases (anchor/follow, hide while maximized) still pass
  • ktlintCheck + detekt clean
  • Manual check in the Lab: tear off a satellite, minimize, restore

Minimizing a window hides the windows it owns (satellites, dialogs) and
restoring it shows them again through WM_SHOWWINDOW/SW_PARENTOPENING,
without TaoWindow.show ever running. DWM has dropped the hidden window's
frame and the scene is clean, so nothing was presented: the satellite
stayed white until the pointer passed over it.

The deco WndProc arms on SW_PARENTOPENING and, once the window is really
mapped (WM_WINDOWPOSCHANGED with SWP_SHOWWINDOW), calls back into the
scene host, which forces its next present. Calling back from
WM_SHOWWINDOW itself is too early: the window is still hidden and DWM
drops that present too.
@kdroidFilter
kdroidFilter merged commit 070f4ec into nucleus-3.0 Nov 1, 2026
13 checks passed
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