Skip to content

Adding the SatelliteWindowController interface to _window.dart#182903

Merged
mattkae merged 14 commits into
flutter:masterfrom
canonical:satellite-windows-api
Mar 12, 2026
Merged

Adding the SatelliteWindowController interface to _window.dart#182903
mattkae merged 14 commits into
flutter:masterfrom
canonical:satellite-windows-api

Conversation

@mattkae

@mattkae mattkae commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

What's new?

  • Added the concept of a SatelliteWindowController and SatelliteWindow widget to the _window.dart API
  • Wrote tests for it
  • Throwing "unsupported" for all existing WindowingOwners when trying to create it
  • Stubbed it in the example application
  • Implemented a "happy" implementation in the flutter_test package

Pre-launch Checklist

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

@github-actions github-actions Bot added a: tests "flutter test", flutter_test, or one of our tests framework flutter/packages/flutter repository. See also f: labels. d: examples Sample code and demos labels Feb 25, 2026
@github-actions github-actions Bot added d: api docs Issues with https://api.flutter.dev/ a: desktop Running on desktop labels Feb 25, 2026
@mattkae mattkae marked this pull request as ready for review February 26, 2026 15:07

@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 introduces a new experimental SatelliteWindow and SatelliteWindowController to the windowing API. The changes are well-structured, including API definitions, platform stubs, a test implementation, and an example. The code follows existing patterns and is well-documented. I have a couple of minor suggestions: one to adhere to the Dart style guide for a one-line method, and another to fix a typo in an error message.

Comment thread examples/api/lib/widgets/windows/satellite.0.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window_win32.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window_macos.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart
Comment thread packages/flutter/lib/src/widgets/_window.dart
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
/// open, the satellite may choose to reparent to the active document such that
/// closing one document will not cause the satellite to close. This behavior
/// may be implemented at the toolkit level. Reparenting a satellite will not
/// change the current absolute position of the satellite.

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.

Just curious, why can't we change the satellite's position when it is reparented? Is that something we can't support on all platforms?


Previously the docs state:

Satellite windows maintain their position relative to their parent

What happens if I reparent a satellite window, and then move the new parent? Will the satellite window maintain its position relative to its new parent? I expect that might result in funky behavior.

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.

We can change the satellite's position, but we figured that would be too jarring for users.

The best example is a word processing application. Imagine you have two windows open each with their own document, but sharing the same satellite window toolbar. When one document is closed, you would expect the satellite toolbar to remain open in the same position instead of snapping to a new anchor position next to the other document.

In this case, the satellite window will now maintain its position relative to the remaining document.

@loic-sharma loic-sharma Mar 12, 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.

Gotcha, that makes sense.

Would it make sense to add a move({required Rect anchorRect, required WindowPositioner positioner}) method to SatelliteWindowController? This would update the satellite window position once. I imagine this would be useful in reparenting scenarios if you do want this slightly jarring experience. I'm OK punting this until later, just a thought.

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.

Yeah let's punt it for now, and see if it comes up. Intuition tells me that the user probably won't want to do that, but who knows. We have that type of method for tooltips and popups.

Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated

@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.

  • I can't get the example to run, see my comments below.

  • I see this is beyond the stuff that you guys decided to call MVP in your doc, are there any implications for pre/post MVP work and our plans for shipping it in general?

  • Overall this PR looks fine but there's one thing that I want to think through. Let's say I'm building an app on only one platform, say macOS. SatelliteWindow uses NSPanel under the hood on macOS, which looks like it takes 3 boolean parameters (isFloatingPanel, becomesKeyOnlyIfNeeded, and worksWhenModal). Let's say I need to individually set one of those booleans for my use case. What are my options? How much of the multiwindow code will be unusable for me and how much can I still manage to use?

Comment thread packages/flutter/lib/src/widgets/_window.dart
Comment thread examples/api/lib/widgets/windows/satellite.0.dart
Comment thread examples/api/test/widgets/windows/satellite.0_test.dart
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart
Comment thread examples/api/lib/widgets/windows/satellite.0.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated
@mattkae

mattkae commented Mar 10, 2026

Copy link
Copy Markdown
Contributor Author
  • I can't get the example to run, see my comments below.

