From bf83d552f8fc901c1e2fe04e6cefacfac4883d61 Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 00:30:34 +0800 Subject: [PATCH 1/8] feat, open multi windows Signed-off-by: dignow --- flutter/lib/common.dart | 112 +++++++++++++++++- flutter/lib/consts.dart | 2 + .../lib/desktop/pages/desktop_home_page.dart | 44 +++---- .../desktop/pages/desktop_setting_page.dart | 2 + .../lib/desktop/pages/remote_tab_page.dart | 39 ++++-- .../lib/desktop/widgets/remote_toolbar.dart | 34 +----- flutter/lib/main.dart | 7 +- flutter/lib/models/model.dart | 51 +++++++- flutter/lib/utils/multi_window_manager.dart | 41 +++++-- libs/hbb_common/src/config.rs | 13 ++ src/client.rs | 13 +- src/flutter_ffi.rs | 43 ++++++- src/lang/ar.rs | 1 + src/lang/ca.rs | 1 + src/lang/cn.rs | 1 + src/lang/cs.rs | 1 + src/lang/da.rs | 1 + src/lang/el.rs | 1 + src/lang/eo.rs | 1 + src/lang/es.rs | 1 + src/lang/fa.rs | 1 + src/lang/fr.rs | 1 + src/lang/hu.rs | 1 + src/lang/id.rs | 1 + src/lang/it.rs | 1 + src/lang/ja.rs | 1 + src/lang/ko.rs | 1 + src/lang/kz.rs | 1 + src/lang/lt.rs | 1 + src/lang/lv.rs | 1 + src/lang/nl.rs | 1 + src/lang/pl.rs | 1 + src/lang/pt_PT.rs | 1 + src/lang/ptbr.rs | 1 + src/lang/ro.rs | 1 + src/lang/sk.rs | 1 + src/lang/sl.rs | 1 + src/lang/sq.rs | 1 + src/lang/sr.rs | 1 + src/lang/sv.rs | 1 + src/lang/template.rs | 1 + src/lang/th.rs | 1 + src/lang/tr.rs | 1 + src/lang/tw.rs | 1 + src/lang/ua.rs | 1 + src/lang/vn.rs | 1 + src/ui_session_interface.rs | 8 ++ 47 files changed, 363 insertions(+), 80 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 1da2dc60a..a67aa27fe 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -14,8 +14,8 @@ import 'package:flutter/services.dart'; import 'package:flutter_hbb/common/formatter/id_formatter.dart'; import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart'; import 'package:flutter_hbb/desktop/widgets/tabbar_widget.dart'; -import 'package:flutter_hbb/models/desktop_render_texture.dart'; import 'package:flutter_hbb/main.dart'; +import 'package:flutter_hbb/models/desktop_render_texture.dart'; import 'package:flutter_hbb/models/peer_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; @@ -53,6 +53,9 @@ int androidVersion = 0; int windowsBuildNumber = 0; DesktopType? desktopType; +bool get isMainDesktopWindow => + desktopType == DesktopType.main || desktopType == DesktopType.cm; + /// Check if the app is running with single view mode. bool isSingleViewApp() { return desktopType == DesktopType.cm; @@ -1672,6 +1675,7 @@ Future _adjustRestoreMainWindowOffset( /// Note that windowId must be provided if it's subwindow Future restoreWindowPosition(WindowType type, {int? windowId, String? peerId}) async { + debugPrintStack(label: "restoreWindowPosition"); if (bind .mainGetEnv(key: "DISABLE_RUSTDESK_RESTORE_WINDOW_POSITION") .isNotEmpty) { @@ -2605,3 +2609,109 @@ bool isChooseDisplayToOpenInNewWindow(PeerInfo pi, SessionID sessionId) => pi.isSupportMultiDisplay && useTextureRender && bind.sessionGetDisplaysAsIndividualWindows(sessionId: sessionId) == 'Y'; + +Future> getScreenListWayland() async { + final screenRectList = []; + if (isMainDesktopWindow) { + for (var screen in await window_size.getScreenList()) { + final scale = kIgnoreDpi ? 1.0 : screen.scaleFactor; + double l = screen.frame.left; + double t = screen.frame.top; + double r = screen.frame.right; + double b = screen.frame.bottom; + final rect = Rect.fromLTRB(l / scale, t / scale, r / scale, b / scale); + screenRectList.add(rect); + } + } else { + final screenList = await rustDeskWinManager.call( + WindowType.Main, kWindowGetScreenList, ''); + try { + for (var screen in jsonDecode(screenList.result) as List) { + final scale = kIgnoreDpi ? 1.0 : screen['scaleFactor']; + double l = screen['frame']['l']; + double t = screen['frame']['t']; + double r = screen['frame']['r']; + double b = screen['frame']['b']; + final rect = Rect.fromLTRB(l / scale, t / scale, r / scale, b / scale); + screenRectList.add(rect); + } + } catch (e) { + debugPrint('Failed to parse screenList: $e'); + } + } + return screenRectList; +} + +Future> getScreenListNotWayland() async { + final screenRectList = []; + final displays = bind.mainGetDisplays(); + if (displays.isEmpty) { + return screenRectList; + } + try { + for (var display in jsonDecode(displays) as List) { + // to-do: scale factor ? + // final scale = kIgnoreDpi ? 1.0 : screen.scaleFactor; + double l = display['x'].toDouble(); + double t = display['y'].toDouble(); + double r = (display['x'] + display['w']).toDouble(); + double b = (display['y'] + display['h']).toDouble(); + screenRectList.add(Rect.fromLTRB(l, t, r, b)); + } + } catch (e) { + debugPrint('Failed to parse displays: $e'); + } + return screenRectList; +} + +Future> getScreenRectList() async { + return bind.mainCurrentIsWayland() + ? await getScreenListWayland() + : await getScreenListNotWayland(); +} + +openMonitorInTheSameTab(int i, FFI ffi, PeerInfo pi) { + final displays = i == kAllDisplayValue + ? List.generate(pi.displays.length, (index) => index) + : [i]; + bind.sessionSwitchDisplay( + sessionId: ffi.sessionId, value: Int32List.fromList(displays)); + ffi.ffiModel.switchToNewDisplay(i, ffi.sessionId, ffi.id); +} + +// Open new tab or window to show this monitor. +// For now just open new window. +// +// screenRect is used to move the new window to the specified screen and set fullscreen. +openMonitorInNewTabOrWindow(int i, String peerId, PeerInfo pi, + {Rect? screenRect}) { + final args = { + 'window_id': stateGlobal.windowId, + 'peer_id': peerId, + 'display': i, + 'display_count': pi.displays.length, + }; + if (screenRect != null) { + args['screen_rect'] = { + 'l': screenRect.left, + 't': screenRect.top, + 'r': screenRect.right, + 'b': screenRect.bottom, + }; + } + DesktopMultiWindow.invokeMethod( + kMainWindowId, kWindowEventOpenMonitorSession, jsonEncode(args)); +} + +tryMoveToScreenAndSetFullscreen(Rect? screenRect) async { + if (screenRect == null) { + return; + } + final frame = + Rect.fromLTWH(screenRect.left + 30, screenRect.top + 30, 600, 400); + await WindowController.fromWindowId(stateGlobal.windowId).setFrame(frame); + // An duration is needed to avoid the window being restored after fullscreen. + Future.delayed(Duration(milliseconds: 300), () async { + stateGlobal.setFullscreen(true); + }); +} diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index d92f42a10..8a562f5a1 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -29,6 +29,7 @@ const String kAppTypeDesktopPortForward = "port forward"; const String kWindowMainWindowOnTop = "main_window_on_top"; const String kWindowGetWindowInfo = "get_window_info"; +const String kWindowGetScreenList = "get_screen_list"; const String kWindowDisableGrabKeyboard = "disable_grab_keyboard"; const String kWindowActionRebuild = "rebuild"; const String kWindowEventHide = "hide"; @@ -65,6 +66,7 @@ const String kPointerEventKindTouch = "touch"; const String kPointerEventKindMouse = "mouse"; const String kKeyShowDisplaysAsIndividualWindows = 'displays_as_individual_windows'; +const String kKeyUseAllMyMonitorsWhenConnecting = 'use_all_my_monitors_when_connecting'; const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar'; // the executable name of the portable version diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index 8ea872c6c..a06c81ad2 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -329,8 +329,7 @@ class _DesktopHomePageState extends State "Click to download", () async { final Uri url = Uri.parse('https://rustdesk.com/download'); await launchUrl(url); - }, - closeButton: true); + }, closeButton: true); } if (systemError.isNotEmpty) { return buildInstallCard("", systemError, "", () {}); @@ -397,7 +396,6 @@ class _DesktopHomePageState extends State Widget buildInstallCard(String title, String content, String btnText, GestureTapCallback onPressed, {String? help, String? link, bool? closeButton}) { - void closeCard() { setState(() { isCardClosed = true; @@ -555,6 +553,22 @@ class _DesktopHomePageState extends State Get.put(svcStopped, tag: 'stop-service'); rustDeskWinManager.registerActiveWindowListener(onActiveWindowChanged); + screenToMap(window_size.Screen screen) => { + 'frame': { + 'l': screen.frame.left, + 't': screen.frame.top, + 'r': screen.frame.right, + 'b': screen.frame.bottom, + }, + 'visibleFrame': { + 'l': screen.visibleFrame.left, + 't': screen.visibleFrame.top, + 'r': screen.visibleFrame.right, + 'b': screen.visibleFrame.bottom, + }, + 'scaleFactor': screen.scaleFactor, + }; + rustDeskWinManager.setMethodHandler((call, fromWindowId) async { debugPrint( "[Main] call ${call.method} with args ${call.arguments} from window $fromWindowId"); @@ -563,24 +577,13 @@ class _DesktopHomePageState extends State } else if (call.method == kWindowGetWindowInfo) { final screen = (await window_size.getWindowInfo()).screen; if (screen == null) { - return ""; + return ''; } else { - return jsonEncode({ - 'frame': { - 'l': screen.frame.left, - 't': screen.frame.top, - 'r': screen.frame.right, - 'b': screen.frame.bottom, - }, - 'visibleFrame': { - 'l': screen.visibleFrame.left, - 't': screen.visibleFrame.top, - 'r': screen.visibleFrame.right, - 'b': screen.visibleFrame.bottom, - }, - 'scaleFactor': screen.scaleFactor, - }); + return jsonEncode(screenToMap(screen)); } + } else if (call.method == kWindowGetScreenList) { + return jsonEncode( + (await window_size.getScreenList()).map(screenToMap).toList()); } else if (call.method == kWindowActionRebuild) { reloadCurrentWindow(); } else if (call.method == kWindowEventShow) { @@ -613,8 +616,9 @@ class _DesktopHomePageState extends State final peerId = args['peer_id'] as String; final display = args['display'] as int; final displayCount = args['display_count'] as int; + final screenRect = args['screen_rect']; await rustDeskWinManager.openMonitorSession( - windowId, peerId, display, displayCount); + windowId, peerId, display, displayCount, screenRect); } }); _uniLinksSubscription = listenUniLinks(); diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index f74535047..517114aea 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1324,6 +1324,8 @@ class _DisplayState extends State<_Display> { if (useTextureRender) { children.add(otherRow('Show displays as individual windows', kKeyShowDisplaysAsIndividualWindows)); + children.add(otherRow('Use all my displays when connecting', + kKeyUseAllMyMonitorsWhenConnecting)); } return _Card(title: 'Other Default Options', children: children); } diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index 0cc23b39a..d2f117db5 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -48,6 +48,7 @@ class _ConnectionTabPageState extends State { late ToolbarState _toolbarState; String? peerId; + bool isScreenRectSet = false; var connectionMap = RxList.empty(growable: true); @@ -59,6 +60,9 @@ class _ConnectionTabPageState extends State { final tabWindowId = params['tab_window_id']; final display = params['display']; final displays = params['displays']; + final screenRect = parseScreenRect(params); + isScreenRectSet = screenRect != null; + tryMoveToScreenAndSetFullscreen(screenRect); if (peerId != null) { ConnectionTypeState.init(peerId!); tabController.onSelected = (id) { @@ -95,6 +99,18 @@ class _ConnectionTabPageState extends State { } } + parseScreenRect(Map params) { + Rect? screenRect; + if (params['screen_rect'] != null) { + double l = params['screen_rect']['l']; + double t = params['screen_rect']['t']; + double r = params['screen_rect']['r']; + double b = params['screen_rect']['b']; + screenRect = Rect.fromLTRB(l, t, r, b); + } + return screenRect; + } + @override void initState() { super.initState(); @@ -115,7 +131,9 @@ class _ConnectionTabPageState extends State { final tabWindowId = args['tab_window_id']; final display = args['display']; final displays = args['displays']; + final screenRect = parseScreenRect(args); windowOnTop(windowId()); + tryMoveToScreenAndSetFullscreen(screenRect); if (tabController.length == 0) { if (Platform.isMacOS && stateGlobal.closeOnFullscreen) { stateGlobal.setFullscreen(true); @@ -196,15 +214,17 @@ class _ConnectionTabPageState extends State { _update_remote_count(); return returnValue; }); - Future.delayed(Duration.zero, () { - restoreWindowPosition( - WindowType.RemoteDesktop, - windowId: windowId(), - peerId: tabController.state.value.tabs.isEmpty - ? null - : tabController.state.value.tabs[0].key, - ); - }); + if (!isScreenRectSet) { + Future.delayed(Duration.zero, () { + restoreWindowPosition( + WindowType.RemoteDesktop, + windowId: windowId(), + peerId: tabController.state.value.tabs.isEmpty + ? null + : tabController.state.value.tabs[0].key, + ); + }); + } } @override @@ -451,6 +471,7 @@ class _ConnectionTabPageState extends State { c++; } } + loopCloseWindow(); } ConnectionTypeState.delete(id); diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 92038f68b..4065ebfb2 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -1,12 +1,10 @@ import 'dart:convert'; import 'dart:async'; import 'dart:io'; -import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hbb/common/widgets/toolbar.dart'; -import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/state_model.dart'; import 'package:flutter_hbb/models/desktop_render_texture.dart'; @@ -744,42 +742,14 @@ class _MonitorMenu extends StatelessWidget { ); } - // Open new tab or window to show this monitor. - // For now just open new window. - openMonitorInNewTabOrWindow(int i, PeerInfo pi) { - if (kWindowId == null) { - // unreachable - debugPrint('openMonitorInNewTabOrWindow, unreachable! kWindowId is null'); - return; - } - DesktopMultiWindow.invokeMethod( - kMainWindowId, - kWindowEventOpenMonitorSession, - jsonEncode({ - 'window_id': kWindowId!, - 'peer_id': ffi.id, - 'display': i, - 'display_count': pi.displays.length, - })); - } - - openMonitorInTheSameTab(int i, PeerInfo pi) { - final displays = i == kAllDisplayValue - ? List.generate(pi.displays.length, (index) => index) - : [i]; - bind.sessionSwitchDisplay( - sessionId: ffi.sessionId, value: Int32List.fromList(displays)); - ffi.ffiModel.switchToNewDisplay(i, ffi.sessionId, id); - } - onPressed(int i, PeerInfo pi) { _menuDismissCallback(ffi); RxInt display = CurrentDisplayState.find(id); if (display.value != i) { if (isChooseDisplayToOpenInNewWindow(pi, ffi.sessionId)) { - openMonitorInNewTabOrWindow(i, pi); + openMonitorInNewTabOrWindow(i, ffi.id, pi); } else { - openMonitorInTheSameTab(i, pi); + openMonitorInTheSameTab(i, ffi, pi); } } } diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index ef44a3bcc..59cf97345 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -198,8 +198,11 @@ void runMultiWindow( } switch (appType) { case kAppTypeDesktopRemote: - await restoreWindowPosition(WindowType.RemoteDesktop, - windowId: kWindowId!, peerId: argument['id'] as String?); + // If screen rect is set, the window will be moved to the target screen and then set fullscreen. + if (argument['screen_rect'] == null) { + await restoreWindowPosition(WindowType.RemoteDesktop, + windowId: kWindowId!, peerId: argument['id'] as String?); + } break; case kAppTypeDesktopFileTransfer: await restoreWindowPosition(WindowType.FileTransfer, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 56e18d309..127410761 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -227,7 +227,7 @@ class FfiModel with ChangeNotifier { }, sessionId, peerId); updatePrivacyMode(data.updatePrivacyMode, sessionId, peerId); setConnectionType(peerId, data.secure, data.direct); - await handlePeerInfo(data.peerInfo, peerId); + await handlePeerInfo(data.peerInfo, peerId, true); for (final element in data.cursorDataList) { updateLastCursorId(element); await handleCursorData(element); @@ -245,7 +245,7 @@ class FfiModel with ChangeNotifier { if (name == 'msgbox') { handleMsgBox(evt, sessionId, peerId); } else if (name == 'peer_info') { - handlePeerInfo(evt, peerId); + handlePeerInfo(evt, peerId, false); } else if (name == 'sync_peer_info') { handleSyncPeerInfo(evt, sessionId, peerId); } else if (name == 'connection_ready') { @@ -623,7 +623,7 @@ class FfiModel with ChangeNotifier { } /// Handle the peer info event based on [evt]. - handlePeerInfo(Map evt, String peerId) async { + handlePeerInfo(Map evt, String peerId, bool isCache) async { cachedPeerData.peerInfo = evt; // recent peer updated by handle_peer_info(ui_session_interface.rs) --> handle_peer_info(client.rs) --> save_config(client.rs) @@ -703,6 +703,51 @@ class FfiModel with ChangeNotifier { stateGlobal.resetLastResolutionGroupValues(peerId); notifyListeners(); + + if (!isCache) { + tryUseAllMyDisplaysWhenConnecting(peerId); + } + } + + tryUseAllMyDisplaysWhenConnecting(String peerId) async { + if (bind.mainGetUserDefaultOption( + key: kKeyUseAllMyMonitorsWhenConnecting) != + 'Y') { + return; + } + + if (!_pi.isSupportMultiDisplay || _pi.displays.length <= 1) { + return; + } + + final screenRectList = await getScreenRectList(); + if (screenRectList.length <= 1) { + return; + } + + // to-do: peer currentDisplay is the primary display, but the primary display may not be the first display. + // local primary display also may not be the first display. + // + // 0 is assumed to be the primary display here, for now. + + // move to the first display and set fullscreen + bind.sessionSwitchDisplay( + sessionId: sessionId, value: Int32List.fromList([0])); + _pi.currentDisplay = 0; + try { + CurrentDisplayState.find(peerId).value = _pi.currentDisplay; + } catch (e) { + // + } + await tryMoveToScreenAndSetFullscreen(screenRectList[0]); + + final length = _pi.displays.length < screenRectList.length + ? _pi.displays.length + : screenRectList.length; + for (var i = 1; i < length; i++) { + openMonitorInNewTabOrWindow(i, peerId, _pi, + screenRect: screenRectList[i]); + } } tryShowAndroidActionsOverlay({int delayMSecs = 10}) { diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index f36370e40..3c3e03627 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -64,13 +64,14 @@ class RustDeskMultiWindowManager { peerId, _remoteDesktopWindows, jsonEncode(params), + false, ); } // This function must be called in the main window thread. // Because the _remoteDesktopWindows is managed in that thread. - openMonitorSession( - int windowId, String peerId, int display, int displayCount) async { + openMonitorSession(int windowId, String peerId, int display, int displayCount, + dynamic screenRect) async { if (_remoteDesktopWindows.length > 1) { for (final windowId in _remoteDesktopWindows) { if (await DesktopMultiWindow.invokeMethod( @@ -94,6 +95,7 @@ class RustDeskMultiWindowManager { 'tab_window_id': windowId, 'display': display, 'displays': displays, + 'screen_rect': screenRect, }; await _newSession( false, @@ -102,21 +104,34 @@ class RustDeskMultiWindowManager { peerId, _remoteDesktopWindows, jsonEncode(params), + screenRect != null, ); } Future newSessionWindow( - WindowType type, String remoteId, String msg, List windows) async { + WindowType type, + String remoteId, + String msg, + List windows, + bool withScreenRect, + ) async { final windowController = await DesktopMultiWindow.createWindow(msg); final windowId = windowController.windowId; - windowController - ..setFrame( - const Offset(0, 0) & Size(1280 + windowId * 20, 720 + windowId * 20)) - ..center() - ..setTitle(getWindowNameWithId( + 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( remoteId, overrideType: type, )); + } if (Platform.isMacOS) { Future.microtask(() => windowController.show()); } @@ -132,10 +147,12 @@ class RustDeskMultiWindowManager { String remoteId, List windows, String msg, + bool withScreenRect, ) async { if (openInTabs) { if (windows.isEmpty) { - final windowId = await newSessionWindow(type, remoteId, msg, windows); + final windowId = await newSessionWindow( + type, remoteId, msg, windows, withScreenRect); return MultiWindowCallResult(windowId, null); } else { return call(type, methodName, msg); @@ -153,7 +170,8 @@ class RustDeskMultiWindowManager { } } } - final windowId = await newSessionWindow(type, remoteId, msg, windows); + final windowId = + await newSessionWindow(type, remoteId, msg, windows, withScreenRect); return MultiWindowCallResult(windowId, null); } } @@ -195,7 +213,8 @@ class RustDeskMultiWindowManager { } } - return _newSession(openInTabs, type, methodName, remoteId, windows, msg); + return _newSession( + openInTabs, type, methodName, remoteId, windows, msg, false); } Future newRemoteDesktop( diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 02f3c719e..09f5a3f35 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -290,6 +290,12 @@ pub struct PeerConfig { skip_serializing_if = "String::is_empty" )] pub displays_as_individual_windows: String, + #[serde( + default = "PeerConfig::default_use_all_my_monitors_when_connecting", + deserialize_with = "PeerConfig::deserialize_use_all_my_monitors_when_connecting", + skip_serializing_if = "String::is_empty" + )] + pub use_all_my_monitors_when_connecting: String, #[serde( default, @@ -335,6 +341,8 @@ impl Default for PeerConfig { view_only: Default::default(), reverse_mouse_wheel: Self::default_reverse_mouse_wheel(), displays_as_individual_windows: Self::default_displays_as_individual_windows(), + use_all_my_monitors_when_connecting: Self::default_use_all_my_monitors_when_connecting( + ), custom_resolutions: Default::default(), options: Self::default_options(), ui_flutter: Default::default(), @@ -1156,6 +1164,11 @@ impl PeerConfig { deserialize_displays_as_individual_windows, UserDefaultConfig::read().get("displays_as_individual_windows") ); + serde_field_string!( + default_use_all_my_monitors_when_connecting, + deserialize_use_all_my_monitors_when_connecting, + UserDefaultConfig::read().get("use_all_my_monitors_when_connecting") + ); fn default_custom_image_quality() -> Vec { let f: f64 = UserDefaultConfig::read() diff --git a/src/client.rs b/src/client.rs index 445aaf225..c2cdfc1e9 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1207,7 +1207,7 @@ impl LoginConfigHandler { self.save_config(config); } - /// Save reverse mouse wheel ("", "Y") to the current config. + /// Save "displays_as_individual_windows" ("", "Y") to the current config. /// /// # Arguments /// @@ -1218,6 +1218,17 @@ impl LoginConfigHandler { self.save_config(config); } + /// Save "use_all_my_monitors_when_connecting" ("", "Y") to the current config. + /// + /// # Arguments + /// + /// * `value` - The "use_all_my_monitors_when_connecting" value ("", "Y"). + pub fn save_use_all_my_monitors_when_connecting(&mut self, value: String) { + let mut config = self.load_config(); + config.use_all_my_monitors_when_connecting = value; + self.save_config(config); + } + /// Save scroll style to the current config. /// /// # Arguments diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index ea6ae1180..19b83590c 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -339,7 +339,9 @@ pub fn session_set_reverse_mouse_wheel(session_id: SessionID, value: String) { } } -pub fn session_get_displays_as_individual_windows(session_id: SessionID) -> SyncReturn> { +pub fn session_get_displays_as_individual_windows( + session_id: SessionID, +) -> SyncReturn> { if let Some(session) = sessions::get_session_by_session_id(&session_id) { SyncReturn(Some(session.get_displays_as_individual_windows())) } else { @@ -353,6 +355,22 @@ pub fn session_set_displays_as_individual_windows(session_id: SessionID, value: } } +pub fn session_get_use_all_my_monitors_when_connecting( + session_id: SessionID, +) -> SyncReturn> { + if let Some(session) = sessions::get_session_by_session_id(&session_id) { + SyncReturn(Some(session.get_use_all_my_monitors_when_connecting())) + } else { + SyncReturn(None) + } +} + +pub fn session_set_use_all_my_monitors_when_connecting(session_id: SessionID, value: String) { + if let Some(session) = sessions::get_session_by_session_id(&session_id) { + session.save_use_all_my_monitors_when_connecting(value); + } +} + pub fn session_get_custom_image_quality(session_id: SessionID) -> Option> { if let Some(session) = sessions::get_session_by_session_id(&session_id) { Some(session.get_custom_image_quality()) @@ -1069,6 +1087,29 @@ pub fn main_get_main_display() -> SyncReturn { SyncReturn(display_info) } +pub fn main_get_displays() -> SyncReturn { + #[cfg(target_os = "ios")] + let display_info = "".to_owned(); + #[cfg(not(target_os = "ios"))] + let mut display_info = "".to_owned(); + #[cfg(not(target_os = "ios"))] + if let Ok(displays) = crate::display_service::try_get_displays() { + let displays = displays + .iter() + .map(|d| { + HashMap::from([ + ("x", d.origin().0), + ("y", d.origin().1), + ("w", d.width() as i32), + ("h", d.height() as i32), + ]) + }) + .collect::>(); + display_info = serde_json::to_string(&displays).unwrap_or_default(); + } + SyncReturn(display_info) +} + pub fn session_add_port_forward( session_id: SessionID, local_port: i32, diff --git a/src/lang/ar.rs b/src/lang/ar.rs index e30621c21..a5568fef9 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index e70c2c044..02c0b3ca6 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index ba2796157..c6db2a09c 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "切换到主显示器,因为提权后,不支持多显示器画面。"), ("Open in new window", "在新的窗口中打开"), ("Show displays as individual windows", "在单个窗口中打开显示器"), + ("Use all my displays when connecting", "建立连接时使用我的所有显示器"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 8907e78e0..c31cfa8bf 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 9d76b8e2e..a4704d069 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 472b494e7..309082e11 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index ccc674749..b5dbc92f3 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 1b1b83afa..870afce91 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index ff90b0430..19993de22 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 2195d4fdd..cc0442ae3 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 24ac09d05..6f6c0fb18 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 892381374..8e170cb61 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Pindah ke tampilan utama, pada mode elevasi, pengggunaan lebih dari satu layar tidak diizinkan"), ("Open in new window", "Buka di jendela baru"), ("Show displays as individual windows", "Tampilkan dengan jendela terpisah"), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index cb7ed922c..fe07c0fb8 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -565,5 +565,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Passo allo schermo principale perché in modalità elevata non sono supportati più schermi."), ("Open in new window", "Apri in una nuova finestra"), ("Show displays as individual windows", "Visualizza schermi come finestre individuali"), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index eeed3e147..95c8333d3 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index dcf28718a..2f26b530a 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 43c36e32c..6b5260284 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 02d4714c2..2b325d5e0 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index 1af747f23..bd9e91e94 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Pārslēdzieties uz primāro displeju, jo paaugstinātajā režīmā netiek atbalstīti vairāki displeji."), ("Open in new window", "Atvērt jaunā logā"), ("Show displays as individual windows", "Rādīt displejus kā atsevišķus logus"), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 71d1c1107..190aa7713 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 88dc5cda5..1f8bf2e79 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Przełącz się na ekran główny, ponieważ wyświetlanie kilku ekranów nie jest obsługiwane przy podniesionych uprawnieniach."), ("Open in new window", "Otwórz w nowym oknie"), ("Show displays as individual windows", "Pokaż ekrany w osobnych oknach"), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 85863d2ae..31d9a4214 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index be4cdfd8e..7a2e8288e 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 311a13bec..faa5efb56 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 23751b734..68003f11d 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 8f84b181a..10e8d1625 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 3d26b5635..bbccd4bde 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 03f4776b7..37ed82a3a 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index ce2dab684..ff6edc549 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 04d3d53ef..811cac31a 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 75afe0324..f66130741 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index e51cff3db..b1e79d93e 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index c70cf8f35..1da5f2e43 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 94e0bc423..7ffc00d8b 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 895e7491a..4d377a6e9 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -564,5 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), + ("Use all my displays when connecting", ""), ].iter().cloned().collect(); } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 0eea85173..37e933927 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -240,6 +240,10 @@ impl Session { self.lc.read().unwrap().displays_as_individual_windows.clone() } + pub fn get_use_all_my_monitors_when_connecting(&self) -> String { + self.lc.read().unwrap().use_all_my_monitors_when_connecting.clone() + } + pub fn save_reverse_mouse_wheel(&self, value: String) { self.lc.write().unwrap().save_reverse_mouse_wheel(value); } @@ -248,6 +252,10 @@ impl Session { self.lc.write().unwrap().save_displays_as_individual_windows(value); } + pub fn save_use_all_my_monitors_when_connecting(&self, value: String) { + self.lc.write().unwrap().save_use_all_my_monitors_when_connecting(value); + } + pub fn save_view_style(&self, value: String) { self.lc.write().unwrap().save_view_style(value); } From 19945df0b3da4b8ac3cc7565239c1a40820979cf Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 07:43:12 +0800 Subject: [PATCH 2/8] open_multi_windows, check before move and set fullscreen Signed-off-by: dignow --- flutter/lib/common.dart | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index a67aa27fe..c7c11da96 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1675,7 +1675,6 @@ Future _adjustRestoreMainWindowOffset( /// Note that windowId must be provided if it's subwindow Future restoreWindowPosition(WindowType type, {int? windowId, String? peerId}) async { - debugPrintStack(label: "restoreWindowPosition"); if (bind .mainGetEnv(key: "DISABLE_RUSTDESK_RESTORE_WINDOW_POSITION") .isNotEmpty) { @@ -2707,9 +2706,18 @@ tryMoveToScreenAndSetFullscreen(Rect? screenRect) async { if (screenRect == null) { return; } + final wc = WindowController.fromWindowId(stateGlobal.windowId); + final curFrame = await wc.getFrame(); final frame = Rect.fromLTWH(screenRect.left + 30, screenRect.top + 30, 600, 400); - await WindowController.fromWindowId(stateGlobal.windowId).setFrame(frame); + if (stateGlobal.fullscreen && + curFrame.left <= frame.left && + curFrame.top <= frame.top && + curFrame.width >= frame.width && + curFrame.height >= frame.height) { + return; + } + await wc.setFrame(frame); // An duration is needed to avoid the window being restored after fullscreen. Future.delayed(Duration(milliseconds: 300), () async { stateGlobal.setFullscreen(true); From af906fac031eb0e387cbdc00b837cb474effa38f Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 09:36:08 +0800 Subject: [PATCH 3/8] debug, open multi windows Signed-off-by: dignow --- flutter/lib/common.dart | 12 +++++++ .../lib/desktop/pages/desktop_home_page.dart | 2 +- .../lib/desktop/pages/remote_tab_page.dart | 16 ++------- flutter/lib/models/state_model.dart | 10 +++--- flutter/lib/utils/multi_window_manager.dart | 35 +++++++++++-------- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index c7c11da96..7fd80d863 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -2723,3 +2723,15 @@ tryMoveToScreenAndSetFullscreen(Rect? screenRect) async { stateGlobal.setFullscreen(true); }); } + +parseParamScreenRect(Map params) { + Rect? screenRect; + if (params['screen_rect'] != null) { + double l = params['screen_rect']['l']; + double t = params['screen_rect']['t']; + double r = params['screen_rect']['r']; + double b = params['screen_rect']['b']; + screenRect = Rect.fromLTRB(l, t, r, b); + } + return screenRect; +} diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index a06c81ad2..8633af1d3 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -616,7 +616,7 @@ class _DesktopHomePageState extends State final peerId = args['peer_id'] as String; final display = args['display'] as int; final displayCount = args['display_count'] as int; - final screenRect = args['screen_rect']; + final screenRect = parseParamScreenRect(args); await rustDeskWinManager.openMonitorSession( windowId, peerId, display, displayCount, screenRect); } diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index d2f117db5..6d28d967f 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -60,7 +60,7 @@ class _ConnectionTabPageState extends State { final tabWindowId = params['tab_window_id']; final display = params['display']; final displays = params['displays']; - final screenRect = parseScreenRect(params); + final screenRect = parseParamScreenRect(params); isScreenRectSet = screenRect != null; tryMoveToScreenAndSetFullscreen(screenRect); if (peerId != null) { @@ -99,18 +99,6 @@ class _ConnectionTabPageState extends State { } } - parseScreenRect(Map params) { - Rect? screenRect; - if (params['screen_rect'] != null) { - double l = params['screen_rect']['l']; - double t = params['screen_rect']['t']; - double r = params['screen_rect']['r']; - double b = params['screen_rect']['b']; - screenRect = Rect.fromLTRB(l, t, r, b); - } - return screenRect; - } - @override void initState() { super.initState(); @@ -131,7 +119,7 @@ class _ConnectionTabPageState extends State { final tabWindowId = args['tab_window_id']; final display = args['display']; final displays = args['displays']; - final screenRect = parseScreenRect(args); + final screenRect = parseParamScreenRect(args); windowOnTop(windowId()); tryMoveToScreenAndSetFullscreen(screenRect); if (tabController.length == 0) { diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 2403a794c..e6744ff77 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -78,17 +78,15 @@ class StateGlobal { "fullscreen: $fullscreen, resizeEdgeSize: ${_resizeEdgeSize.value}"); _windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth; if (procWnd) { - WindowController.fromWindowId(windowId) - .setFullscreen(_fullscreen) - .then((_) { + final wc = WindowController.fromWindowId(windowId); + wc.setFullscreen(_fullscreen).then((_) { // https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982 if (Platform.isWindows && !v) { Future.delayed(Duration.zero, () async { - final frame = - await WindowController.fromWindowId(windowId).getFrame(); + final frame = await wc.getFrame(); final newRect = Rect.fromLTWH( frame.left, frame.top, frame.width + 1, frame.height + 1); - await WindowController.fromWindowId(windowId).setFrame(newRect); + await wc.setFrame(newRect); }); } }); diff --git a/flutter/lib/utils/multi_window_manager.dart b/flutter/lib/utils/multi_window_manager.dart index 3c3e03627..b8edeb3e4 100644 --- a/flutter/lib/utils/multi_window_manager.dart +++ b/flutter/lib/utils/multi_window_manager.dart @@ -64,14 +64,13 @@ class RustDeskMultiWindowManager { peerId, _remoteDesktopWindows, jsonEncode(params), - false, ); } // This function must be called in the main window thread. // Because the _remoteDesktopWindows is managed in that thread. openMonitorSession(int windowId, String peerId, int display, int displayCount, - dynamic screenRect) async { + Rect? screenRect) async { if (_remoteDesktopWindows.length > 1) { for (final windowId in _remoteDesktopWindows) { if (await DesktopMultiWindow.invokeMethod( @@ -95,8 +94,15 @@ class RustDeskMultiWindowManager { 'tab_window_id': windowId, 'display': display, 'displays': displays, - 'screen_rect': screenRect, }; + if (screenRect != null) { + params['screen_rect'] = { + 'l': screenRect.left, + 't': screenRect.top, + 'r': screenRect.right, + 'b': screenRect.bottom, + }; + } await _newSession( false, WindowType.RemoteDesktop, @@ -104,7 +110,7 @@ class RustDeskMultiWindowManager { peerId, _remoteDesktopWindows, jsonEncode(params), - screenRect != null, + screenRect: screenRect, ); } @@ -146,13 +152,13 @@ class RustDeskMultiWindowManager { String methodName, String remoteId, List windows, - String msg, - bool withScreenRect, - ) async { + String msg, { + Rect? screenRect, + }) async { if (openInTabs) { if (windows.isEmpty) { final windowId = await newSessionWindow( - type, remoteId, msg, windows, withScreenRect); + type, remoteId, msg, windows, screenRect != null); return MultiWindowCallResult(windowId, null); } else { return call(type, methodName, msg); @@ -161,8 +167,10 @@ class RustDeskMultiWindowManager { if (_inactiveWindows.isNotEmpty) { for (final windowId in windows) { if (_inactiveWindows.contains(windowId)) { - await restoreWindowPosition(type, - windowId: windowId, peerId: remoteId); + if (screenRect == null) { + await restoreWindowPosition(type, + windowId: windowId, peerId: remoteId); + } await DesktopMultiWindow.invokeMethod(windowId, methodName, msg); WindowController.fromWindowId(windowId).show(); registerActiveWindow(windowId); @@ -170,8 +178,8 @@ class RustDeskMultiWindowManager { } } } - final windowId = - await newSessionWindow(type, remoteId, msg, windows, withScreenRect); + final windowId = await newSessionWindow( + type, remoteId, msg, windows, screenRect != null); return MultiWindowCallResult(windowId, null); } } @@ -213,8 +221,7 @@ class RustDeskMultiWindowManager { } } - return _newSession( - openInTabs, type, methodName, remoteId, windows, msg, false); + return _newSession(openInTabs, type, methodName, remoteId, windows, msg); } Future newRemoteDesktop( From e997b148e11f70fab52bd089b851cd5d65253cc3 Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 13:16:42 +0800 Subject: [PATCH 4/8] Change option text Signed-off-by: dignow --- flutter/lib/desktop/pages/desktop_setting_page.dart | 2 +- src/lang/ar.rs | 2 +- src/lang/ca.rs | 2 +- src/lang/cn.rs | 2 +- src/lang/cs.rs | 2 +- src/lang/da.rs | 2 +- src/lang/el.rs | 2 +- src/lang/eo.rs | 2 +- src/lang/es.rs | 2 +- src/lang/fa.rs | 2 +- src/lang/fr.rs | 2 +- src/lang/hu.rs | 2 +- src/lang/id.rs | 2 +- src/lang/it.rs | 2 +- src/lang/ja.rs | 2 +- src/lang/ko.rs | 2 +- src/lang/kz.rs | 2 +- src/lang/lt.rs | 2 +- src/lang/lv.rs | 2 +- src/lang/nl.rs | 2 +- src/lang/pl.rs | 2 +- src/lang/pt_PT.rs | 2 +- src/lang/ptbr.rs | 2 +- src/lang/ro.rs | 2 +- src/lang/sk.rs | 2 +- src/lang/sl.rs | 2 +- src/lang/sq.rs | 2 +- src/lang/sr.rs | 2 +- src/lang/sv.rs | 2 +- src/lang/template.rs | 2 +- src/lang/th.rs | 2 +- src/lang/tr.rs | 2 +- src/lang/tw.rs | 2 +- src/lang/ua.rs | 2 +- src/lang/vn.rs | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 517114aea..42c75a70a 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1324,7 +1324,7 @@ class _DisplayState extends State<_Display> { if (useTextureRender) { children.add(otherRow('Show displays as individual windows', kKeyShowDisplaysAsIndividualWindows)); - children.add(otherRow('Use all my displays when connecting', + children.add(otherRow('Use all my displays for the remote session', kKeyUseAllMyMonitorsWhenConnecting)); } return _Card(title: 'Other Default Options', children: children); diff --git a/src/lang/ar.rs b/src/lang/ar.rs index a5568fef9..4b80047d5 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 02c0b3ca6..bd62b21c7 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index c6db2a09c..2893eb9a5 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "切换到主显示器,因为提权后,不支持多显示器画面。"), ("Open in new window", "在新的窗口中打开"), ("Show displays as individual windows", "在单个窗口中打开显示器"), - ("Use all my displays when connecting", "建立连接时使用我的所有显示器"), + ("Use all my displays for the remote session", "将我的所有显示器用于远程会话"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index c31cfa8bf..3ba2c4a23 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index a4704d069..2f1076fd1 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 309082e11..940889e16 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index b5dbc92f3..8685fa567 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 870afce91..30bee3ace 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 19993de22..845cb1868 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index cc0442ae3..9f1954f7d 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 6f6c0fb18..882663b7e 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 8e170cb61..7122f7845 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Pindah ke tampilan utama, pada mode elevasi, pengggunaan lebih dari satu layar tidak diizinkan"), ("Open in new window", "Buka di jendela baru"), ("Show displays as individual windows", "Tampilkan dengan jendela terpisah"), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index fe07c0fb8..129d10eb6 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -565,6 +565,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Passo allo schermo principale perché in modalità elevata non sono supportati più schermi."), ("Open in new window", "Apri in una nuova finestra"), ("Show displays as individual windows", "Visualizza schermi come finestre individuali"), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 95c8333d3..059b355db 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 2f26b530a..0a7affb3b 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 6b5260284..73fc04469 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 2b325d5e0..39747e0d4 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index bd9e91e94..09eef383b 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Pārslēdzieties uz primāro displeju, jo paaugstinātajā režīmā netiek atbalstīti vairāki displeji."), ("Open in new window", "Atvērt jaunā logā"), ("Show displays as individual windows", "Rādīt displejus kā atsevišķus logus"), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 190aa7713..6eee21410 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 1f8bf2e79..91c508aaa 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", "Przełącz się na ekran główny, ponieważ wyświetlanie kilku ekranów nie jest obsługiwane przy podniesionych uprawnieniach."), ("Open in new window", "Otwórz w nowym oknie"), ("Show displays as individual windows", "Pokaż ekrany w osobnych oknach"), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 31d9a4214..9c3c01660 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 7a2e8288e..9b052947f 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index faa5efb56..61d44813d 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 68003f11d..b124aed71 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 10e8d1625..e1bf2ab8e 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index bbccd4bde..1d9b218a6 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 37ed82a3a..754192fc3 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index ff6edc549..007e180bb 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 811cac31a..f14c3e206 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index f66130741..bb13d82b6 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index b1e79d93e..394b9bca9 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 1da5f2e43..cdc900ae2 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 7ffc00d8b..7bdea72d6 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 4d377a6e9..0e0cf6a05 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -564,6 +564,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("elevated_switch_display_msg", ""), ("Open in new window", ""), ("Show displays as individual windows", ""), - ("Use all my displays when connecting", ""), + ("Use all my displays for the remote session", ""), ].iter().cloned().collect(); } From f1d3a553d172ff6e0a213823ab33ef8047d10263 Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 13:57:06 +0800 Subject: [PATCH 5/8] open multi windows, add remote toolbar option Signed-off-by: dignow --- flutter/lib/common/widgets/toolbar.dart | 15 +++++++++++++++ flutter/lib/consts.dart | 2 +- .../lib/desktop/pages/desktop_setting_page.dart | 2 +- flutter/lib/models/model.dart | 8 ++++---- libs/hbb_common/src/config.rs | 14 +++++++------- src/client.rs | 8 ++++---- src/flutter_ffi.rs | 8 ++++---- src/ui_session_interface.rs | 8 ++++---- 8 files changed, 40 insertions(+), 25 deletions(-) diff --git a/flutter/lib/common/widgets/toolbar.dart b/flutter/lib/common/widgets/toolbar.dart index ebaff8954..757a03fec 100644 --- a/flutter/lib/common/widgets/toolbar.dart +++ b/flutter/lib/common/widgets/toolbar.dart @@ -535,5 +535,20 @@ Future> toolbarDisplayToggle( child: Text(translate('Show displays as individual windows')))); } + final screenList = await getScreenRectList(); + if (useTextureRender && pi.isSupportMultiDisplay && screenList.length > 1) { + final value = bind.sessionGetUseAllMyDisplaysForTheRemoteSession( + sessionId: ffi.sessionId) == + 'Y'; + v.add(TToggleMenu( + value: value, + onChanged: (value) { + if (value == null) return; + bind.sessionSetUseAllMyDisplaysForTheRemoteSession( + sessionId: sessionId, value: value ? 'Y' : ''); + }, + child: Text(translate('Use all my displays for the remote session')))); + } + return v; } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 8a562f5a1..9f0a5b56f 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -66,7 +66,7 @@ const String kPointerEventKindTouch = "touch"; const String kPointerEventKindMouse = "mouse"; const String kKeyShowDisplaysAsIndividualWindows = 'displays_as_individual_windows'; -const String kKeyUseAllMyMonitorsWhenConnecting = 'use_all_my_monitors_when_connecting'; +const String kKeyUseAllMyDisplaysForTheRemoteSession = 'use_all_my_displays_for_the_remote_session'; const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar'; // the executable name of the portable version diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 42c75a70a..416cbaa5e 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1325,7 +1325,7 @@ class _DisplayState extends State<_Display> { children.add(otherRow('Show displays as individual windows', kKeyShowDisplaysAsIndividualWindows)); children.add(otherRow('Use all my displays for the remote session', - kKeyUseAllMyMonitorsWhenConnecting)); + kKeyUseAllMyDisplaysForTheRemoteSession)); } return _Card(title: 'Other Default Options', children: children); } diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 127410761..fb2b96d62 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -705,13 +705,13 @@ class FfiModel with ChangeNotifier { notifyListeners(); if (!isCache) { - tryUseAllMyDisplaysWhenConnecting(peerId); + tryUseAllMyDisplaysForTheRemoteSession(peerId); } } - tryUseAllMyDisplaysWhenConnecting(String peerId) async { - if (bind.mainGetUserDefaultOption( - key: kKeyUseAllMyMonitorsWhenConnecting) != + tryUseAllMyDisplaysForTheRemoteSession(String peerId) async { + if (bind.sessionGetUseAllMyDisplaysForTheRemoteSession( + sessionId: sessionId) != 'Y') { return; } diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 09f5a3f35..82867ad73 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -291,11 +291,11 @@ pub struct PeerConfig { )] pub displays_as_individual_windows: String, #[serde( - default = "PeerConfig::default_use_all_my_monitors_when_connecting", - deserialize_with = "PeerConfig::deserialize_use_all_my_monitors_when_connecting", + default = "PeerConfig::default_use_all_my_displays_for_the_remote_session", + deserialize_with = "PeerConfig::deserialize_use_all_my_displays_for_the_remote_session", skip_serializing_if = "String::is_empty" )] - pub use_all_my_monitors_when_connecting: String, + pub use_all_my_displays_for_the_remote_session: String, #[serde( default, @@ -341,7 +341,7 @@ impl Default for PeerConfig { view_only: Default::default(), reverse_mouse_wheel: Self::default_reverse_mouse_wheel(), displays_as_individual_windows: Self::default_displays_as_individual_windows(), - use_all_my_monitors_when_connecting: Self::default_use_all_my_monitors_when_connecting( + use_all_my_displays_for_the_remote_session: Self::default_use_all_my_displays_for_the_remote_session( ), custom_resolutions: Default::default(), options: Self::default_options(), @@ -1165,9 +1165,9 @@ impl PeerConfig { UserDefaultConfig::read().get("displays_as_individual_windows") ); serde_field_string!( - default_use_all_my_monitors_when_connecting, - deserialize_use_all_my_monitors_when_connecting, - UserDefaultConfig::read().get("use_all_my_monitors_when_connecting") + default_use_all_my_displays_for_the_remote_session, + deserialize_use_all_my_displays_for_the_remote_session, + UserDefaultConfig::read().get("use_all_my_displays_for_the_remote_session") ); fn default_custom_image_quality() -> Vec { diff --git a/src/client.rs b/src/client.rs index c2cdfc1e9..da4559c99 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1218,14 +1218,14 @@ impl LoginConfigHandler { self.save_config(config); } - /// Save "use_all_my_monitors_when_connecting" ("", "Y") to the current config. + /// Save "use_all_my_displays_for_the_remote_session" ("", "Y") to the current config. /// /// # Arguments /// - /// * `value` - The "use_all_my_monitors_when_connecting" value ("", "Y"). - pub fn save_use_all_my_monitors_when_connecting(&mut self, value: String) { + /// * `value` - The "use_all_my_displays_for_the_remote_session" value ("", "Y"). + pub fn save_use_all_my_displays_for_the_remote_session(&mut self, value: String) { let mut config = self.load_config(); - config.use_all_my_monitors_when_connecting = value; + config.use_all_my_displays_for_the_remote_session = value; self.save_config(config); } diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 19b83590c..fda3247b9 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -355,19 +355,19 @@ pub fn session_set_displays_as_individual_windows(session_id: SessionID, value: } } -pub fn session_get_use_all_my_monitors_when_connecting( +pub fn session_get_use_all_my_displays_for_the_remote_session( session_id: SessionID, ) -> SyncReturn> { if let Some(session) = sessions::get_session_by_session_id(&session_id) { - SyncReturn(Some(session.get_use_all_my_monitors_when_connecting())) + SyncReturn(Some(session.get_use_all_my_displays_for_the_remote_session())) } else { SyncReturn(None) } } -pub fn session_set_use_all_my_monitors_when_connecting(session_id: SessionID, value: String) { +pub fn session_set_use_all_my_displays_for_the_remote_session(session_id: SessionID, value: String) { if let Some(session) = sessions::get_session_by_session_id(&session_id) { - session.save_use_all_my_monitors_when_connecting(value); + session.save_use_all_my_displays_for_the_remote_session(value); } } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 37e933927..991691886 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -240,8 +240,8 @@ impl Session { self.lc.read().unwrap().displays_as_individual_windows.clone() } - pub fn get_use_all_my_monitors_when_connecting(&self) -> String { - self.lc.read().unwrap().use_all_my_monitors_when_connecting.clone() + pub fn get_use_all_my_displays_for_the_remote_session(&self) -> String { + self.lc.read().unwrap().use_all_my_displays_for_the_remote_session.clone() } pub fn save_reverse_mouse_wheel(&self, value: String) { @@ -252,8 +252,8 @@ impl Session { self.lc.write().unwrap().save_displays_as_individual_windows(value); } - pub fn save_use_all_my_monitors_when_connecting(&self, value: String) { - self.lc.write().unwrap().save_use_all_my_monitors_when_connecting(value); + pub fn save_use_all_my_displays_for_the_remote_session(&self, value: String) { + self.lc.write().unwrap().save_use_all_my_displays_for_the_remote_session(value); } pub fn save_view_style(&self, value: String) { From f9f463e7995a0a9fa52586dd032766ccd3e9cba4 Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 14:29:14 +0800 Subject: [PATCH 6/8] fix, use RxBool to sync fullscreen state (remote toolbar) Signed-off-by: dignow --- flutter/lib/common.dart | 4 ++-- flutter/lib/consts.dart | 3 ++- .../lib/desktop/widgets/remote_toolbar.dart | 16 +++++++-------- flutter/lib/models/state_model.dart | 20 +++++++++---------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 7fd80d863..545b8a238 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1494,7 +1494,7 @@ Future saveWindowPosition(WindowType type, {int? windowId}) async { late Offset position; late Size sz; late bool isMaximized; - bool isFullscreen = stateGlobal.fullscreen || + bool isFullscreen = stateGlobal.fullscreen.isTrue || (Platform.isMacOS && stateGlobal.closeOnFullscreen); setFrameIfMaximized() { if (isMaximized) { @@ -2710,7 +2710,7 @@ tryMoveToScreenAndSetFullscreen(Rect? screenRect) async { final curFrame = await wc.getFrame(); final frame = Rect.fromLTWH(screenRect.left + 30, screenRect.top + 30, 600, 400); - if (stateGlobal.fullscreen && + if (stateGlobal.fullscreen.isTrue && curFrame.left <= frame.left && curFrame.top <= frame.top && curFrame.width >= frame.width && diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 9f0a5b56f..e4d777ccb 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/models/state_model.dart'; +import 'package:get/get.dart'; const double kDesktopRemoteTabBarHeight = 28.0; const int kInvalidWindowId = -1; @@ -88,7 +89,7 @@ const double kDesktopFileTransferHeaderHeight = 25.0; EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && Platform.isLinux - ? stateGlobal.fullscreen || stateGlobal.isMaximized.value + ? stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.value ? EdgeInsets.zero : EdgeInsets.all(5.0) : EdgeInsets.zero; diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 4065ebfb2..7439ed6c8 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -351,7 +351,6 @@ class _RemoteToolbarState extends State { int get windowId => stateGlobal.windowId; - bool get isFullscreen => stateGlobal.fullscreen; void _setFullscreen(bool v) { stateGlobal.setFullscreen(v); setState(() {}); @@ -797,7 +796,7 @@ class ScreenAdjustor { required this.cbExitFullscreen, }); - bool get isFullscreen => stateGlobal.fullscreen; + bool get isFullscreen => stateGlobal.fullscreen.isTrue; int get windowId => stateGlobal.windowId; adjustWindow(BuildContext context) { @@ -951,7 +950,6 @@ class _DisplayMenuState extends State<_DisplayMenu> { cbExitFullscreen: () => widget.setFullscreen(false), ); - bool get isFullscreen => stateGlobal.fullscreen; int get windowId => stateGlobal.windowId; Map get perms => widget.ffi.ffiModel.permissions; PeerInfo get pi => widget.ffi.ffiModel.pi; @@ -2060,21 +2058,21 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { mainAxisSize: MainAxisSize.min, children: [ _buildDraggable(context), - TextButton( + Obx(()=>TextButton( onPressed: () { - widget.setFullscreen(!isFullscreen); + widget.setFullscreen(!isFullscreen.value); setState(() {}); }, child: Tooltip( - message: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'), + message: translate(isFullscreen.isTrue ? 'Exit Fullscreen' : 'Fullscreen'), child: Icon( - isFullscreen ? Icons.fullscreen_exit : Icons.fullscreen, + isFullscreen.isTrue ? Icons.fullscreen_exit : Icons.fullscreen, size: iconSize, ), ), - ), + )), Offstage( - offstage: !isFullscreen, + offstage: !isFullscreen.value, child: TextButton( onPressed: () => widget.setMinimize(), child: Tooltip( diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index e6744ff77..82176c1a0 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -11,7 +11,7 @@ enum SvcStatus { notReady, connecting, ready } class StateGlobal { int _windowId = -1; bool grabKeyboard = false; - bool _fullscreen = false; + RxBool _fullscreen = false.obs; bool _isMinimized = false; final RxBool isMaximized = false.obs; final RxBool _showTabBar = true.obs; @@ -26,9 +26,9 @@ class StateGlobal { final Map> _lastResolutionGroupValues = {}; int get windowId => _windowId; - bool get fullscreen => _fullscreen; + RxBool get fullscreen => _fullscreen; bool get isMinimized => _isMinimized; - double get tabBarHeight => fullscreen ? 0 : kDesktopRemoteTabBarHeight; + double get tabBarHeight => fullscreen.isTrue ? 0 : kDesktopRemoteTabBarHeight; RxBool get showTabBar => _showTabBar; RxDouble get resizeEdgeSize => _resizeEdgeSize; RxDouble get windowBorderWidth => _windowBorderWidth; @@ -51,7 +51,7 @@ class StateGlobal { setWindowId(int id) => _windowId = id; setMaximized(bool v) { - if (!_fullscreen) { + if (!_fullscreen.isTrue) { if (isMaximized.value != v) { isMaximized.value = v; _resizeEdgeSize.value = @@ -66,20 +66,20 @@ class StateGlobal { setMinimized(bool v) => _isMinimized = v; setFullscreen(bool v, {bool procWnd = true}) { - if (_fullscreen != v) { - _fullscreen = v; - _showTabBar.value = !_fullscreen; - _resizeEdgeSize.value = fullscreen + if (_fullscreen.value != v) { + _fullscreen.value = v; + _showTabBar.value = !_fullscreen.value; + _resizeEdgeSize.value = fullscreen.isTrue ? kFullScreenEdgeSize : isMaximized.isTrue ? kMaximizeEdgeSize : kWindowEdgeSize; print( "fullscreen: $fullscreen, resizeEdgeSize: ${_resizeEdgeSize.value}"); - _windowBorderWidth.value = fullscreen ? 0 : kWindowBorderWidth; + _windowBorderWidth.value = fullscreen.isTrue ? 0 : kWindowBorderWidth; if (procWnd) { final wc = WindowController.fromWindowId(windowId); - wc.setFullscreen(_fullscreen).then((_) { + wc.setFullscreen(_fullscreen.isTrue).then((_) { // https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982 if (Platform.isWindows && !v) { Future.delayed(Duration.zero, () async { From b2404809fc98579ab19a5a49a5cfca3e6250338f Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 14:31:04 +0800 Subject: [PATCH 7/8] trivial, add final Signed-off-by: dignow --- flutter/lib/models/state_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index 82176c1a0..4afd77db2 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -11,7 +11,7 @@ enum SvcStatus { notReady, connecting, ready } class StateGlobal { int _windowId = -1; bool grabKeyboard = false; - RxBool _fullscreen = false.obs; + final RxBool _fullscreen = false.obs; bool _isMinimized = false; final RxBool isMaximized = false.obs; final RxBool _showTabBar = true.obs; From fdfeec54d72903c14967af7c43ca6af7a9abbeba Mon Sep 17 00:00:00 2001 From: dignow Date: Tue, 17 Oct 2023 14:42:35 +0800 Subject: [PATCH 8/8] Remove the unnecessary setState, as RxBool is used Signed-off-by: dignow --- .../lib/desktop/widgets/remote_toolbar.dart | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 7439ed6c8..88638f0b1 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -353,7 +353,8 @@ class _RemoteToolbarState extends State { void _setFullscreen(bool v) { stateGlobal.setFullscreen(v); - setState(() {}); + // stateGlobal.fullscreen is RxBool now, no need to call setState. + // setState(() {}); } RxBool get show => widget.state.show; @@ -2058,32 +2059,34 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { mainAxisSize: MainAxisSize.min, children: [ _buildDraggable(context), - Obx(()=>TextButton( - onPressed: () { - widget.setFullscreen(!isFullscreen.value); - setState(() {}); - }, - child: Tooltip( - message: translate(isFullscreen.isTrue ? 'Exit Fullscreen' : 'Fullscreen'), - child: Icon( - isFullscreen.isTrue ? Icons.fullscreen_exit : Icons.fullscreen, - size: iconSize, - ), - ), - )), - Offstage( - offstage: !isFullscreen.value, - child: TextButton( - onPressed: () => widget.setMinimize(), - child: Tooltip( - message: translate('Minimize'), - child: Icon( - Icons.remove, - size: iconSize, + Obx(() => TextButton( + onPressed: () { + widget.setFullscreen(!isFullscreen.value); + }, + child: Tooltip( + message: translate( + isFullscreen.isTrue ? 'Exit Fullscreen' : 'Fullscreen'), + child: Icon( + isFullscreen.isTrue + ? Icons.fullscreen_exit + : Icons.fullscreen, + size: iconSize, + ), ), - ), - ), - ), + )), + Obx(() => Offstage( + offstage: isFullscreen.isFalse, + child: TextButton( + onPressed: () => widget.setMinimize(), + child: Tooltip( + message: translate('Minimize'), + child: Icon( + Icons.remove, + size: iconSize, + ), + ), + ), + )), TextButton( onPressed: () => setState(() { widget.show.value = !widget.show.value;