Merge pull request #1976 from Kingtous/master

opt: add window status management to handle exit logic
This commit is contained in:
RustDesk 2022-11-05 23:46:00 +08:00 committed by GitHub
commit ddeaf7fb92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 21 deletions

View File

@ -322,10 +322,12 @@ void window_on_top(int? id) {
windowManager.restore();
windowManager.show();
windowManager.focus();
rustDeskWinManager.registerActiveWindow(0);
} else {
WindowController.fromWindowId(id)
..focus()
..show();
rustDeskWinManager.call(WindowType.Main, kWindowEventShow, {"id": id});
}
}
@ -1360,3 +1362,34 @@ Future<void> reloadAllWindows() async {
// ignore
}
}
/// Indicate the flutter app is running in portable mode.
///
/// [Note]
/// Portable build is only avaliable on Windows.
bool isRunningInPortableMode() {
if (!Platform.isWindows) {
return false;
}
return bool.hasEnvironment(kEnvPortableExecutable);
}
/// Window status callback
void onActiveWindowChanged() async {
print(
"[MultiWindowHandler] active window changed: ${rustDeskWinManager.getActiveWindows()}");
if (rustDeskWinManager.getActiveWindows().isEmpty) {
// close all sub windows
try {
await Future.wait([
saveWindowPosition(WindowType.Main),
rustDeskWinManager.closeAllSubWindows()
]);
} catch (err) {
debugPrint("$err");
} finally {
await windowManager.setPreventClose(false);
await windowManager.close();
}
}
}

View File

@ -10,6 +10,8 @@ const String kAppTypeDesktopFileTransfer = "file transfer";
const String kAppTypeDesktopPortForward = "port forward";
const String kWindowActionRebuild = "rebuild";
const String kWindowEventHide = "hide";
const String kWindowEventShow = "show";
const String kUniLinksPrefix = "rustdesk://";
const String kActionNewConnection = "connection/new/";
@ -19,6 +21,9 @@ const String kTabLabelSettingPage = "Settings";
const String kWindowPrefix = "wm_";
// the executable name of the portable version
const String kEnvPortableExecutable = "RUSTDESK_APPNAME";
const Color kColorWarn = Color.fromARGB(255, 245, 133, 59);
const int kMobileDefaultDisplayWidth = 720;

View File