Fixed 👍 bad merge

* I see this is beyond the stuff that you guys decided to call [MVP in your doc](https://docs.google.com/document/d/1eQG-IS7r4_S9_h50MY_hSGwUVtgSTRSLzu7MLzPNd2Y/edit?tab=t.0#heading=h.4y3d6rrizqfa), are there any implications for pre/post MVP work and our plans for shipping it in general?

Satellites were always intended to follow after the other window types, so we figured we'd open up the conversation now to get the ball rolling 😄 These can very well ship with the rest of the windowing API, but we expected them to be a bit more controversial as they have no precedent in Flutter or Material.

* Overall this PR looks fine but there's one thing that I want to think through. Let's say I'm building an app on only one platform, say macOS. SatelliteWindow uses [NSPanel](https://developer.apple.com/documentation/appkit/nspanel) under the hood on macOS, which looks like it takes 3 boolean parameters (isFloatingPanel, becomesKeyOnlyIfNeeded, and worksWhenModal). Let's say I need to individually set one of those booleans for my use case. What are my options? How much of the multiwindow code will be unusable for me and how much can I still manage to use?

At the moment, your options are limited. We haven't yet tackled the problem of "how do I add this platform-specific configuration to my window" yet. This is something that we'll really have to talk about for Win32, macOS, and Linux. I have a feeling that this will involve designing an API that exposes many of those features, which is no small task.

The "escape hatch" that the user has at the moment is to override the WindowingOwner with their own implementation to create their custom satellite window.

@knopp

knopp commented Mar 10, 2026

Copy link
Copy Markdown
Member

Overall this PR looks fine but there's one thing that I want to think through. Let's say I'm building an app on only one platform, say macOS. SatelliteWindow uses NSPanel under the hood on macOS, which looks like it takes 3 boolean parameters (isFloatingPanel, becomesKeyOnlyIfNeeded, and worksWhenModal). Let's say I need to individually set one of those booleans for my use case. What are my options? How much of the multiwindow code will be unusable for me and how much can I still manage to use?

We will be exposing raw window handle (NSWindow*, HWND and GtkWindow*). Once you have the NSWindow you can pretty much change any attribute that you want. There are plans to expose message handling on windows too, so you can for example handle WM_NCHITTEST if you want completely customizable window.

We will likely want to expose some of the NSWindowDelegate methods too. The nice thing is we can do all this per platform implementation and we don't need to with lowest common denominator.

/// provided to the [SatelliteWindow] widget, who does the work of rendering the
/// content inside of this window.
///
/// The user of this class is responsible for managing the lifecycle of the window.

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 add a sentence that explains how destroying the parent BaseWindowController affects this SatelliteWindowController.

It'd likely be worth adding a similar comment to dialog, tooltip, and popups window controllers too.

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 added it just to satellite for now.

I am going to revise some of the documentation for the other windows after this, as satellites have brought up a bunch of nits that we should address there.

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.

SGTM, thanks!

@mattkae mattkae requested a review from loic-sharma March 11, 2026 12:59

@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 👍

Thanks for the explanations of the API here @mattkae and @knopp, I think the problem is a lot smaller than I was assuming. As discussed offline I think the best way to prove this is to include an example of the use of something like the raw NSWindow* used alongside the rest of the usual multiwindow infrastructure like RegularWindow etc. But that can wait for another PR, once we have exposed the raw window handles.

Landing this PR won't delay the removal of the feature flag, will it? I just want to make sure that adding satellites in the framework isn't going to delay everything else by expanding the scope of the engine work.

Comment thread packages/flutter/lib/src/widgets/_window.dart Outdated

@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!

@mattkae

mattkae commented Mar 12, 2026

Copy link
Copy Markdown
Contributor Author

Landing this PR won't delay the removal of the feature flag, will it? I just want to make sure that adding satellites in the framework isn't going to delay everything else by expanding the scope of the engine work.

No it should not. We want to keep the feature flag around while we gain some early users of the windowing system. This is just another window that we'll get feedback on, albeit a less-used window in all likelihood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop a: tests "flutter test", flutter_test, or one of our tests CICD Run CI/CD d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants