Skip to content

Use the WindowRegistry in the multiple_windows example app#184579

Merged
mattkae merged 11 commits into
flutter:masterfrom
canonical:use-window-registry
Apr 7, 2026
Merged

Use the WindowRegistry in the multiple_windows example app#184579
mattkae merged 11 commits into
flutter:masterfrom
canonical:use-window-registry

Conversation

@mattkae

@mattkae mattkae commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

What's new?

  • This pull request updates the multiple_windows example application use the new WindowRegistry from the _window.dart API to hold the collection of windows instead of the KeyedWindowManager that we had implemented prior.
  • It also adds WindowRegistry.of for a non-nullable access to the window registry.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. d: examples Sample code and demos labels Apr 3, 2026
@mattkae mattkae requested review from justinmc and loic-sharma April 3, 2026 15:49
@mattkae mattkae added the CICD Run CI/CD label Apr 3, 2026
@mattkae mattkae marked this pull request as ready for review April 3, 2026 15:49

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the custom KeyedWindowManager with the framework's WindowRegistry in the multiple windows example, refactoring several widgets to use WindowRegistry.of and WindowEntry for window management. Feedback highlights a bug in the WindowRegistry.of debug check which should verify _WindowRegistryScope instead of WindowScope. Additionally, improvements are suggested for the window toggle logic in PopupButton and TooltipButton to prevent potential null pointer exceptions during asynchronous destruction and to fix a missing method call to dispose.

Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread examples/multiple_windows/lib/app/popup_button.dart
Comment thread examples/multiple_windows/lib/app/tooltip_button.dart

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice clean up! Looks good overall, but please take a look at Gemini's feedback

@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 3, 2026
@mattkae mattkae added the CICD Run CI/CD label Apr 3, 2026
@mattkae mattkae requested a review from loic-sharma April 3, 2026 18:06
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
loic-sharma
loic-sharma previously approved these changes Apr 3, 2026

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM modulo the potentially incorrect doc. Thanks for cleaning this up!

