Skip to content

perf(widgets): scope caption and frame listeners to their window - #600

Open
palmoni5 wants to merge 1 commit into
leanflutter:mainfrom
palmoni5:upstream/scoped-window-listeners
Open

palmoni5 wants to merge 1 commit into
leanflutter:mainfrom
palmoni5:upstream/scoped-window-listeners

Conversation

@palmoni5

@palmoni5 palmoni5 commented Nov 10, 2026 •

Copy link
Copy Markdown

Problem

WindowCaption and VirtualWindowFrame register a process-wide nativeapi.WindowManager listener even when they are given a window. In a multi-window app every resize, focus or maximize event of any window therefore makes every caption and frame query its own window over FFI. In addition, VirtualWindowFrame calls setState from initState when the window starts maximized, unfocused or full screen.

Change

  • Given a window, both widgets listen to that window only (Window.addListener).
  • The subscription moves when the widget is given another window and is released on dispose; rebuilding with the same window keeps it.
  • Without a window, both widgets keep the current behavior: a manager-wide listener that resolves the current window on each event, so a window that is not current yet at startup is still picked up later.
  • VirtualWindowFrame assigns its initial state directly in initState instead of calling setState.

Tests

Extended test/window_caption_test.dart with a fake window that records its listeners: a caption and a frame react only to their own window, the subscription moves to a replacement window and is released on dispose, no re-subscription on rebuild with the same window, a caption without a window builds and disposes cleanly, and a frame whose window starts maximized raises no exception. The new tests fail against the previous widget code.

dart format --set-exit-if-changed ., flutter analyze (package and example) and flutter test (package and example) pass locally (Flutter 3.47.7, Windows), and the full CI workflow passes on the identical commit in my fork.

Related

Part of a set of independent PRs, each based on main and mergeable on its own: widgets #598, #599, #600 (this), #601; legacy bridge #602, #603, #604, #605, #606.

Touches window_caption.dart like #601 (close fallback); the two merge cleanly in either order.

WindowCaption and VirtualWindowFrame registered a process-wide
WindowManager listener even when given a window, so in a multi-window
app every resize, focus or maximize event of any window made every
caption and frame query its own window over FFI.

Given a window, both widgets now listen to that window only. The
subscription moves when the widget gets another window and is released
on dispose. Without a window they keep the manager-wide listener that
resolves the current window on each event.

VirtualWindowFrame no longer calls setState from initState when the
window starts maximized, unfocused or full screen; the initial state is
assigned directly.
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