Skip to content

Commit 65fa21c

Browse files
committed
window setting
1 parent f91e40a commit 65fa21c

File tree

4 files changed

+319
-48
lines changed

4 files changed

+319
-48
lines changed

mwp/lib/src/context_menu.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'package:flutter/gestures.dart';
21
import 'package:flutter/material.dart';
32

43
import 'window.dart';
@@ -28,7 +27,7 @@ class _WindowedContextMenuState extends State<WindowedContextMenu> {
2827
controller: _controller,
2928
child: Container(
3029
color: Colors.white,
31-
margin: EdgeInsets.all(2.0),
30+
margin: const EdgeInsets.all(2.0),
3231
child: Material(
3332
child: Column(
3433
children: widget.entries,

mwp/lib/src/dart_ui.dart

+35-17
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@ import 'package:meta/meta.dart';
1111

1212
extension 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.
2427
class _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

7584
class 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
101111
class 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
143157
class 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',

mwp/lib/src/framework_extensions.dart

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'dart:ui';
2+
3+
import 'package:flutter/rendering.dart';
4+
5+
// TODO: everything in this file should be added to the framework.
6+
7+
extension BoxConstraintsExtension on BoxConstraints {
8+
/// Creates [ViewConstraints] that matches this box constraints.
9+
ViewConstraints toViewConstraints() {
10+
return ViewConstraints(minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight);
11+
}
12+
}

0 commit comments

Comments
 (0)