Windowing implementation of showDialog that uses a native desktop window to display the content #181861
Conversation
showDialog that relies on native desktop dialog windowsshowDialog that uses a native desktop to display the content
There was a problem hiding this comment.
Code Review
This pull request introduces an experimental implementation of showDialog that uses native desktop windows. It adds a useWindowing flag to MaterialApp which, when enabled, makes showDialog create a new window instead of an overlay. A new MaterialWindowingManager widget is introduced to manage these windows. The implementation includes a fallback to the traditional dialog behavior if windowing is not supported. A new example application, api_multiwindow, is also added to demonstrate and test this new functionality.
packages/flutter/lib/src/material/material_windowing_manager.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/material_windowing_manager.dart
Outdated
Show resolved
Hide resolved
showDialog that uses a native desktop to display the content showDialog that uses a native desktop window to display the content
examples/api_multiwindow/test/material/dialog/dialog_0_test.dart
Outdated
Show resolved
Hide resolved
| final WidgetBuilder builder; | ||
| } | ||
|
|
||
| /// The window manager provides a convient way to render windows |
There was a problem hiding this comment.
| /// The window manager provides a convient way to render windows | |
| /// The window manager provides a convenient way to render windows |
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { |
There was a problem hiding this comment.
Do you think it'd be worth checking that _WindowRegistryScopes aren't nested? For example, you might get unexpected behavior if you use MaterialApp and then manually add your own WindowManager to the widget tree. I don't feel strongly about this.
There was a problem hiding this comment.
This sounds like an unnecessary restriction. You may even want it in some places I imagine. Let's leave it like this for now, and if it proves to be a problem, we can go back and add the restriction :)
| final List<WindowEntry> _windows = <WindowEntry>[]; | ||
|
|
||
| /// The list of registered windows. | ||
| List<WindowEntry> get windows => List<WindowEntry>.unmodifiable(_windows); |
There was a problem hiding this comment.
Should this be internal with the experimental docs macro?
| /// | ||
| /// See also: | ||
| /// | ||
| /// * [WindowManager], responsible for listening for new windows and rendering them. |
There was a problem hiding this comment.
I'd consider moving the 5th paragraph - which explains when WindowRegistry is useful - up to the 2nd paragraph. I think that's useful context when reading the rest of the docs.
Maybe something like:
| /// * [WindowManager], responsible for listening for new windows and rendering them. | |
| /// A registry used to render top-level windows. | |
| /// | |
| /// The registry is often used to render top-level windows | |
| /// that are logically nested under a widget deep in the tree. | |
| /// | |
| /// The [WindowManager] provides a [WindowRegistry] to its descendents. | |
| /// | |
| /// Descendents of the manager can use [WindowRegistry.maybeOf] to access the | |
| /// registry. With the registry, they can call [WindowRegistry.register] to | |
| /// add a new window to the registry and [WindowRegistry.unregister] to remove | |
| /// a window from the registry. | |
| /// | |
| /// {@macro flutter.widgets.windowing.experimental} | |
| /// | |
| /// See also: | |
| /// | |
| /// * [WindowManager], responsible for listening for new windows and rendering them. |
| late final WindowRegistry _registry; | ||
|
|
||
| @override | ||
| void initState() { | ||
| super.initState(); | ||
| _registry = WindowRegistry(); | ||
| } |
There was a problem hiding this comment.
Oh sorry, my suggestion to create this in initState was unnecessary, you can just initialize the field directly:
| late final WindowRegistry _registry; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| _registry = WindowRegistry(); | |
| } | |
| final WindowRegistry _registry = WindowRegistry(); |
Or if you're feeling fancy:
| late final WindowRegistry _registry; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| _registry = WindowRegistry(); | |
| } | |
| final WindowRegistry _registry = .new(); |
| return navigator.push<T>(route); | ||
| } | ||
|
|
||
| // TODO(justinmc): This was copied from Material, is it needed? |
There was a problem hiding this comment.
@mattkae Bubbling up this comment, it looks like it got missed since it's on an old thread: https://github.com/flutter/flutter/pull/181861/changes#r2879491013
There was a problem hiding this comment.
We certainly need this in Material. I think we can remove it at this layer though. It needs to happen before much of the build in showDialog
827eb77 to
6538a43
Compare
… desktop window to display the content (flutter/flutter#181861)
… desktop window to display the content (flutter/flutter#181861)
Roll Flutter from d3dd7744e81f to d18214307703 (33 revisions) flutter/flutter@d3dd774...d182143 2026-03-06 [email protected] Roll Packages from 8d5c5cd to fe3de64 (2 revisions) (flutter/flutter#183308) 2026-03-06 [email protected] Roll Dart SDK from 1b51451cdb99 to 7c7c1e3d024d (2 revisions) (flutter/flutter#183294) 2026-03-06 [email protected] Roll Dart SDK from 9ac06cdd1801 to 1b51451cdb99 (9 revisions) (flutter/flutter#183289) 2026-03-06 [email protected] Add GitHub workflows to assist with release tasks (flutter/flutter#181978) 2026-03-06 [email protected] [Impeller] Fix new convex path shadow generation in perspective (flutter/flutter#183187) 2026-03-06 [email protected] Roll pub packages (flutter/flutter#183178) 2026-03-05 [email protected] fix: use double quotes in settings.gradle.kts template (flutter/flutter#183081) 2026-03-05 [email protected] Add fallbackColor for PredictiveBackPageTransitionBuilder and PredictiveBackFullscreenPageTransitionBuilder (flutter/flutter#182690) 2026-03-05 [email protected] Simplify TesterContextGLES (multithreading logic not needed), and enable some tests that now pass (flutter/flutter#183250) 2026-03-05 [email protected] Roll Skia from a94df1cdabb0 to a69ef43650ee (14 revisions) (flutter/flutter#183280) 2026-03-05 [email protected] Windowing implementation of `showDialog` that uses a native desktop window to display the content (flutter/flutter#181861) 2026-03-05 [email protected] Build CocoaPod plugin frameworks for Add to App FlutterPluginRegistrant (flutter/flutter#183239) 2026-03-05 [email protected] Extend the Linux web_skwasm_tests_1 timeout to 45 minutes (flutter/flutter#183247) 2026-03-05 [email protected] Update Dart to 3.12 beta 2 (flutter/flutter#183251) 2026-03-05 [email protected] Replace the rest of the references to `flutter/engine` with `flutter/flutter` (flutter/flutter#182938) 2026-03-05 [email protected] chore: convert android_verified_input to pub-workspace (flutter/flutter#183175) 2026-03-05 [email protected] Add await to flutter_test callsites (flutter/flutter#182983) 2026-03-05 [email protected] [iOS] Skip gesture recognizer reset workaround on iOS 26+ (flutter/flutter#183186) 2026-03-05 [email protected] Add warning for plugins not migrated to UIScene (flutter/flutter#182826) 2026-03-05 [email protected] Roll Fuchsia Linux SDK from JJw5EJ87vLGqFVl4h... to 8ay15_eQOEgPHCypm... (flutter/flutter#183255) 2026-03-05 [email protected] Roll Skia from ada0b7628c79 to a94df1cdabb0 (2 revisions) (flutter/flutter#183249) 2026-03-05 [email protected] Roll Packages from 82baf93 to 8d5c5cd (2 revisions) (flutter/flutter#183269) 2026-03-05 [email protected] Add `UnlabaledLeafNodeEvaluation` (flutter/flutter#182872) 2026-03-04 [email protected] Re-specify the ndk version in various test apps, to prevent ndk download (flutter/flutter#183134) 2026-03-04 [email protected] Eliminate rebuilds for Scaffold FAB animation (flutter/flutter#182331) 2026-03-04 [email protected] Add Michal Kucharski to AUTHORS (flutter/flutter#182366) 2026-03-04 [email protected] Merge changelog from 3.41.4 stable. (flutter/flutter#183243) 2026-03-04 [email protected] Allow stylus support on windows (flutter/flutter#165323) 2026-03-04 [email protected] Fix docs on SingletonFlutterWindow.supportsShowingSystemContextMenu (flutter/flutter#183142) 2026-03-04 [email protected] Roll Packages from 9083bc9 to 82baf93 (5 revisions) (flutter/flutter#183240) 2026-03-04 [email protected] Fixes FocusHighlightMode on Android when typing in software keyboard (flutter/flutter#180753) 2026-03-04 [email protected] Make compileShader() retry without sksl if it fails with sksl. (flutter/flutter#183146) 2026-03-04 [email protected] [web] Use pointer-events: auto for non-interactive leaf semantics nodes (flutter/flutter#183077) 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: ...
…indow to display the content (flutter#181861) <img width="800" height="635" alt="image" src="proxy.php?url=https://github.com/user-attachments/assets/54315175-2091-4508-a61f-337b35ef35e8" /> <img width="800" height="635" alt="image" src="proxy.php?url=https://github.com/user-attachments/assets/9f627624-b008-48e1-a281-aabb15b9418e" /> ## What's new? - Added the `MaterialWindowingManager` which will render all of the sub-windows that the material app relies - The `MaterialWindowingManager` provides the `MaterialWindowRegistry` which enables its descendants to create and remove windows from the windowing manager - Implemented a windowing path for `showDialog` which uses that `Navigator` to push a true window to the navigation stack - In `material_window_manager.dart`, the dialog will be rendered appropriately with inherited theming, text direction, and other media query data - Added the `api_multiwindow` example application to demonstrate the new behavior for both fullscreen and non-fullscreen dialogs - Added tests to the `api_multiwindow` example application - Updated the documentation of `showDialog` to explain how each field works when windowing is enabled - Made it so that we fallback to the regular `showDialog` implementation if the windowing implementation fails ## How to test On Win32, macOS, and Linux: 1. `fluter config --enable-windowing` 2. In `examples/api_multiwindow`: `flutter run lib/material/dialog/dialog.0.dart` 3. Click the two buttons and see the true dialogs Also, run `flutter test` and see that the tests pass ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [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. --------- Co-authored-by: Justin McCandless <[email protected]>
What's new?
MaterialWindowingManagerwhich will render all of the sub-windows that the material app reliesMaterialWindowingManagerprovides theMaterialWindowRegistrywhich enables its descendants to create and remove windows from the windowing managershowDialogwhich uses thatNavigatorto push a true window to the navigation stackmaterial_window_manager.dart, the dialog will be rendered appropriately with inherited theming, text direction, and other media query dataapi_multiwindowexample application to demonstrate the new behavior for both fullscreen and non-fullscreen dialogsapi_multiwindowexample applicationshowDialogto explain how each field works when windowing is enabledshowDialogimplementation if the windowing implementation failsHow to test
On Win32, macOS, and Linux:
fluter config --enable-windowingexamples/api_multiwindow:flutter run lib/material/dialog/dialog.0.dartAlso, run
flutter testand see that the tests passPre-launch Checklist
///).