@ -44,20 +44,9 @@ class _DesktopHomePageState extends State<DesktopHomePage>
@override
void onWindowClose() async {
super.onWindowClose();
// close all sub windows
if (await windowManager.isPreventClose()) {
try {
await Future.wait([
saveWindowPosition(WindowType.Main),
rustDeskWinManager.closeAllSubWindows()
]);
} catch (err) {
debugPrint("$err");
} finally {
await windowManager.setPreventClose(false);
await windowManager.close();
}
}
// hide window on close
await windowManager.hide();
rustDeskWinManager.unregisterActiveWindow(0);
}
@override
@ -437,9 +426,11 @@ class _DesktopHomePageState extends State<DesktopHomePage>
// initTray();
trayManager.addListener(this);
windowManager.addListener(this);
rustDeskWinManager.registerActiveWindowListener(onActiveWindowChanged);
rustDeskWinManager.registerActiveWindow(0);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
debugPrint(
"call ${call.method} with args ${call.arguments} from window $fromWindowId");
"[Main] call ${call.method} with args ${call.arguments} from window $fromWindowId");
if (call.method == "main_window_on_top") {
window_on_top(null);
} else if (call.method == "get_window_info") {
@ -465,6 +456,10 @@ class _DesktopHomePageState extends State<DesktopHomePage>
}
} else if (call.method == kWindowActionRebuild) {
reloadCurrentWindow();
} else if (call.method == kWindowEventShow) {
rustDeskWinManager.registerActiveWindow(call.arguments["id"]);
} else if (call.method == kWindowEventHide) {
rustDeskWinManager.unregisterActiveWindow(call.arguments["id"]);
}
});
Future.delayed(Duration.zero, () {
@ -475,7 +470,8 @@ class _DesktopHomePageState extends State<DesktopHomePage>
@override
void dispose() {
destoryTray();
// destoryTray();
rustDeskWinManager.unregisterActiveWindowListener(onActiveWindowChanged);
trayManager.removeListener(this);
windowManager.removeListener(this);
_uniLinksSubscription?.cancel();

View File

@ -97,6 +97,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
void onRemoveId(String id) {
if (tabController.state.value.tabs.isEmpty) {
WindowController.fromWindowId(windowId()).hide();
rustDeskWinManager.call(WindowType.Main, kWindowEventHide, {"id": windowId()});
}
}

View File

@ -51,7 +51,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
debugPrint(
"call ${call.method} with args ${call.arguments} from window $fromWindowId");
"[Port Forward] call ${call.method} with args ${call.arguments} from window $fromWindowId");
// for simplify, just replace connectionId
if (call.method == "new_port_forward") {
final args = jsonDecode(call.arguments);
@ -108,6 +108,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
void onRemoveId(String id) {
if (tabController.state.value.tabs.isEmpty) {
WindowController.fromWindowId(windowId()).hide();
rustDeskWinManager.call(WindowType.Main, kWindowEventHide, {"id": windowId()});
}
}

View File

@ -73,7 +73,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
print(
"call ${call.method} with args ${call.arguments} from window $fromWindowId");
"[Remote Page] call ${call.method} with args ${call.arguments} from window $fromWindowId");
// for simplify, just replace connectionId
if (call.method == "new_remote_desktop") {
@ -324,6 +324,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
void onRemoveId(String id) {
if (tabController.state.value.tabs.isEmpty) {
WindowController.fromWindowId(windowId()).hide();
rustDeskWinManager.call(WindowType.Main, kWindowEventHide, {"id": windowId()});
}
ConnectionTypeState.delete(id);
_update_remote_count();

View File

@ -541,8 +541,11 @@ class WindowActionPanelState extends State<WindowActionPanel>
Future.delayed(Duration.zero, () async {
if (widget.isMainWindow) {
await windowManager.hide();
rustDeskWinManager.unregisterActiveWindow(0);
} else {
await WindowController.fromWindowId(windowId!).hide();
rustDeskWinManager.call(
WindowType.Main, kWindowEventHide, {"id": windowId!});
}
});
}

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'package:desktop_multi_window/desktop_multi_window.dart';
import 'package:flutter/material.dart';
@ -139,11 +140,30 @@ void runMultiWindow(
String title,
) async {
await initEnv(appType);
late Widget widget;
switch (appType) {
case kAppTypeDesktopRemote:
widget = DesktopRemoteScreen(
params: argument,
);
break;
case kAppTypeDesktopFileTransfer:
widget = DesktopFileTransferScreen(
params: argument,
);
break;
case kAppTypeDesktopPortForward:
widget = DesktopPortForwardScreen(
params: argument,
);
break;
default:
// no such appType
exit(0);
}
_runApp(
title,
DesktopRemoteScreen(
params: argument,
),
widget,
MyTheme.currentThemeMode(),
);
}

View File

@ -33,6 +33,8 @@ class RustDeskMultiWindowManager {
static final instance = RustDeskMultiWindowManager._();
final List<int> _activeWindows = List.empty(growable: true);
final List<VoidCallback> _windowActiveCallbacks = List.empty(growable: true);
int? _remoteDesktopWindowId;
int? _fileTransferWindowId;
int? _portForwardWindowId;
@ -57,6 +59,7 @@ class RustDeskMultiWindowManager {
..center()
..setTitle("rustdesk - remote desktop")
..show();
registerActiveWindow(remoteDesktopController.windowId);
_remoteDesktopWindowId = remoteDesktopController.windowId;
} else {
return call(WindowType.RemoteDesktop, "new_remote_desktop", msg);
@ -82,6 +85,7 @@ class RustDeskMultiWindowManager {
..center()
..setTitle("rustdesk - file transfer")
..show();
registerActiveWindow(fileTransferController.windowId);
_fileTransferWindowId = fileTransferController.windowId;
} else {
return call(WindowType.FileTransfer, "new_file_transfer", msg);
@ -107,6 +111,7 @@ class RustDeskMultiWindowManager {
..center()
..setTitle("rustdesk - port forward")
..show();
registerActiveWindow(portForwardController.windowId);
_portForwardWindowId = portForwardController.windowId;
} else {
return call(WindowType.PortForward, "new_port_forward", msg);
@ -167,6 +172,56 @@ class RustDeskMultiWindowManager {
}
}
}
Future<List<int>> getAllSubWindowIds() async {
try {
final windows = await DesktopMultiWindow.getAllSubWindowIds();
return windows;
} catch (err) {
if (err is AssertionError) {
return [];
} else {
rethrow;
}
}
}
List<int> getActiveWindows() {
return _activeWindows;
}
void _notifyActiveWindow() {
for (final callback in _windowActiveCallbacks) {
callback.call();
}
}
void registerActiveWindow(int windowId) {
if (_activeWindows.contains(windowId)) {
// ignore
} else {
_activeWindows.add(windowId);
_notifyActiveWindow();
}
}
void unregisterActiveWindow(int windowId) {
if (!_activeWindows.contains(windowId)) {
// ignore
} else {
_activeWindows.remove(windowId);
_notifyActiveWindow();
}
}
void registerActiveWindowListener(VoidCallback callback) {
_windowActiveCallbacks.add(callback);
}
void unregisterActiveWindowListener(VoidCallback callback) {
_windowActiveCallbacks.remove(callback);
}
}
final rustDeskWinManager = RustDeskMultiWindowManager.instance;