diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 59d0576a1..65e8611c3 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -39,6 +39,7 @@ const String kWindowEventActiveSession = "active_session"; const String kWindowEventGetRemoteList = "get_remote_list"; const String kWindowEventGetSessionIdList = "get_session_id_list"; +const String kWindowEventSplit = "split"; const String kWindowEventCloseForSeparateWindow = "close_for_separate_window"; const String kOptionSeparateRemoteWindow = "enable-separate-remote-window"; diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 43c73b0b5..34916481c 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -570,6 +570,17 @@ class _DesktopHomePageState extends State forceRelay: call.arguments['forceRelay'], forceSeparateWindow: call.arguments['forceSeparateWindow'], ); + } else if (call.method == kWindowEventSplit) { + final args = call.arguments.split(','); + int? windowId; + try { + windowId = int.parse(args[0]); + } catch (e) { + debugPrint("Failed to parse window id '${call.arguments}': $e"); + } + if (windowId != null) { + await rustDeskWinManager.splitWindow(windowId, args[1], args[2]); + } } }); _uniLinksSubscription = listenUniLinks(); diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 9072643ea..06555bc8d 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/consts.dart'; -import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:flutter_hbb/desktop/pages/desktop_home_page.dart'; import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; import 'package:flutter_hbb/models/platform_model.dart'; @@ -323,13 +322,6 @@ class _GeneralState extends State<_General> { 'Separate remote window', kOptionSeparateRemoteWindow, isServer: false, - update: () { - final useSeparateWindow = - mainGetLocalBoolOptionSync(kOptionSeparateRemoteWindow); - if (useSeparateWindow) { - rustDeskWinManager.separateWindows(); - } - }, ), ]; // though this is related to GUI, but opengl problem affects all users, so put in config rather than local diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 080895729..e4bbeba92 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -329,6 +329,22 @@ class _ConnectionTabPageState extends State { )); } + if (tabController.state.value.tabs.length > 1) { + final splitAction = MenuEntryButton( + childBuilder: (TextStyle? style) => Text( + translate('Split'), + style: style, + ), + proc: () async { + await DesktopMultiWindow.invokeMethod( + kMainWindowId, kWindowEventSplit, '${windowId()},$key,$sessionId'); + cancelFunc(); + }, + padding: padding, + ); + menu.insert(1, splitAction); + } + if (perms['keyboard'] != false && !ffi.ffiModel.viewOnly) { if (perms['clipboard'] != false) { menu.add(RemoteMenuEntry.disableClipboard(sessionId, padding, diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index b0959246b..fb576e426 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -43,33 +43,22 @@ class RustDeskMultiWindowManager { final List _fileTransferWindows = List.empty(growable: true); final List _portForwardWindows = List.empty(growable: true); - separateWindows() async { - for (final windowId in _remoteDesktopWindows.toList()) { - final String sessionIdList = await DesktopMultiWindow.invokeMethod( - windowId, kWindowEventGetSessionIdList, null); - final idList = sessionIdList.split(';'); - if (idList.length <= 1) { - continue; - } - for (final idPair in idList.sublist(1)) { - final peerSession = idPair.split(','); - var params = { - 'type': WindowType.RemoteDesktop.index, - 'id': peerSession[0], - 'session_id': peerSession[1], - }; - await _newSession( - true, - WindowType.RemoteDesktop, - kWindowEventNewRemoteDesktop, - peerSession[0], - _remoteDesktopWindows, - jsonEncode(params), - ); - await DesktopMultiWindow.invokeMethod( - windowId, kWindowEventCloseForSeparateWindow, peerSession[0]); - } - } + splitWindow(int windowId, String peerId, String sessionId) async { + var params = { + 'type': WindowType.RemoteDesktop.index, + 'id': peerId, + 'session_id': sessionId, + }; + await _newSession( + true, + WindowType.RemoteDesktop, + kWindowEventNewRemoteDesktop, + peerId, + _remoteDesktopWindows, + jsonEncode(params), + ); + await DesktopMultiWindow.invokeMethod( + windowId, kWindowEventCloseForSeparateWindow, peerId); } newSessionWindow( @@ -214,7 +203,8 @@ class RustDeskMultiWindowManager { } for (final windowId in wnds) { if (_activeWindows.contains(windowId)) { - return await DesktopMultiWindow.invokeMethod(windowId, methodName, args); + return await DesktopMultiWindow.invokeMethod( + windowId, methodName, args); } } return await DesktopMultiWindow.invokeMethod(wnds[0], methodName, args); @@ -223,7 +213,7 @@ class RustDeskMultiWindowManager { List _findWindowsByType(WindowType type) { switch (type) { case WindowType.Main: - return [0]; + return [kMainWindowId]; case WindowType.RemoteDesktop: return _remoteDesktopWindows; case WindowType.FileTransfer: diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index eee857f60..c24d0f54c 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -125,7 +125,18 @@ impl Remote { .await { Ok((mut peer, direct, pk)) => { - self.handler.set_connection_type(peer.is_secured(), direct); // flutter -> connection_ready + let is_secured = peer.is_secured(); + #[cfg(feature = "flutter")] + #[cfg(not(any(target_os = "android", target_os = "ios")))] + { + self.handler + .cache_flutter + .write() + .unwrap() + .is_secured_direct + .replace((is_secured, direct)); + } + self.handler.set_connection_type(is_secured, direct); // flutter -> connection_ready self.handler.update_direct(Some(direct)); if conn_type == ConnType::DEFAULT_CONN { self.handler diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 326ef5dd0..d285805f5 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index f52cb9b61..3e93a7869 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "对标签进行排序"), ("Separate remote window", "使用独立远程窗口"), ("separate window", "独立窗口"), + ("Split", "拆分"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index a61c46001..8bc165f40 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index c3f43b7f1..c44973bbf 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index e59eb63d6..24a59d4fc 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "Tags sortieren"), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 83160cae7..ccfd1c8ec 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 47792961a..9cc79a98a 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index b57474793..2d33c5756 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "Ordenar etiquetas"), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 6f2531b46..f57687e53 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 679620a99..bab0ef06b 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 8eacb75d3..02b0ed900 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 2d12c31e5..608b00cd1 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 5118adc16..d1c71c385 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "Ordina etichette"), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index ed09d6132..e5328f332 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index d48347023..05f003f63 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 1bcadec64..634654dc6 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index accdf9a39..bdc8c9e24 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index b1bcd1d2a..d4868b401 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "Labels sorteren"), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 1d813ef41..8aa9525ab 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 6b32a1e48..196f1e5c3 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index c732dd2af..53c91b3c6 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 4db68ee50..f3cc62202 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 9dcef1a48..c44335f69 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", "Сортировка меток"), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 3f8d57169..0c7e5f2d8 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index e3c17a659..ff0c0114d 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 46db68578..261d5fa5a 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 370865e0a..9ce8e4c3f 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 3ec8535ef..72b3f3243 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 7eb168fdf..82fcec792 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index f125384de..b17f432d0 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index b4959b158..c2467ce5d 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index cda76a154..c705665ae 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 8d46b61ae..879dd9d94 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index c188e2d14..52fef05d4 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -526,5 +526,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Sort tags", ""), ("Separate remote window", ""), ("separate window", ""), + ("Split", ""), ].iter().cloned().collect(); } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 21b9c9d9e..704b91cf0 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -56,6 +56,7 @@ pub struct CacheFlutter { pub sp: Option, pub cursor_data: HashMap, pub cursor_id: u64, + pub is_secured_direct: Option<(bool, bool)>, } #[derive(Clone, Default)] @@ -1198,6 +1199,9 @@ impl Session { #[cfg(feature = "flutter")] #[cfg(not(any(target_os = "android", target_os = "ios")))] pub fn restore_flutter_cache(&mut self) { + if let Some((is_secured, direct)) = self.cache_flutter.read().unwrap().is_secured_direct { + self.set_connection_type(is_secured, direct); + } let pi = self.cache_flutter.read().unwrap().pi.clone(); self.handle_peer_info(pi); if let Some(sp) = self.cache_flutter.read().unwrap().sp.as_ref() {