Merge pull request #6064 from dignow/feat/open_multi_windows
Feat/open multi windows
This commit is contained in:
commit
63591941b8
@ -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;
|
||||
@ -1491,7 +1494,7 @@ Future<void> 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) {
|
||||
@ -2605,3 +2608,130 @@ bool isChooseDisplayToOpenInNewWindow(PeerInfo pi, SessionID sessionId) =>
|
||||
pi.isSupportMultiDisplay &&
|
||||
useTextureRender &&
|
||||
bind.sessionGetDisplaysAsIndividualWindows(sessionId: sessionId) == 'Y';
|
||||
|
||||
Future<List<Rect>> getScreenListWayland() async {
|
||||
final screenRectList = <Rect>[];
|
||||
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<dynamic>) {
|
||||
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<List<Rect>> getScreenListNotWayland() async {
|
||||
final screenRectList = <Rect>[];
|
||||
final displays = bind.mainGetDisplays();
|
||||
if (displays.isEmpty) {
|
||||
return screenRectList;
|
||||
}
|
||||
try {
|
||||
for (var display in jsonDecode(displays) as List<dynamic>) {
|
||||
// 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<List<Rect>> 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 wc = WindowController.fromWindowId(stateGlobal.windowId);
|
||||
final curFrame = await wc.getFrame();
|
||||
final frame =
|
||||
Rect.fromLTWH(screenRect.left + 30, screenRect.top + 30, 600, 400);
|
||||
if (stateGlobal.fullscreen.isTrue &&
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
parseParamScreenRect(Map<String, dynamic> 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;
|
||||
}
|
||||
|
@ -535,5 +535,20 @@ Future<List<TToggleMenu>> 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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -29,6 +30,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 +67,7 @@ const String kPointerEventKindTouch = "touch";
|
||||
const String kPointerEventKindMouse = "mouse";
|
||||
|
||||
const String kKeyShowDisplaysAsIndividualWindows = 'displays_as_individual_windows';
|
||||
const String kKeyUseAllMyDisplaysForTheRemoteSession = 'use_all_my_displays_for_the_remote_session';
|
||||
const String kKeyShowMonitorsToolbar = 'show_monitors_toolbar';
|
||||
|
||||
// the executable name of the portable version
|
||||
@ -86,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;
|
||||
|
@ -329,8 +329,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||
"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<DesktopHomePage>
|
||||
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<DesktopHomePage>
|
||||
Get.put<RxBool>(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<DesktopHomePage>
|
||||
} 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<DesktopHomePage>
|
||||
final peerId = args['peer_id'] as String;
|
||||
final display = args['display'] as int;
|
||||
final displayCount = args['display_count'] as int;
|
||||
final screenRect = parseParamScreenRect(args);
|
||||
await rustDeskWinManager.openMonitorSession(
|
||||
windowId, peerId, display, displayCount);
|
||||
windowId, peerId, display, displayCount, screenRect);
|
||||
}
|
||||
});
|
||||
_uniLinksSubscription = listenUniLinks();
|
||||
|
@ -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 for the remote session',
|
||||
kKeyUseAllMyDisplaysForTheRemoteSession));
|
||||
}
|
||||
return _Card(title: 'Other Default Options', children: children);
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
|
||||
late ToolbarState _toolbarState;
|
||||
String? peerId;
|
||||
bool isScreenRectSet = false;
|
||||
|
||||
var connectionMap = RxList<Widget>.empty(growable: true);
|
||||
|
||||
@ -59,6 +60,9 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
final tabWindowId = params['tab_window_id'];
|
||||
final display = params['display'];
|
||||
final displays = params['displays'];
|
||||
final screenRect = parseParamScreenRect(params);
|
||||
isScreenRectSet = screenRect != null;
|
||||
tryMoveToScreenAndSetFullscreen(screenRect);
|
||||
if (peerId != null) {
|
||||
ConnectionTypeState.init(peerId!);
|
||||
tabController.onSelected = (id) {
|
||||
@ -115,7 +119,9 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
final tabWindowId = args['tab_window_id'];
|
||||
final display = args['display'];
|
||||
final displays = args['displays'];
|
||||
final screenRect = parseParamScreenRect(args);
|
||||
windowOnTop(windowId());
|
||||
tryMoveToScreenAndSetFullscreen(screenRect);
|
||||
if (tabController.length == 0) {
|
||||
if (Platform.isMacOS && stateGlobal.closeOnFullscreen) {
|
||||
stateGlobal.setFullscreen(true);
|
||||
@ -196,15 +202,17 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
_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 +459,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
loopCloseWindow();
|
||||
}
|
||||
ConnectionTypeState.delete(id);
|
||||
|
@ -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';
|
||||
@ -353,10 +351,10 @@ class _RemoteToolbarState extends State<RemoteToolbar> {
|
||||
|
||||
int get windowId => stateGlobal.windowId;
|
||||
|
||||
bool get isFullscreen => stateGlobal.fullscreen;
|
||||
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;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -827,7 +797,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) {
|
||||
@ -981,7 +951,6 @@ class _DisplayMenuState extends State<_DisplayMenu> {
|
||||
cbExitFullscreen: () => widget.setFullscreen(false),
|
||||
);
|
||||
|
||||
bool get isFullscreen => stateGlobal.fullscreen;
|
||||
int get windowId => stateGlobal.windowId;
|
||||
Map<String, bool> get perms => widget.ffi.ffiModel.permissions;
|
||||
PeerInfo get pi => widget.ffi.ffiModel.pi;
|
||||
@ -2090,32 +2059,34 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildDraggable(context),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
widget.setFullscreen(!isFullscreen);
|
||||
setState(() {});
|
||||
},
|
||||
child: Tooltip(
|
||||
message: translate(isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'),
|
||||
child: Icon(
|
||||
isFullscreen ? Icons.fullscreen_exit : Icons.fullscreen,
|
||||
size: iconSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
Offstage(
|
||||
offstage: !isFullscreen,
|
||||
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;
|
||||
|
@ -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,
|
||||
|
@ -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<String, dynamic> evt, String peerId) async {
|
||||
handlePeerInfo(Map<String, dynamic> 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) {
|
||||
tryUseAllMyDisplaysForTheRemoteSession(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
tryUseAllMyDisplaysForTheRemoteSession(String peerId) async {
|
||||
if (bind.sessionGetUseAllMyDisplaysForTheRemoteSession(
|
||||
sessionId: sessionId) !=
|
||||
'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}) {
|
||||
|
@ -11,7 +11,7 @@ enum SvcStatus { notReady, connecting, ready }
|
||||
class StateGlobal {
|
||||
int _windowId = -1;
|
||||
bool grabKeyboard = false;
|
||||
bool _fullscreen = false;
|
||||
final 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<String, Map<int, String?>> _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,29 +66,27 @@ 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) {
|
||||
WindowController.fromWindowId(windowId)
|
||||
.setFullscreen(_fullscreen)
|
||||
.then((_) {
|
||||
final wc = WindowController.fromWindowId(windowId);
|
||||
wc.setFullscreen(_fullscreen.isTrue).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);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -69,8 +69,8 @@ class RustDeskMultiWindowManager {
|
||||
|
||||
// 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,
|
||||
Rect? screenRect) async {
|
||||
if (_remoteDesktopWindows.length > 1) {
|
||||
for (final windowId in _remoteDesktopWindows) {
|
||||
if (await DesktopMultiWindow.invokeMethod(
|
||||
@ -95,6 +95,14 @@ class RustDeskMultiWindowManager {
|
||||
'display': display,
|
||||
'displays': displays,
|
||||
};
|
||||
if (screenRect != null) {
|
||||
params['screen_rect'] = {
|
||||
'l': screenRect.left,
|
||||
't': screenRect.top,
|
||||
'r': screenRect.right,
|
||||
'b': screenRect.bottom,
|
||||
};
|
||||
}
|
||||
await _newSession(
|
||||
false,
|
||||
WindowType.RemoteDesktop,
|
||||
@ -102,21 +110,34 @@ class RustDeskMultiWindowManager {
|
||||
peerId,
|
||||
_remoteDesktopWindows,
|
||||
jsonEncode(params),
|
||||
screenRect: screenRect,
|
||||
);
|
||||
}
|
||||
|
||||
Future<int> newSessionWindow(
|
||||
WindowType type, String remoteId, String msg, List<int> windows) async {
|
||||
WindowType type,
|
||||
String remoteId,
|
||||
String msg,
|
||||
List<int> 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());
|
||||
}
|
||||
@ -131,11 +152,13 @@ class RustDeskMultiWindowManager {
|
||||
String methodName,
|
||||
String remoteId,
|
||||
List<int> windows,
|
||||
String msg,
|
||||
) async {
|
||||
String msg, {
|
||||
Rect? screenRect,
|
||||
}) async {
|
||||
if (openInTabs) {
|
||||
if (windows.isEmpty) {
|
||||
final windowId = await newSessionWindow(type, remoteId, msg, windows);
|
||||
final windowId = await newSessionWindow(
|
||||
type, remoteId, msg, windows, screenRect != null);
|
||||
return MultiWindowCallResult(windowId, null);
|
||||
} else {
|
||||
return call(type, methodName, msg);
|
||||
@ -144,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);
|
||||
@ -153,7 +178,8 @@ class RustDeskMultiWindowManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
final windowId = await newSessionWindow(type, remoteId, msg, windows);
|
||||
final windowId = await newSessionWindow(
|
||||
type, remoteId, msg, windows, screenRect != null);
|
||||
return MultiWindowCallResult(windowId, null);
|
||||
}
|
||||
}
|
||||
|
@ -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_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_displays_for_the_remote_session: 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_displays_for_the_remote_session: Self::default_use_all_my_displays_for_the_remote_session(
|
||||
),
|
||||
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_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<i32> {
|
||||
let f: f64 = UserDefaultConfig::read()
|
||||
|
@ -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_displays_for_the_remote_session" ("", "Y") to the current config.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `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_displays_for_the_remote_session = value;
|
||||
self.save_config(config);
|
||||
}
|
||||
|
||||
/// Save scroll style to the current config.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -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<Option<String>> {
|
||||
pub fn session_get_displays_as_individual_windows(
|
||||
session_id: SessionID,
|
||||
) -> SyncReturn<Option<String>> {
|
||||
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_displays_for_the_remote_session(
|
||||
session_id: SessionID,
|
||||
) -> SyncReturn<Option<String>> {
|
||||
if let Some(session) = sessions::get_session_by_session_id(&session_id) {
|
||||
SyncReturn(Some(session.get_use_all_my_displays_for_the_remote_session()))
|
||||
} else {
|
||||
SyncReturn(None)
|
||||
}
|
||||
}
|
||||
|
||||
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_displays_for_the_remote_session(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn session_get_custom_image_quality(session_id: SessionID) -> Option<Vec<i32>> {
|
||||
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<String> {
|
||||
SyncReturn(display_info)
|
||||
}
|
||||
|
||||
pub fn main_get_displays() -> SyncReturn<String> {
|
||||
#[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::<Vec<_>>();
|
||||
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,
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", "将我的所有显示器用于远程会话"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -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 for the remote session", ""),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
@ -240,6 +240,10 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.read().unwrap().displays_as_individual_windows.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) {
|
||||
self.lc.write().unwrap().save_reverse_mouse_wheel(value);
|
||||
}
|
||||
@ -248,6 +252,10 @@ impl<T: InvokeUiSession> Session<T> {
|
||||
self.lc.write().unwrap().save_displays_as_individual_windows(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) {
|
||||
self.lc.write().unwrap().save_view_style(value);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user