Merge pull request #5625 from dignow/feat/remember_remote_window_fullscreen
Feat/remember remote window fullscreen
This commit is contained in:
commit
065c19cbbc
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
|
@ -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);
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user