diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 8b20214df..33321c81a 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1441,6 +1441,8 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { late Offset position; late Size sz; late bool isMaximized; + bool isFullscreen = stateGlobal.fullscreen || + (Platform.isMacOS && stateGlobal.closeOnFullscreen); setFrameIfMaximized() { if (isMaximized) { final pos = bind.getLocalFlutterOption(k: kWindowPrefix + type.name); @@ -1486,7 +1488,7 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { } final pos = LastWindowPosition( - sz.width, sz.height, position.dx, position.dy, isMaximized, stateGlobal.fullscreen); + sz.width, sz.height, position.dx, position.dy, isMaximized, isFullscreen); debugPrint( "Saving frame: $windowId: ${pos.width}/${pos.height}, offset:${pos.offsetWidth}/${pos.offsetHeight}, isMaximized:${pos.isMaximized}, isFullscreen:${pos.isFullscreen}"); @@ -1495,7 +1497,7 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { if (type == WindowType.RemoteDesktop && windowId != null) { await _saveSessionWindowPosition( - type, windowId, isMaximized, stateGlobal.fullscreen, pos); + type, windowId, isMaximized, isFullscreen, pos); } } diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 0490ce373..cb9438465 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; @@ -109,6 +110,14 @@ class _ConnectionTabPageState extends State { final sessionId = args['session_id']; final tabWindowId = args['tab_window_id']; windowOnTop(windowId()); + if (tabController.length == 0) { + if (Platform.isMacOS && stateGlobal.closeOnFullscreen) { + Timer( + Duration(milliseconds: 300), + () async => await WindowController.fromWindowId(windowId()) + .setFullscreen(true)); + } + } ConnectionTypeState.init(id); _toolbarState.setShow( bind.mainGetUserDefaultOption(key: 'collapse_toolbar') != 'Y'); diff --git a/flutter/lib/desktop/widgets/tabbar_widget.dart b/flutter/lib/desktop/widgets/tabbar_widget.dart index b27e8fafe..2dcd757a1 100644 --- a/flutter/lib/desktop/widgets/tabbar_widget.dart +++ b/flutter/lib/desktop/widgets/tabbar_widget.dart @@ -482,6 +482,8 @@ class WindowActionPanel extends StatefulWidget { class WindowActionPanelState extends State with MultiWindowListener, WindowListener { final _saveFrameDebounce = Debouncer(delay: Duration(seconds: 1)); + Timer? _macOSCheckRestoreTimer; + int _macOSCheckRestoreCounter = 0; @override void initState() { @@ -514,6 +516,7 @@ class WindowActionPanelState extends State void dispose() { DesktopMultiWindow.removeListener(this); windowManager.removeListener(this); + _macOSCheckRestoreTimer?.cancel(); super.dispose(); } @@ -566,6 +569,33 @@ class WindowActionPanelState extends State @override void onWindowClose() async { + mainWindowClose() async => await windowManager.hide(); + notMainWindowClose(WindowController controller) async { + await controller.hide(); + await Future.wait([ + rustDeskWinManager + .call(WindowType.Main, kWindowEventHide, {"id": kWindowId!}), + widget.onClose?.call() ?? Future.microtask(() => null) + ]); + } + + macOSWindowClose( + Future Function() restoreFunc, + Future Function() checkFullscreen, + Future Function() closeFunc) async { + await restoreFunc(); + _macOSCheckRestoreCounter = 0; + _macOSCheckRestoreTimer = + Timer.periodic(Duration(milliseconds: 30), (timer) async { + _macOSCheckRestoreCounter++; + if (!await checkFullscreen() || _macOSCheckRestoreCounter >= 30) { + _macOSCheckRestoreTimer?.cancel(); + _macOSCheckRestoreTimer = null; + Timer(Duration(milliseconds: 500), () async => await closeFunc()); + } + }); + } + // hide window on close if (widget.isMainWindow) { if (rustDeskWinManager.getActiveWindows().contains(kMainWindowId)) { @@ -573,23 +603,28 @@ class WindowActionPanelState extends State } // macOS specific workaround, the window is not hiding when in fullscreen. if (Platform.isMacOS && await windowManager.isFullScreen()) { - await windowManager.setFullScreen(false); - await Future.delayed(Duration(seconds: 1)); + stateGlobal.closeOnFullscreen = true; + await macOSWindowClose( + () async => await windowManager.setFullScreen(false), + () async => await windowManager.isFullScreen(), + mainWindowClose); + } else { + stateGlobal.closeOnFullscreen = false; + await mainWindowClose(); } - await windowManager.hide(); } else { // it's safe to hide the subwindow final controller = WindowController.fromWindowId(kWindowId!); if (Platform.isMacOS && await controller.isFullScreen()) { - await controller.setFullscreen(false); - await Future.delayed(Duration(seconds: 1)); + stateGlobal.closeOnFullscreen = true; + await macOSWindowClose( + () async => await controller.setFullscreen(false), + () async => await controller.isFullScreen(), + () async => await notMainWindowClose(controller)); + } else { + stateGlobal.closeOnFullscreen = false; + await notMainWindowClose(controller); } - await controller.hide(); - await Future.wait([ - rustDeskWinManager - .call(WindowType.Main, kWindowEventHide, {"id": kWindowId!}), - widget.onClose?.call() ?? Future.microtask(() => null) - ]); } super.onWindowClose(); } diff --git a/flutter/lib/models/chat_model.dart b/flutter/lib/models/chat_model.dart index 37766e54a..61d7682e1 100644 --- a/flutter/lib/models/chat_model.dart +++ b/flutter/lib/models/chat_model.dart @@ -10,7 +10,6 @@ import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; import 'package:flutter_hbb/mobile/pages/home_page.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; -import 'package:get/get_rx/src/rx_types/rx_types.dart'; import 'package:get/get.dart'; import 'package:uuid/uuid.dart'; import 'package:window_manager/window_manager.dart'; diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index a70d0f97d..e36bef924 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -20,6 +20,8 @@ class StateGlobal { final RxBool showRemoteToolBar = false.obs; final RxInt displaysCount = 0.obs; final svcStatus = SvcStatus.notReady.obs; + // Only used for macOS + bool closeOnFullscreen = false; // Use for desktop -> remote toolbar -> resolution final Map> _lastResolutionGroupValues = {};