| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							| 
									
										
										
										
											2023-01-28 09:33:57 +08:00
										 |  |  | import 'dart:io'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import 'package:desktop_multi_window/desktop_multi_window.dart'; | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  | import 'package:flutter/foundation.dart'; | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | import 'package:flutter/services.dart'; | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  | import 'package:flutter_hbb/consts.dart'; | 
					
						
							| 
									
										
										
										
											2022-10-14 19:48:41 +09:00
										 |  |  | import 'package:flutter_hbb/common.dart'; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /// must keep the order
 | 
					
						
							|  |  |  | enum WindowType { Main, RemoteDesktop, FileTransfer, PortForward, Unknown } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extension Index on int { | 
					
						
							|  |  |  |   WindowType get windowType { | 
					
						
							|  |  |  |     switch (this) { | 
					
						
							|  |  |  |       case 0: | 
					
						
							|  |  |  |         return WindowType.Main; | 
					
						
							|  |  |  |       case 1: | 
					
						
							|  |  |  |         return WindowType.RemoteDesktop; | 
					
						
							|  |  |  |       case 2: | 
					
						
							|  |  |  |         return WindowType.FileTransfer; | 
					
						
							|  |  |  |       case 3: | 
					
						
							|  |  |  |         return WindowType.PortForward; | 
					
						
							|  |  |  |       default: | 
					
						
							|  |  |  |         return WindowType.Unknown; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  | class MultiWindowCallResult { | 
					
						
							|  |  |  |   int windowId; | 
					
						
							|  |  |  |   dynamic result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MultiWindowCallResult(this.windowId, this.result); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | /// Window Manager
 | 
					
						
							|  |  |  | /// mainly use it in `Main Window`
 | 
					
						
							|  |  |  | /// use it in sub window is not recommended
 | 
					
						
							|  |  |  | class RustDeskMultiWindowManager { | 
					
						
							|  |  |  |   RustDeskMultiWindowManager._(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static final instance = RustDeskMultiWindowManager._(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |   final Set<int> _inactiveWindows = {}; | 
					
						
							|  |  |  |   final Set<int> _activeWindows = {}; | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   final List<AsyncCallback> _windowActiveCallbacks = List.empty(growable: true); | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |   final List<int> _remoteDesktopWindows = List.empty(growable: true); | 
					
						
							|  |  |  |   final List<int> _fileTransferWindows = List.empty(growable: true); | 
					
						
							|  |  |  |   final List<int> _portForwardWindows = List.empty(growable: true); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-06 11:21:07 +08:00
										 |  |  |   moveTabToNewWindow(int windowId, String peerId, String sessionId) async { | 
					
						
							| 
									
										
										
										
											2023-08-06 10:19:30 +08:00
										 |  |  |     var params = { | 
					
						
							|  |  |  |       'type': WindowType.RemoteDesktop.index, | 
					
						
							|  |  |  |       'id': peerId, | 
					
						
							| 
									
										
										
										
											2023-08-14 20:40:58 +08:00
										 |  |  |       'tab_window_id': windowId, | 
					
						
							| 
									
										
										
										
											2023-08-06 10:19:30 +08:00
										 |  |  |       'session_id': sessionId, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-08-14 20:40:58 +08:00
										 |  |  |     await _newSession( | 
					
						
							| 
									
										
										
										
											2023-08-09 17:17:18 +08:00
										 |  |  |       false, | 
					
						
							| 
									
										
										
										
											2023-08-06 10:19:30 +08:00
										 |  |  |       WindowType.RemoteDesktop, | 
					
						
							|  |  |  |       kWindowEventNewRemoteDesktop, | 
					
						
							|  |  |  |       peerId, | 
					
						
							|  |  |  |       _remoteDesktopWindows, | 
					
						
							|  |  |  |       jsonEncode(params), | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2023-08-03 23:14:40 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |   // This function must be called in the main window thread.
 | 
					
						
							|  |  |  |   // Because the _remoteDesktopWindows is managed in that thread.
 | 
					
						
							| 
									
										
										
										
											2023-10-17 00:30:34 +08:00
										 |  |  |   openMonitorSession(int windowId, String peerId, int display, int displayCount, | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |       Rect? screenRect) async { | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     if (_remoteDesktopWindows.length > 1) { | 
					
						
							|  |  |  |       for (final windowId in _remoteDesktopWindows) { | 
					
						
							|  |  |  |         if (await DesktopMultiWindow.invokeMethod( | 
					
						
							|  |  |  |             windowId, | 
					
						
							|  |  |  |             kWindowEventActiveDisplaySession, | 
					
						
							|  |  |  |             jsonEncode({ | 
					
						
							|  |  |  |               'id': peerId, | 
					
						
							|  |  |  |               'display': display, | 
					
						
							|  |  |  |             }))) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     final displays = display == kAllDisplayValue | 
					
						
							|  |  |  |         ? List.generate(displayCount, (index) => index) | 
					
						
							|  |  |  |         : [display]; | 
					
						
							|  |  |  |     var params = { | 
					
						
							|  |  |  |       'type': WindowType.RemoteDesktop.index, | 
					
						
							|  |  |  |       'id': peerId, | 
					
						
							|  |  |  |       'tab_window_id': windowId, | 
					
						
							|  |  |  |       'display': display, | 
					
						
							|  |  |  |       'displays': displays, | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |     if (screenRect != null) { | 
					
						
							|  |  |  |       params['screen_rect'] = { | 
					
						
							|  |  |  |         'l': screenRect.left, | 
					
						
							|  |  |  |         't': screenRect.top, | 
					
						
							|  |  |  |         'r': screenRect.right, | 
					
						
							|  |  |  |         'b': screenRect.bottom, | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     await _newSession( | 
					
						
							|  |  |  |       false, | 
					
						
							|  |  |  |       WindowType.RemoteDesktop, | 
					
						
							|  |  |  |       kWindowEventNewRemoteDesktop, | 
					
						
							|  |  |  |       peerId, | 
					
						
							|  |  |  |       _remoteDesktopWindows, | 
					
						
							|  |  |  |       jsonEncode(params), | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |       screenRect: screenRect, | 
					
						
							| 
									
										
										
										
											2023-10-08 21:44:54 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<int> newSessionWindow( | 
					
						
							| 
									
										
										
										
											2023-10-17 00:30:34 +08:00
										 |  |  |     WindowType type, | 
					
						
							|  |  |  |     String remoteId, | 
					
						
							|  |  |  |     String msg, | 
					
						
							|  |  |  |     List<int> windows, | 
					
						
							|  |  |  |     bool withScreenRect, | 
					
						
							|  |  |  |   ) async { | 
					
						
							| 
									
										
										
										
											2023-08-03 23:14:40 +08:00
										 |  |  |     final windowController = await DesktopMultiWindow.createWindow(msg); | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |     final windowId = windowController.windowId; | 
					
						
							| 
									
										
										
										
											2023-10-17 00:30:34 +08:00
										 |  |  |     if (!withScreenRect) { | 
					
						
							|  |  |  |       windowController | 
					
						
							|  |  |  |         ..setFrame(const Offset(0, 0) & | 
					
						
							|  |  |  |             Size(1280 + windowId * 20, 720 + windowId * 20)) | 
					
						
							|  |  |  |         ..center() | 
					
						
							|  |  |  |         ..setTitle(getWindowNameWithId( | 
					
						
							|  |  |  |           remoteId, | 
					
						
							|  |  |  |           overrideType: type, | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       windowController.setTitle(getWindowNameWithId( | 
					
						
							| 
									
										
										
										
											2023-08-03 23:14:40 +08:00
										 |  |  |         remoteId, | 
					
						
							|  |  |  |         overrideType: type, | 
					
						
							|  |  |  |       )); | 
					
						
							| 
									
										
										
										
											2023-10-17 00:30:34 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-03 23:14:40 +08:00
										 |  |  |     if (Platform.isMacOS) { | 
					
						
							|  |  |  |       Future.microtask(() => windowController.show()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |     registerActiveWindow(windowId); | 
					
						
							|  |  |  |     windows.add(windowId); | 
					
						
							|  |  |  |     return windowId; | 
					
						
							| 
									
										
										
										
											2023-08-03 23:14:40 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> _newSession( | 
					
						
							| 
									
										
										
										
											2023-08-08 12:12:35 +08:00
										 |  |  |     bool openInTabs, | 
					
						
							| 
									
										
										
										
											2023-08-04 00:17:11 +08:00
										 |  |  |     WindowType type, | 
					
						
							|  |  |  |     String methodName, | 
					
						
							|  |  |  |     String remoteId, | 
					
						
							|  |  |  |     List<int> windows, | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |     String msg, { | 
					
						
							|  |  |  |     Rect? screenRect, | 
					
						
							|  |  |  |   }) async { | 
					
						
							| 
									
										
										
										
											2023-08-08 12:12:35 +08:00
										 |  |  |     if (openInTabs) { | 
					
						
							|  |  |  |       if (windows.isEmpty) { | 
					
						
							| 
									
										
										
										
											2023-10-17 00:30:34 +08:00
										 |  |  |         final windowId = await newSessionWindow( | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |             type, remoteId, msg, windows, screenRect != null); | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |         return MultiWindowCallResult(windowId, null); | 
					
						
							| 
									
										
										
										
											2023-08-08 12:12:35 +08:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |         return call(type, methodName, msg); | 
					
						
							| 
									
										
										
										
											2023-08-08 12:12:35 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (_inactiveWindows.isNotEmpty) { | 
					
						
							| 
									
										
										
										
											2023-08-06 16:47:41 +08:00
										 |  |  |         for (final windowId in windows) { | 
					
						
							|  |  |  |           if (_inactiveWindows.contains(windowId)) { | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |             if (screenRect == null) { | 
					
						
							|  |  |  |               await restoreWindowPosition(type, | 
					
						
							|  |  |  |                   windowId: windowId, peerId: remoteId); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-08-09 18:37:09 +08:00
										 |  |  |             await DesktopMultiWindow.invokeMethod(windowId, methodName, msg); | 
					
						
							| 
									
										
										
										
											2023-08-06 16:47:41 +08:00
										 |  |  |             WindowController.fromWindowId(windowId).show(); | 
					
						
							|  |  |  |             registerActiveWindow(windowId); | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |             return MultiWindowCallResult(windowId, null); | 
					
						
							| 
									
										
										
										
											2023-08-06 16:47:41 +08:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-08-04 00:17:11 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |       final windowId = await newSessionWindow( | 
					
						
							|  |  |  |           type, remoteId, msg, windows, screenRect != null); | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |       return MultiWindowCallResult(windowId, null); | 
					
						
							| 
									
										
										
										
											2023-08-04 00:17:11 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> newSession( | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     WindowType type, | 
					
						
							|  |  |  |     String methodName, | 
					
						
							|  |  |  |     String remoteId, | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |     List<int> windows, { | 
					
						
							| 
									
										
										
										
											2023-03-20 00:16:06 +08:00
										 |  |  |     String? password, | 
					
						
							| 
									
										
										
										
											2023-02-13 16:40:24 +08:00
										 |  |  |     bool? forceRelay, | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     String? switchUuid, | 
					
						
							|  |  |  |     bool? isRDP, | 
					
						
							| 
									
										
										
										
											2023-02-13 16:40:24 +08:00
										 |  |  |   }) async { | 
					
						
							| 
									
										
										
										
											2023-02-01 19:49:41 +08:00
										 |  |  |     var params = { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |       "type": type.index, | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |       "id": remoteId, | 
					
						
							| 
									
										
										
										
											2023-03-20 00:16:06 +08:00
										 |  |  |       "password": password, | 
					
						
							| 
									
										
										
										
											2023-02-13 16:40:24 +08:00
										 |  |  |       "forceRelay": forceRelay | 
					
						
							| 
									
										
										
										
											2023-02-01 19:49:41 +08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     if (switchUuid != null) { | 
					
						
							|  |  |  |       params['switch_uuid'] = switchUuid; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (isRDP != null) { | 
					
						
							|  |  |  |       params['isRDP'] = isRDP; | 
					
						
							| 
									
										
										
										
											2023-02-01 19:49:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     final msg = jsonEncode(params); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     // separate window for file transfer is not supported
 | 
					
						
							| 
									
										
										
										
											2023-08-08 14:22:32 +08:00
										 |  |  |     bool openInTabs = type != WindowType.RemoteDesktop || | 
					
						
							|  |  |  |         mainGetLocalBoolOptionSync(kOptionOpenNewConnInTabs); | 
					
						
							| 
									
										
										
										
											2022-06-17 22:57:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-16 10:47:16 +08:00
										 |  |  |     if (windows.length > 1 || !openInTabs) { | 
					
						
							|  |  |  |       for (final windowId in windows) { | 
					
						
							|  |  |  |         if (await DesktopMultiWindow.invokeMethod( | 
					
						
							|  |  |  |             windowId, kWindowEventActiveSession, remoteId)) { | 
					
						
							|  |  |  |           return MultiWindowCallResult(windowId, null); | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-06-17 22:57:41 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 09:36:08 +08:00
										 |  |  |     return _newSession(openInTabs, type, methodName, remoteId, windows, msg); | 
					
						
							| 
									
										
										
										
											2022-06-17 22:57:41 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> newRemoteDesktop( | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     String remoteId, { | 
					
						
							|  |  |  |     String? password, | 
					
						
							|  |  |  |     String? switchUuid, | 
					
						
							|  |  |  |     bool? forceRelay, | 
					
						
							|  |  |  |   }) async { | 
					
						
							|  |  |  |     return await newSession( | 
					
						
							|  |  |  |       WindowType.RemoteDesktop, | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |       kWindowEventNewRemoteDesktop, | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |       remoteId, | 
					
						
							|  |  |  |       _remoteDesktopWindows, | 
					
						
							|  |  |  |       password: password, | 
					
						
							|  |  |  |       forceRelay: forceRelay, | 
					
						
							|  |  |  |       switchUuid: switchUuid, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> newFileTransfer(String remoteId, | 
					
						
							| 
									
										
										
										
											2023-07-07 12:22:39 +08:00
										 |  |  |       {String? password, bool? forceRelay}) async { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     return await newSession( | 
					
						
							|  |  |  |       WindowType.FileTransfer, | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |       kWindowEventNewFileTransfer, | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |       remoteId, | 
					
						
							|  |  |  |       _fileTransferWindows, | 
					
						
							|  |  |  |       password: password, | 
					
						
							|  |  |  |       forceRelay: forceRelay, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-26 11:35:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> newPortForward(String remoteId, bool isRDP, | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |       {String? password, bool? forceRelay}) async { | 
					
						
							|  |  |  |     return await newSession( | 
					
						
							|  |  |  |       WindowType.PortForward, | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |       kWindowEventNewPortForward, | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |       remoteId, | 
					
						
							|  |  |  |       _portForwardWindows, | 
					
						
							|  |  |  |       password: password, | 
					
						
							|  |  |  |       forceRelay: forceRelay, | 
					
						
							|  |  |  |       isRDP: isRDP, | 
					
						
							|  |  |  |     ); | 
					
						
							| 
									
										
										
										
											2022-08-26 11:35:28 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |   Future<MultiWindowCallResult> call( | 
					
						
							|  |  |  |       WindowType type, String methodName, dynamic args) async { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     final wnds = _findWindowsByType(type); | 
					
						
							|  |  |  |     if (wnds.isEmpty) { | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |       return MultiWindowCallResult(kInvalidWindowId, null); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-05 17:57:12 +08:00
										 |  |  |     for (final windowId in wnds) { | 
					
						
							|  |  |  |       if (_activeWindows.contains(windowId)) { | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |         final res = | 
					
						
							|  |  |  |             await DesktopMultiWindow.invokeMethod(windowId, methodName, args); | 
					
						
							|  |  |  |         return MultiWindowCallResult(windowId, res); | 
					
						
							| 
									
										
										
										
											2023-08-05 17:57:12 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-14 18:28:31 +08:00
										 |  |  |     final res = | 
					
						
							|  |  |  |         await DesktopMultiWindow.invokeMethod(wnds[0], methodName, args); | 
					
						
							|  |  |  |     return MultiWindowCallResult(wnds[0], res); | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |   List<int> _findWindowsByType(WindowType type) { | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |     switch (type) { | 
					
						
							|  |  |  |       case WindowType.Main: | 
					
						
							| 
									
										
										
										
											2023-08-06 10:19:30 +08:00
										 |  |  |         return [kMainWindowId]; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       case WindowType.RemoteDesktop: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         return _remoteDesktopWindows; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       case WindowType.FileTransfer: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         return _fileTransferWindows; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       case WindowType.PortForward: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         return _portForwardWindows; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |       case WindowType.Unknown: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-02 20:38:09 +08:00
										 |  |  |     return []; | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 17:08:40 +08:00
										 |  |  |   void clearWindowType(WindowType type) { | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |       case WindowType.Main: | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       case WindowType.RemoteDesktop: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         _remoteDesktopWindows.clear(); | 
					
						
							| 
									
										
										
										
											2023-02-03 17:08:40 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       case WindowType.FileTransfer: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         _fileTransferWindows.clear(); | 
					
						
							| 
									
										
										
										
											2023-02-03 17:08:40 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       case WindowType.PortForward: | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         _portForwardWindows.clear(); | 
					
						
							| 
									
										
										
										
											2023-02-03 17:08:40 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       case WindowType.Unknown: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  |   void setMethodHandler( | 
					
						
							|  |  |  |       Future<dynamic> Function(MethodCall call, int fromWindowId)? handler) { | 
					
						
							|  |  |  |     DesktopMultiWindow.setMethodHandler(handler); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Future<void> closeAllSubWindows() async { | 
					
						
							|  |  |  |     await Future.wait(WindowType.values.map((e) => closeWindows(e))); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-26 11:35:28 +08:00
										 |  |  |   Future<void> closeWindows(WindowType type) async { | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  |     if (type == WindowType.Main) { | 
					
						
							|  |  |  |       // skip main window, use window manager instead
 | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     List<int> windows = []; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       windows = await DesktopMultiWindow.getAllSubWindowIds(); | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							|  |  |  |       debugPrint('Failed to getAllSubWindowIds of $type, $e'); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (windows.isEmpty) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (final wId in windows) { | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  |       debugPrint("closing multi window: ${type.toString()}"); | 
					
						
							| 
									
										
										
										
											2022-10-27 18:40:45 +08:00
										 |  |  |       await saveWindowPosition(type, windowId: wId); | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  |       try { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         // final ids = await DesktopMultiWindow.getAllSubWindowIds();
 | 
					
						
							|  |  |  |         // if (!ids.contains(wId)) {
 | 
					
						
							|  |  |  |         //   // no such window already
 | 
					
						
							|  |  |  |         //   return;
 | 
					
						
							|  |  |  |         // }
 | 
					
						
							| 
									
										
										
										
											2022-11-06 17:39:19 +08:00
										 |  |  |         await WindowController.fromWindowId(wId).setPreventClose(false); | 
					
						
							| 
									
										
										
										
											2022-08-30 20:48:03 +08:00
										 |  |  |         await WindowController.fromWindowId(wId).close(); | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |         _activeWindows.remove(wId); | 
					
						
							| 
									
										
										
										
											2023-02-03 17:08:40 +08:00
										 |  |  |       } catch (e) { | 
					
						
							|  |  |  |         debugPrint("$e"); | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     await _notifyActiveWindow(); | 
					
						
							|  |  |  |     clearWindowType(type); | 
					
						
							| 
									
										
										
										
											2022-08-09 13:39:30 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Future<List<int>> getAllSubWindowIds() async { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       final windows = await DesktopMultiWindow.getAllSubWindowIds(); | 
					
						
							|  |  |  |       return windows; | 
					
						
							|  |  |  |     } catch (err) { | 
					
						
							|  |  |  |       if (err is AssertionError) { | 
					
						
							|  |  |  |         return []; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         rethrow; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |   Set<int> getActiveWindows() { | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     return _activeWindows; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   Future<void> _notifyActiveWindow() async { | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     for (final callback in _windowActiveCallbacks) { | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |       await callback.call(); | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   Future<void> registerActiveWindow(int windowId) async { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     _activeWindows.add(windowId); | 
					
						
							|  |  |  |     _inactiveWindows.remove(windowId); | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |     await _notifyActiveWindow(); | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |   Future<void> destroyWindow(int windowId) async { | 
					
						
							|  |  |  |     await WindowController.fromWindowId(windowId).setPreventClose(false); | 
					
						
							|  |  |  |     await WindowController.fromWindowId(windowId).close(); | 
					
						
							|  |  |  |     _remoteDesktopWindows.remove(windowId); | 
					
						
							|  |  |  |     _fileTransferWindows.remove(windowId); | 
					
						
							|  |  |  |     _portForwardWindows.remove(windowId); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-06 17:39:19 +08:00
										 |  |  |   /// Remove active window which has [`windowId`]
 | 
					
						
							| 
									
										
										
										
											2023-01-17 13:28:33 +08:00
										 |  |  |   ///
 | 
					
						
							| 
									
										
										
										
											2022-12-25 20:21:13 +03:00
										 |  |  |   /// [Availability]
 | 
					
						
							| 
									
										
										
										
											2022-11-06 17:39:19 +08:00
										 |  |  |   /// This function should only be called from main window.
 | 
					
						
							|  |  |  |   /// For other windows, please post a unregister(hide) event to main window handler:
 | 
					
						
							|  |  |  |   /// `rustDeskWinManager.call(WindowType.Main, kWindowEventHide, {"id": windowId!});`
 | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   Future<void> unregisterActiveWindow(int windowId) async { | 
					
						
							| 
									
										
										
										
											2023-08-01 22:19:38 +08:00
										 |  |  |     _activeWindows.remove(windowId); | 
					
						
							|  |  |  |     if (windowId != kMainWindowId) { | 
					
						
							|  |  |  |       _inactiveWindows.add(windowId); | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |     await _notifyActiveWindow(); | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   void registerActiveWindowListener(AsyncCallback callback) { | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     _windowActiveCallbacks.add(callback); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 20:40:29 -08:00
										 |  |  |   void unregisterActiveWindowListener(AsyncCallback callback) { | 
					
						
							| 
									
										
										
										
											2022-11-05 23:41:22 +08:00
										 |  |  |     _windowActiveCallbacks.remove(callback); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-05-29 17:19:50 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | final rustDeskWinManager = RustDeskMultiWindowManager.instance; |