diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index b069fcee1..9f6bc01f2 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1389,6 +1389,13 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { isMaximized = await wc.isMaximized(); break; } + if (Platform.isWindows) { + const kMinOffset = -10000; + if (position.dx < kMinOffset || position.dy < kMinOffset) { + debugPrint("Invalid position: $position, ignore saving position"); + return; + } + } final pos = LastWindowPosition( sz.width, sz.height, position.dx, position.dy, isMaximized); diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 8c2f6a0b0..ec96d271e 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -360,6 +360,9 @@ class _RemoteToolbarState extends State { triggerAutoHide() => _debouncerHide.value = _debouncerHide.value + 1; + void _minimize() async => + await WindowController.fromWindowId(windowId).minimize(); + @override initState() { super.initState(); @@ -467,6 +470,12 @@ class _RemoteToolbarState extends State { toolbarItems.add(_VoiceCallMenu(id: widget.id, ffi: widget.ffi)); } toolbarItems.add(_RecordMenu(ffi: widget.ffi)); + if (!isWebDesktop) { + toolbarItems.add(_MinimizeMenu( + state: widget.state, + onPressed: _minimize, + )); + } toolbarItems.add(_CloseMenu(id: widget.id, ffi: widget.ffi)); return Column( mainAxisSize: MainAxisSize.min, @@ -549,6 +558,30 @@ class _PinMenu extends StatelessWidget { } } +class _MinimizeMenu extends StatelessWidget { + final ToolbarState state; + final Function() onPressed; + bool get isFullscreen => stateGlobal.fullscreen; + const _MinimizeMenu({ + Key? key, + required this.state, + required this.onPressed, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Offstage( + offstage: !isFullscreen, + child: _IconMenuButton( + assetName: 'assets/minimize_black_24dp.svg', + tooltip: 'Minimize', + onPressed: onPressed, + color: _ToolbarTheme.blueColor, + hoverColor: _ToolbarTheme.hoverBlueColor, + )); + } +} + class _FullscreenMenu extends StatelessWidget { final ToolbarState state; final Function(bool) setFullscreen; @@ -1597,11 +1630,11 @@ class _IconMenuButtonState extends State<_IconMenuButton> { final icon = widget.icon ?? SvgPicture.asset( widget.assetName!, - color: Colors.white, + colorFilter: ColorFilter.mode(Colors.white, BlendMode.srcIn), width: _ToolbarTheme.buttonSize, height: _ToolbarTheme.buttonSize, ); - final button = SizedBox( + var button = SizedBox( width: _ToolbarTheme.buttonSize, height: _ToolbarTheme.buttonSize, child: MenuItemButton( @@ -1625,6 +1658,12 @@ class _IconMenuButtonState extends State<_IconMenuButton> { ).marginSymmetric( horizontal: widget.hMargin ?? _ToolbarTheme.buttonHMargin, vertical: widget.vMargin ?? _ToolbarTheme.buttonVMargin); + if (widget.tooltip != null) { + button = Tooltip( + message: widget.tooltip!, + child: button, + ); + } if (widget.topLevel) { return MenuBar(children: [button]); } else { diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index f7b4f8cc2..94f9cc234 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -65,7 +65,7 @@ class StateGlobal { ? kMaximizeEdgeSize : kWindowEdgeSize; print( - "fullscreen: ${fullscreen}, resizeEdgeSize: ${_resizeEdgeSize.value}"); + "fullscreen: $fullscreen, resizeEdgeSize: ${_resizeEdgeSize.value}"); _windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth; WindowController.fromWindowId(windowId) .setFullscreen(_fullscreen)