Merge pull request #5625 from dignow/feat/remember_remote_window_fullscreen

Feat/remember remote window fullscreen
This commit is contained in:
RustDesk 2023-09-08 00:41:38 +08:00 committed by GitHub
commit 065c19cbbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 35 deletions

View File

@ -1392,9 +1392,10 @@ class LastWindowPosition {
double? offsetWidth; double? offsetWidth;
double? offsetHeight; double? offsetHeight;
bool? isMaximized; bool? isMaximized;
bool? isFullscreen;
LastWindowPosition(this.width, this.height, this.offsetWidth, LastWindowPosition(this.width, this.height, this.offsetWidth,
this.offsetHeight, this.isMaximized); this.offsetHeight, this.isMaximized, this.isFullscreen);
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return <String, dynamic>{ return <String, dynamic>{
@ -1403,6 +1404,7 @@ class LastWindowPosition {
"offsetWidth": offsetWidth, "offsetWidth": offsetWidth,
"offsetHeight": offsetHeight, "offsetHeight": offsetHeight,
"isMaximized": isMaximized, "isMaximized": isMaximized,
"isFullscreen": isFullscreen,
}; };
} }
@ -1418,7 +1420,7 @@ class LastWindowPosition {
try { try {
final m = jsonDecode(content); final m = jsonDecode(content);
return LastWindowPosition(m["width"], m["height"], m["offsetWidth"], return LastWindowPosition(m["width"], m["height"], m["offsetWidth"],
m["offsetHeight"], m["isMaximized"]); m["offsetHeight"], m["isMaximized"], m["isFullscreen"]);
} catch (e) { } catch (e) {
debugPrintStack( debugPrintStack(
label: label:
@ -1439,6 +1441,8 @@ Future<void> saveWindowPosition(WindowType type, {int? windowId}) async {
late Offset position; late Offset position;
late Size sz; late Size sz;
late bool isMaximized; late bool isMaximized;
bool isFullscreen = stateGlobal.fullscreen ||
(Platform.isMacOS && stateGlobal.closeOnFullscreen);
setFrameIfMaximized() { setFrameIfMaximized() {
if (isMaximized) { if (isMaximized) {
final pos = bind.getLocalFlutterOption(k: kWindowPrefix + type.name); final pos = bind.getLocalFlutterOption(k: kWindowPrefix + type.name);
@ -1484,20 +1488,21 @@ Future<void> saveWindowPosition(WindowType type, {int? windowId}) async {
} }
final pos = LastWindowPosition( final pos = LastWindowPosition(
sz.width, sz.height, position.dx, position.dy, isMaximized); sz.width, sz.height, position.dx, position.dy, isMaximized, isFullscreen);
debugPrint( debugPrint(
"Saving frame: $windowId: ${pos.width}/${pos.height}, offset:${pos.offsetWidth}/${pos.offsetHeight}, isMaximized:${pos.isMaximized}"); "Saving frame: $windowId: ${pos.width}/${pos.height}, offset:${pos.offsetWidth}/${pos.offsetHeight}, isMaximized:${pos.isMaximized}, isFullscreen:${pos.isFullscreen}");
await bind.setLocalFlutterOption( await bind.setLocalFlutterOption(
k: kWindowPrefix + type.name, v: pos.toString()); k: kWindowPrefix + type.name, v: pos.toString());
if (type == WindowType.RemoteDesktop && windowId != null) { if (type == WindowType.RemoteDesktop && windowId != null) {
await _saveSessionWindowPosition(type, windowId, isMaximized, pos); await _saveSessionWindowPosition(
type, windowId, isMaximized, isFullscreen, pos);
} }
} }
Future _saveSessionWindowPosition(WindowType windowType, int windowId, Future _saveSessionWindowPosition(WindowType windowType, int windowId,
bool isMaximized, LastWindowPosition pos) async { bool isMaximized, bool isFullscreen, LastWindowPosition pos) async {
final remoteList = await DesktopMultiWindow.invokeMethod( final remoteList = await DesktopMultiWindow.invokeMethod(
windowId, kWindowEventGetRemoteList, null); windowId, kWindowEventGetRemoteList, null);
getPeerPos(String peerId) { getPeerPos(String peerId) {
@ -1510,7 +1515,8 @@ Future _saveSessionWindowPosition(WindowType windowType, int windowId,
lpos?.height ?? pos.offsetHeight, lpos?.height ?? pos.offsetHeight,
lpos?.offsetWidth ?? pos.offsetWidth, lpos?.offsetWidth ?? pos.offsetWidth,
lpos?.offsetHeight ?? pos.offsetHeight, lpos?.offsetHeight ?? pos.offsetHeight,
isMaximized) isMaximized,
isFullscreen)
.toString(); .toString();
} else { } else {
return pos.toString(); return pos.toString();
@ -1700,7 +1706,13 @@ Future<bool> restoreWindowPosition(WindowType type,
await wc.setFrame(frame); await wc.setFrame(frame);
} }
} }
if (lpos.isMaximized == true) { if (lpos.isFullscreen == true) {
await restoreFrame();
// An duration is needed to avoid the window being restored after fullscreen.
Future.delayed(Duration(milliseconds: 300), () async {
stateGlobal.setFullscreen(true);
});
} else if (lpos.isMaximized == true) {
await restoreFrame(); await restoreFrame();
// An duration is needed to avoid the window being restored after maximized. // An duration is needed to avoid the window being restored after maximized.
Future.delayed(Duration(milliseconds: 300), () async { Future.delayed(Duration(milliseconds: 300), () async {

View File

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui; import 'dart:ui' as ui;
@ -109,6 +110,11 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
final sessionId = args['session_id']; final sessionId = args['session_id'];
final tabWindowId = args['tab_window_id']; final tabWindowId = args['tab_window_id'];
windowOnTop(windowId()); windowOnTop(windowId());
if (tabController.length == 0) {
if (Platform.isMacOS && stateGlobal.closeOnFullscreen) {
stateGlobal.setFullscreen(true);
}
}
ConnectionTypeState.init(id); ConnectionTypeState.init(id);
_toolbarState.setShow( _toolbarState.setShow(
bind.mainGetUserDefaultOption(key: 'collapse_toolbar') != 'Y'); bind.mainGetUserDefaultOption(key: 'collapse_toolbar') != 'Y');
@ -410,6 +416,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
void onRemoveId(String id) async { void onRemoveId(String id) async {
if (tabController.state.value.tabs.isEmpty) { if (tabController.state.value.tabs.isEmpty) {
await WindowController.fromWindowId(windowId()).close(); await WindowController.fromWindowId(windowId()).close();
stateGlobal.setFullscreen(false, procWnd: false);
} }
ConnectionTypeState.delete(id); ConnectionTypeState.delete(id);
_update_remote_count(); _update_remote_count();

View File

@ -482,6 +482,8 @@ class WindowActionPanel extends StatefulWidget {
class WindowActionPanelState extends State<WindowActionPanel> class WindowActionPanelState extends State<WindowActionPanel>
with MultiWindowListener, WindowListener { with MultiWindowListener, WindowListener {
final _saveFrameDebounce = Debouncer(delay: Duration(seconds: 1)); final _saveFrameDebounce = Debouncer(delay: Duration(seconds: 1));
Timer? _macOSCheckRestoreTimer;
int _macOSCheckRestoreCounter = 0;
@override @override
void initState() { void initState() {
@ -514,6 +516,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
void dispose() { void dispose() {
DesktopMultiWindow.removeListener(this); DesktopMultiWindow.removeListener(this);
windowManager.removeListener(this); windowManager.removeListener(this);
_macOSCheckRestoreTimer?.cancel();
super.dispose(); super.dispose();
} }
@ -566,6 +569,33 @@ class WindowActionPanelState extends State<WindowActionPanel>
@override @override
void onWindowClose() async { 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<void> Function() restoreFunc,
Future<bool> Function() checkFullscreen,
Future<void> 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: 700), () async => await closeFunc());
}
});
}
// hide window on close // hide window on close
if (widget.isMainWindow) { if (widget.isMainWindow) {
if (rustDeskWinManager.getActiveWindows().contains(kMainWindowId)) { if (rustDeskWinManager.getActiveWindows().contains(kMainWindowId)) {
@ -573,23 +603,28 @@ class WindowActionPanelState extends State<WindowActionPanel>
} }
// macOS specific workaround, the window is not hiding when in fullscreen. // macOS specific workaround, the window is not hiding when in fullscreen.
if (Platform.isMacOS && await windowManager.isFullScreen()) { if (Platform.isMacOS && await windowManager.isFullScreen()) {
await windowManager.setFullScreen(false); stateGlobal.closeOnFullscreen = true;
await Future.delayed(Duration(seconds: 1)); await macOSWindowClose(
() async => await windowManager.setFullScreen(false),
() async => await windowManager.isFullScreen(),
mainWindowClose);
} else {
stateGlobal.closeOnFullscreen = false;
await mainWindowClose();
} }
await windowManager.hide();
} else { } else {
// it's safe to hide the subwindow // it's safe to hide the subwindow
final controller = WindowController.fromWindowId(kWindowId!); final controller = WindowController.fromWindowId(kWindowId!);
if (Platform.isMacOS && await controller.isFullScreen()) { if (Platform.isMacOS && await controller.isFullScreen()) {
await controller.setFullscreen(false); stateGlobal.closeOnFullscreen = true;
await Future.delayed(Duration(seconds: 1)); 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(); super.onWindowClose();
} }

View File

@ -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/mobile/pages/home_page.dart';
import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/platform_model.dart';
import 'package:flutter_hbb/models/state_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:get/get.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';

View File

@ -20,6 +20,8 @@ class StateGlobal {
final RxBool showRemoteToolBar = false.obs; final RxBool showRemoteToolBar = false.obs;
final RxInt displaysCount = 0.obs; final RxInt displaysCount = 0.obs;
final svcStatus = SvcStatus.notReady.obs; final svcStatus = SvcStatus.notReady.obs;
// Only used for macOS
bool closeOnFullscreen = false;
// Use for desktop -> remote toolbar -> resolution // Use for desktop -> remote toolbar -> resolution
final Map<String, Map<int, String?>> _lastResolutionGroupValues = {}; final Map<String, Map<int, String?>> _lastResolutionGroupValues = {};
@ -64,7 +66,7 @@ class StateGlobal {
setMinimized(bool v) => _isMinimized = v; setMinimized(bool v) => _isMinimized = v;
setFullscreen(bool v) { setFullscreen(bool v, {bool procWnd = true}) {
if (_fullscreen != v) { if (_fullscreen != v) {
_fullscreen = v; _fullscreen = v;
_showTabBar.value = !_fullscreen; _showTabBar.value = !_fullscreen;
@ -76,20 +78,22 @@ class StateGlobal {
print( print(
"fullscreen: $fullscreen, resizeEdgeSize: ${_resizeEdgeSize.value}"); "fullscreen: $fullscreen, resizeEdgeSize: ${_resizeEdgeSize.value}");
_windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth; _windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth;
WindowController.fromWindowId(windowId) if (procWnd) {
.setFullscreen(_fullscreen) WindowController.fromWindowId(windowId)
.then((_) { .setFullscreen(_fullscreen)
// https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982 .then((_) {
if (Platform.isWindows && !v) { // https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982
Future.delayed(Duration.zero, () async { if (Platform.isWindows && !v) {
final frame = Future.delayed(Duration.zero, () async {
await WindowController.fromWindowId(windowId).getFrame(); final frame =
final newRect = Rect.fromLTWH( await WindowController.fromWindowId(windowId).getFrame();
frame.left, frame.top, frame.width + 1, frame.height + 1); final newRect = Rect.fromLTWH(
await WindowController.fromWindowId(windowId).setFrame(newRect); frame.left, frame.top, frame.width + 1, frame.height + 1);
}); await WindowController.fromWindowId(windowId).setFrame(newRect);
} });
}); }
});
}
} }
} }