-
Notifications
You must be signed in to change notification settings - Fork 6k
Migrate engine to use multi-window API #18368
Conversation
3e43ee5
to
333a973
Compare
0c9b84b
to
fe6e3a1
Compare
f0ce7f8
to
df307a0
Compare
6103c26
to
2f8e327
Compare
lib/ui/window.dart
Outdated
/// | ||
/// This class provides backward compatibility with code that was written before | ||
/// Flutter supported multiple top level windows. To modify or retrieve these | ||
/// properties, new code should use `WidgetsBinding.instance.platformDispatcher`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't want people to use an API, we shouldn't provide it. If it's only for legacy use, let's @deprecate it and sunset it.
I wouldn't do that though. I would just merge PlatformDispatcher into SingletonFlutterWindow and call it Window. The single-window case is the common case for most apps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be OK if I just remove the "backward compatibility" comments, and treat it entirely as non-legacy API?
I'd really rather not merge the classes back together. I separated them out because the functions on PlatformDispatcher
don't belong conceptually to a "Window": they're all attributes of the platform configuration, and don't have to do with the concept of a window. It makes no sense to me, for instance, that alwaysUse24HourFormat
is a window attribute, or that a window has an onPlatformMessage
.
I think it's is incorrectly complecting things to keep them in Window
, other than to keep from breaking existing code.
Also, (as I think you suggested in the doc), I'd like to use Window
as the name of the widget that defines a new window, which is why I introduced SingletonFlutterWindow
.
I can see why you would want to merge them again, but even if I just made window
an instance of PlatformDispatcher
, it would have odd things in it. For instance, it would have a list of views that included itself, and a screen accessor as well as a list of screens, and viewConfiguration accessor as well as a list of views. I can foresee people making mistakes accessing the wrong one, or just being confused.
c70c663
to
5da9a1b
Compare
The goal here is to convert from the window singleton to an API that has the concept of multiple windows. I'm not attempting to actually enable creating multiple windows here, just migrate to an API that has a concept of multiple windows/screens.
…en initialization order on web.
…s unnecessarily breaking
… window class, to avoid breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial comments from skimming the native side of the changes. Figuring out how to handle embedder.h is going to be the trickiest part of the native side of this migration.
@@ -2,12 +2,11 @@ | |||
// Use of this source code is governed by a BSD-style license that can be | |||
// found in the LICENSE file. | |||
|
|||
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary header(s) should be first. This was intentional, and your change violates the style guide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I know that, I'm not really sure why I reordered it like that.
@@ -298,13 +297,21 @@ - (void)updateWindowMetrics { | |||
CGSize scaledSize = [view convertRectToBacking:view.bounds].size; | |||
double pixelRatio = view.bounds.size.width == 0 ? 1 : scaledSize.width / view.bounds.size.width; | |||
|
|||
const FlutterWindowMetricsEvent event = { | |||
.struct_size = sizeof(event), | |||
// The screen is currently always the same size as the window. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we reference an issue that describes a transition plan for this? It seems weird to intentionally send incorrect information without more detail about the plan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I filed flutter/flutter#60131 and referenced it in the comment.
I'm going to split out the screen stuff into a separate PR and land that before the rest of the changes here, to make it easier to review, and then I can even get the right screen information on each platform.
@@ -336,9 +336,18 @@ typedef struct { | |||
size_t width; | |||
/// Physical height of the window. | |||
size_t height; | |||
} FlutterWindowMetricsEvent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change, which we don't generally allow in embedder.h. If we're changing the structs, we need new structs and new APIs using them, and the old path needs to do something reasonable (presumably translate under the hood to the new structs then call through).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I can just duplicate the information about the pixel ratio when I send the window events, and send additional window events when the screen DPI changes (which shouldn't be often). I moved it because I didn't want it to be possible to have them not be in agreement with the screen information and I didn't want it to be ambiguous as to which one is authoritative.
But not breaking the ABI is obviously more important.
FLUTTER_EXPORT | ||
FlutterEngineResult FlutterEngineSendScreenMetricsEvent( | ||
FLUTTER_API_SYMBOL(FlutterEngine) engine, | ||
const FlutterScreenMetricsEvent* event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't make breaking changes to embedder.h, we should be as future-proof as possible in any new API we're adding. That means we shouldn't add an API that assumes a single screen when we know we're going to need to allow a list of screens. Instead we should design it for the future case, and document that it currently only uses the first screen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the window and screen events were meant to have an additional id field so that they would be identified, I just forgot to add that here in the embedder implementation. (if you look at screen.h
, you'll see what I mean). I've wired that through now, so it isn't limited to one screen.
shell/platform/linux/fl_engine.cc
Outdated
@@ -3,13 +3,13 @@ | |||
// found in the LICENSE file. | |||
|
|||
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h" | |||
#include "flutter/shell/platform/linux/fl_engine_private.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a primary header, and should be first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments from skimming through the dart side for the first time.
|
||
/// The current platform configuration. | ||
/// | ||
/// If values in this configuration change, [onMetricsChanged] will be called. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will onMetricsChanged be called in addition to onPlatformConfigurationChanged? Or is this a typo?
PlatformConfiguration get configuration => _configuration; | ||
PlatformConfiguration _configuration = const PlatformConfiguration(); | ||
|
||
/// Called when the platform configuration changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to onMetricsChanged, maybe document what this callback is used for?
/// A const constructor for an immutable [ViewConfiguration]. | ||
const ViewConfiguration( | ||
this.screen, | ||
{ this.window, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: formatting, put the { on the previous line?
/// This is the screen that the upper left corner of the view appears on. | ||
final Screen screen; | ||
|
||
/// The top level view into which the view is placed and its geometry is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doc comment confused me a little but because it only talks about views and the property is named "window"...
5da9a1b
to
a235ea6
Compare
I'm going to split out all the screen-related changes into another PR that doesn't include Dart changes, so that can be reviewed separately, so I'm going to close this PR and reopen when I have something based on a submitted set of screen changes. This thing is just too huuge to review. |
The screens PR is #19425 |
Hello @gspencergoog, when will it be released ? are there any plans? Thanks! |
@0xZOne There are plans, but no concrete release date yet. There's a lot still to do before it will be ready, and we're somewhat resource constrained at the moment. |
Amazing.Are there any plans now? If not how can I compile it myself. |
There are plans, and we are working on it, but as yet no working prototypes you can compile. |
Description
This is a PR for trying out the multi-window API on the engine repo. The goal here is to convert from the window singleton to an API that has the concept of multiple windows. I'm not attempting to actually enable creating multiple windows here, just migrate to an API that has a concept of multiple windows/screens.
The design doc for this change is here.
The associated framework change is flutter/flutter#58696
The major changes in this PR:
Window
class to a newPlatformConfiguration
class.ScreenMetrics
andScreen
classes so that windows can be on screens.ScreenMetrics
, and adding an upper left position for windows (currently always 0, 0).Window
, and into the newPlatformDispatcher
class that holds all of the platform state, so that the platform code need only update the configuration on this class.FlutterView
,FlutterWindow
, andSingletonFlutterWindow
classes to separate out the concepts of a view (of which there may be multiple in a window), a window (of which there may be multiple on a screen, and they host views), and a window where there is only ever expected to be one (this hosts the entire API of the formerWindow
class, and is the type of thewindow
singleton).Window
class entirely (it is replaced bySingletonFlutterWindow
), so that we can eventually use that name as the name for the widget that creates new windows.Things that still need to happen before review:
Related Issues
Tests
Breaking Change
Engine::DefaultRouteName
toEngine::InitialRouteName
, andRuntimeController::DefaultRouteName
toRuntimeController::InitialRouteName
to match PlatformDispatcher name. Leaveswindow.defaultRouteName
as-is.