@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 3, 2026
@mattkae mattkae added the CICD Run CI/CD label Apr 3, 2026
@mattkae mattkae requested a review from loic-sharma April 3, 2026 18:37
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
///
/// {@macro flutter.widgets.windowing.experimental}
@internal
static WindowRegistry of(BuildContext context) {

@loic-sharma loic-sharma Apr 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, I'm leaning towards making this throw if isWindowingEnabled is false. Currently, WindowManager doesn't add a _WindowRegistryScope if isWindowingEnabled is false:

class _WindowManagerState extends State<WindowManager> {
final WindowRegistry _registry = WindowRegistry();
@override
Widget build(BuildContext context) {
if (!isWindowingEnabled) {
return widget.child;
}

Thus, WindowRegistry.of will always throw if windowing is off. Some potential options:

  • Option 1: Throw here if isWindowingEnabled is false. This behavior would be consistent with other windowing APIs.
  • Option 2: Update WindowManager to add an empty _WindowRegistryScope if isWindowingEnabled is false. I don't love this option - it feels like WindowRegistry will need a partial working state if windowing is off.
  • Option 3: Update the ErrorHint below to explain that another reason this throws is if you have a WindowManager ancestor but windowing is off. We'd need to remember to clean this up in the future when we remove the windowing feature, though.

What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bad part of always throwing whenever one attempts to access the WindowRegistry is that its unavailability is currently the common case. For example, the MaterialApp now uses the presence of a WindowRegistry to decide whether or not to display a true dialog/tooltip. A common case (right now) would be for windowing to be turned off by the feature flag. This would lead the build() method to constantly throw, which isn't great.

In my opinion, this should behave similar to how other .of(...) methods behave. If the feature is unavailable for whatever reason, it will be null. Then the user does not have to worry about handling separate exceptional cases.

justinmc
justinmc previously approved these changes Apr 3, 2026

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits 👍 . Thanks for coming back and cleaning this up now that we have WindowRegistry. I think the example is now a lot easier for devs to learn from.

final KeyedWindowManager windowManager = KeyedWindowManagerAccessor.of(
context,
);
final WindowRegistry windowRegistry = WindowRegistry.of(context);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to look this up inside of the onPressed callback? Not sure if that's an improvement, just thinking about it.


final RegularWindowController mainWindow;

DataRow _buildRow(BaseWindowController controller, BuildContext context) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could this be a widget instead of a function? I try to lean that way when I see functions that return widgets, but I'm not sure whether it works out here or not.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

///
/// {@macro flutter.widgets.windowing.experimental}
@internal
static WindowRegistry of(BuildContext context) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the point of this versus .maybeOf(context)! just to provide a better error message in debug mode?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That and it is a common pattern throughout the code. There are certain contexts where lack of access to an InheritedWidget is nonsensical, so this declares a hard dependency on the presence of the WindowRegistry

@internal
static WindowRegistry of(BuildContext context) {
final WindowRegistry? registry = maybeOf(context);
assert(() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if the assert is useful here or not. In release mode, there is still guaranteed to be an error thrown (at registry!). It will just be a less useful error than the one in debug mode.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally appreciate the helpful error message. Plus this matches existing of(...) calls, so I'm tempted to keep it as-is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also lean to keeping this as-is as the error bubbles up that you need to wrap your app with a WindowManager widget to get a WindowRegistry inherited widget. I think this error will be particularly helpful for folks that try to use windowing APIs with their own custom design systems that aren't based on Material.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant maybe we should remove the assert but keep its body, so we always throw the useful FlutterError instead of only throwing it in debug mode. Not a big deal though, I know this is about to merge :)

Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 6, 2026
@mattkae mattkae requested a review from justinmc April 6, 2026 12:35
@mattkae mattkae added the CICD Run CI/CD label Apr 6, 2026

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-LGTM!

@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 6, 2026
@mattkae mattkae added the CICD Run CI/CD label Apr 6, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 7, 2026
@mattkae mattkae added the CICD Run CI/CD label Apr 7, 2026
@mattkae mattkae enabled auto-merge April 7, 2026 15:20
@mattkae mattkae added this pull request to the merge queue Apr 7, 2026
@flutter-dashboard

Copy link
Copy Markdown

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #184579 at sha 6ff2a76

@flutter-dashboard flutter-dashboard Bot added the will affect goldens Changes to golden files label Apr 7, 2026
Merged via the queue into flutter:master with commit 92d81d3 Apr 7, 2026
78 of 80 checks passed
@mattkae mattkae deleted the use-window-registry branch April 7, 2026 16:23
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Apr 7, 2026
flutter/flutter@9cd60b5...a0924c7

2026-04-07 [email protected] Reland "[data_assets] Cleanup tests" (flutter/flutter#184714)
2026-04-07 [email protected] Use the WindowRegistry in the multiple_windows example app (flutter/flutter#184579)
2026-04-07 [email protected] Introduce command to build a swift package for SwiftPM add to app integration (flutter/flutter#184660)
2026-04-07 [email protected] Have `flutter create` create a pubspec.lock to ensure pinned versions are being used. (flutter/flutter#175352)
2026-04-07 [email protected] [widgets/raw_menu_anchor.dart] Always call onClose and onCloseRequested on descendants before parent. (flutter/flutter#182357)
2026-04-07 [email protected] `WindowsPlugin` should not crash when ffiPlugin enabled (flutter/flutter#184695)
2026-04-06 [email protected] Use full goto.google.com hostname for go/ links (flutter/flutter#184679)
2026-04-06 [email protected] Apply rect clipping to surface views (flutter/flutter#184471)
2026-04-06 [email protected] [A11y] Allow percentage strings like "50%" as `SemanticsValue` for `ProgressIndicator` (flutter/flutter#183670)
2026-04-06 [email protected] Fix invisible accessibility element before scroll view (flutter/flutter#184155)
2026-04-06 [email protected] Roll Skia from 163dfdf500c7 to e264d870a380 (2 revisions) (flutter/flutter#184674)
2026-04-06 [email protected] Keep last character obscured when toggling obscureText (flutter/flutter#183488)
2026-04-06 [email protected] Parse scheme file with XML parser for SwiftPM migrator (flutter/flutter#184525)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
mbcorona pushed a commit to mbcorona/flutter that referenced this pull request Apr 15, 2026
…84579)

## What's new?
- This pull request updates the multiple_windows example application use
the new `WindowRegistry` from the `_window.dart` API to hold the
collection of windows instead of the `KeyedWindowManager` that we had
implemented prior.
- It also adds `WindowRegistry.of` for a non-nullable access to the
window registry.

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD d: examples Sample code and demos framework flutter/packages/flutter repository. See also f: labels. will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants