@@ -11,15 +11,18 @@ import 'package:meta/meta.dart';
1111
1212extension WindowApi on PlatformDispatcher {
1313 Iterable <FlutterWindow > get windows => _WindowManager .instance.windows;
14+ FlutterWindow ? window ({required int id}) => _WindowManager .instance.window (id: id);
1415 Future <FlutterWindow > createWindow (FlutterWindowRequest request) {
1516 return _WindowManager .instance.createWindow (request);
1617 }
17- VoidCallback ? get onWindowsChanged => _WindowManager .instance.onWindowsChanged;
18- set onWindowsChanged (VoidCallback ? value) {
18+ WindowsChangedCallback ? get onWindowsChanged => _WindowManager .instance.onWindowsChanged;
19+ set onWindowsChanged (WindowsChangedCallback ? value) {
1920 _WindowManager .instance.onWindowsChanged = value;
2021 }
2122}
2223
24+ typedef WindowsChangedCallback = void Function (Iterable <int > windowIds);
25+
2326// This should live on the PlatformDispatcher.
2427class _WindowManager {
2528 _WindowManager ._() {
@@ -32,6 +35,8 @@ class _WindowManager {
3235 Iterable <FlutterWindow > get windows => _windows.values;
3336 final Map <int , FlutterWindow > _windows = < int , FlutterWindow > {};
3437
38+ FlutterWindow ? window ({required int id}) => _windows[id];
39+
3540 Future <FlutterWindow > createWindow (FlutterWindowRequest request) async {
3641 final int ? windowId = await _windowChannel.invokeMethod <int >('create' , request._encode ());
3742 if (windowId == null ) {
@@ -44,12 +49,12 @@ class _WindowManager {
4449 return window;
4550 }
4651
47- VoidCallback ? onWindowsChanged;
52+ WindowsChangedCallback ? onWindowsChanged;
4853
4954 static const MethodChannel _windowChannel = MethodChannel ('flutter/window' );
5055
5156 Future <Object ?> _handleChannelInvocation (MethodCall call) async {
52- bool invokeCallback = true ;
57+ final List < int > ids = < int > [] ;
5358 switch (call.method) {
5459 case 'update' :
5560 final Map <String , Object > args = call.arguments as Map <String , Object >;
@@ -62,20 +67,24 @@ class _WindowManager {
6267 } else {
6368 _windows[windowId] = FlutterWindow ._(windowId, config, view);
6469 }
70+ ids.add (windowId);
6571 case 'delete' :
66- invokeCallback = _windows.remove (call.arguments) != null ;
72+ final int windowId = call.arguments as int ;
73+ if (_windows.remove (windowId) != null ) {
74+ ids.add (windowId);
75+ }
6776 }
68- if (invokeCallback ) {
69- onWindowsChanged? .call ();
77+ if (ids.isNotEmpty ) {
78+ onWindowsChanged? .call (ids );
7079 }
7180 return null ;
7281 }
7382}
7483
7584class FlutterWindow {
76- FlutterWindow ._(this ._id , this ._config, this ._view);
85+ FlutterWindow ._(this .id , this ._config, this ._view);
7786
78- final int _id ;
87+ final int id ;
7988 _FlutterWindowConfiguration _config;
8089 FlutterView _view;
8190
@@ -86,28 +95,33 @@ class FlutterWindow {
8695
8796 FlutterView get view => _view;
8897 Size get contentSize => _config.contentSize;
98+ RelativeOffset get contentLocation => _config.contentLocation;
8999
90100 Future <void > requestUpdate (FlutterWindowRequest request) async {
91- await _WindowManager ._windowChannel.invokeMethod ('update' , < String , Object ? > {'id' : _id , 'request' : request._encode ()});
101+ await _WindowManager ._windowChannel.invokeMethod ('update' , < String , Object ? > {'id' : id , 'request' : request._encode ()});
92102 }
93103
94104 Future <void > close () async {
95- await _WindowManager ._windowChannel.invokeMethod ('close' , _id );
105+ await _WindowManager ._windowChannel.invokeMethod ('close' , id );
96106 }
97107}
98108
99109// Everything is in physical pixel!
100110@immutable
101111class FlutterWindowRequest {
102- const FlutterWindowRequest ({this .contentOffset, this .contentConstraints, this .allowPointerEvents});
112+ const FlutterWindowRequest ({
113+ this .contentLocation,
114+ this .contentConstraints,
115+ this .allowPointerEvents,
116+ });
103117
104- final RelativeOffset ? contentOffset ;
118+ final RelativeOffset ? contentLocation ;
105119 final ViewConstraints ? contentConstraints;
106120 final bool ? allowPointerEvents;
107121
108122 Object ? _encode () {
109123 return < String , Object ? > {
110- 'offset ' : contentOffset ? ._encode (),
124+ 'location ' : contentLocation ? ._encode (),
111125 'constraint_min_width' : contentConstraints? .minWidth,
112126 'constraint_max_width' : contentConstraints? .maxWidth,
113127 'constraint_min_height' : contentConstraints? .minHeight,
@@ -122,27 +136,28 @@ class _FlutterWindowConfiguration {
122136 const _FlutterWindowConfiguration ({
123137 required this .viewId,
124138 required this .contentSize,
125- required this .contentOffset ,
139+ required this .contentLocation ,
126140 });
127141
128142 factory _FlutterWindowConfiguration .decode (Object encoded) {
129143 final Map <String , Object ?> decoded = encoded as Map <String , Object ?>;
130144 return _FlutterWindowConfiguration (
131145 viewId: decoded['viewId' ]! as int ,
132146 contentSize: Size (decoded['width' ]! as double , decoded['height' ]! as double ),
133- contentOffset : RelativeOffset ._decode (decoded['offset' ]! ),
147+ contentLocation : RelativeOffset ._decode (decoded['offset' ]! ),
134148 );
135149 }
136150
137151 final int viewId;
138152 final Size contentSize;
139- final RelativeOffset contentOffset ;
153+ final RelativeOffset contentLocation ;
140154}
141155
142156@immutable
143157class RelativeOffset {
144158 const RelativeOffset .display (Display this .display, this .offset) : view = null ;
145159 const RelativeOffset .view (FlutterView this .view, this .offset) : display = null ;
160+ const RelativeOffset ._(this .view, this .display, this .offset) : assert (view == null || display == null );
146161
147162 factory RelativeOffset ._decode (Object encoded) {
148163 final Map <String , Object ?> decoded = encoded as Map <String , Object ?>;
@@ -169,6 +184,9 @@ class RelativeOffset {
169184
170185 double get devicePixelRatio => view? .devicePixelRatio ?? display? .devicePixelRatio ?? 1.0 ;
171186
187+ RelativeOffset operator * (double operand) => RelativeOffset ._(view, display, offset * operand);
188+ RelativeOffset operator / (double operand) => RelativeOffset ._(view, display, offset / operand);
189+
172190 Object _encode () {
173191 return < String , Object ? > {
174192 'type' : view == null ? 'display' : 'view' ,
0 commit comments