refact: win, virtual display (#7767)

* refact: win, virtual display

Signed-off-by: fufesou <shuanglongchen@yeah.net>

* Update flutter-build.yml

---------

Signed-off-by: fufesou <shuanglongchen@yeah.net>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
fufesou
2024-04-19 11:31:52 +08:00
committed by GitHub
parent a3c0911529
commit e83c28bf54
61 changed files with 1113 additions and 290 deletions

View File

@@ -19,7 +19,9 @@ const kKeyTranslateMode = 'translate';
const String kPlatformAdditionsIsWayland = "is_wayland";
const String kPlatformAdditionsHeadless = "headless";
const String kPlatformAdditionsIsInstalled = "is_installed";
const String kPlatformAdditionsVirtualDisplays = "virtual_displays";
const String kPlatformAdditionsIddImpl = "idd_impl";
const String kPlatformAdditionsRustDeskVirtualDisplays = "rustdesk_virtual_displays";
const String kPlatformAdditionsAmyuniVirtualDisplays = "amyuni_virtual_displays";
const String kPlatformAdditionsHasFileClipboard = "has_file_clipboard";
const String kPlatformAdditionsSupportedPrivacyModeImpl =
"supported_privacy_mode_impl";
@@ -121,12 +123,11 @@ double kNewWindowOffset = isWindows
? 30.0
: 50.0;
EdgeInsets get kDragToResizeAreaPadding =>
!kUseCompatibleUiMode && isLinux
? stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.value
? EdgeInsets.zero
: EdgeInsets.all(5.0)
: EdgeInsets.zero;
EdgeInsets get kDragToResizeAreaPadding => !kUseCompatibleUiMode && isLinux
? stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.value
? EdgeInsets.zero
: EdgeInsets.all(5.0)
: EdgeInsets.zero;
// https://en.wikipedia.org/wiki/Non-breaking_space
const int $nbsp = 0x00A0;

View File

@@ -1058,11 +1058,16 @@ class _DisplayMenuState extends State<_DisplayMenu> {
ffi: widget.ffi,
screenAdjustor: _screenAdjustor,
),
// We may add this feature if it is needed and we have an EV certificate.
// _VirtualDisplayMenu(
// id: widget.id,
// ffi: widget.ffi,
// ),
if (pi.isRustDeskIdd)
_RustDeskVirtualDisplayMenu(
id: widget.id,
ffi: widget.ffi,
),
if (pi.isAmyuniIdd)
_AmyuniVirtualDisplayMenu(
id: widget.id,
ffi: widget.ffi,
),
Divider(),
toggles(),
];
@@ -1540,21 +1545,23 @@ class _ResolutionsMenuState extends State<_ResolutionsMenu> {
}
}
class _VirtualDisplayMenu extends StatefulWidget {
class _RustDeskVirtualDisplayMenu extends StatefulWidget {
final String id;
final FFI ffi;
_VirtualDisplayMenu({
_RustDeskVirtualDisplayMenu({
Key? key,
required this.id,
required this.ffi,
}) : super(key: key);
@override
State<_VirtualDisplayMenu> createState() => _VirtualDisplayMenuState();
State<_RustDeskVirtualDisplayMenu> createState() =>
_RustDeskVirtualDisplayMenuState();
}
class _VirtualDisplayMenuState extends State<_VirtualDisplayMenu> {
class _RustDeskVirtualDisplayMenuState
extends State<_RustDeskVirtualDisplayMenu> {
@override
void initState() {
super.initState();
@@ -1569,7 +1576,7 @@ class _VirtualDisplayMenuState extends State<_VirtualDisplayMenu> {
return Offstage();
}
final virtualDisplays = widget.ffi.ffiModel.pi.virtualDisplays;
final virtualDisplays = widget.ffi.ffiModel.pi.RustDeskVirtualDisplays;
final privacyModeState = PrivacyModeState.find(widget.id);
final children = <Widget>[];
@@ -1611,6 +1618,82 @@ class _VirtualDisplayMenuState extends State<_VirtualDisplayMenu> {
}
}
class _AmyuniVirtualDisplayMenu extends StatefulWidget {
final String id;
final FFI ffi;
_AmyuniVirtualDisplayMenu({
Key? key,
required this.id,
required this.ffi,
}) : super(key: key);
@override
State<_AmyuniVirtualDisplayMenu> createState() =>
_AmiyuniVirtualDisplayMenuState();
}
class _AmiyuniVirtualDisplayMenuState extends State<_AmyuniVirtualDisplayMenu> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
if (widget.ffi.ffiModel.pi.platform != kPeerPlatformWindows) {
return Offstage();
}
if (!widget.ffi.ffiModel.pi.isInstalled) {
return Offstage();
}
final count = widget.ffi.ffiModel.pi.amyuniVirtualDisplayCount;
final privacyModeState = PrivacyModeState.find(widget.id);
final children = <Widget>[
Obx(() => Row(
children: [
TextButton(
onPressed: privacyModeState.isNotEmpty || count == 0
? null
: () => bind.sessionToggleVirtualDisplay(
sessionId: widget.ffi.sessionId, index: 0, on: false),
child: Icon(Icons.remove),
),
Text(count.toString()),
TextButton(
onPressed: privacyModeState.isNotEmpty || count == 4
? null
: () => bind.sessionToggleVirtualDisplay(
sessionId: widget.ffi.sessionId, index: 0, on: true),
child: Icon(Icons.add),
),
],
)),
Divider(),
Obx(() => MenuButton(
onPressed: privacyModeState.isNotEmpty || count == 0
? null
: () {
bind.sessionToggleVirtualDisplay(
sessionId: widget.ffi.sessionId,
index: kAllVirtualDisplay,
on: false);
},
ffi: widget.ffi,
child: Text(translate('Plug out all')),
)),
];
return _SubmenuButton(
ffi: widget.ffi,
menuChildren: children,
child: Text(translate("Virtual display")),
);
}
}
class _KeyboardMenu extends StatelessWidget {
final String id;
final FFI ffi;

View File

@@ -561,8 +561,12 @@ class FfiModel with ChangeNotifier {
showRelayHintDialog(sessionId, type, title, text, dialogManager, peerId);
} else if (text == 'Connected, waiting for image...') {
showConnectedWaitingForImage(dialogManager, sessionId, type, title, text);
} else if (title == 'Privacy mode') {
final hasRetry = evt['hasRetry'] == 'true';
showPrivacyFailedDialog(
sessionId, type, title, text, link, hasRetry, dialogManager);
} else {
var hasRetry = evt['hasRetry'] == 'true';
final hasRetry = evt['hasRetry'] == 'true';
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
}
}
@@ -657,6 +661,27 @@ class FfiModel with ChangeNotifier {
bind.sessionOnWaitingForImageDialogShow(sessionId: sessionId);
}
void showPrivacyFailedDialog(
SessionID sessionId,
String type,
String title,
String text,
String link,
bool hasRetry,
OverlayDialogManager dialogManager) {
if (text == 'no_need_privacy_mode_no_physical_displays_tip' ||
text == 'Enter privacy mode') {
// There are display changes on the remote side,
// which will cause some messages to refresh the canvas and dismiss dialogs.
// So we add a delay here to ensure the dialog is displayed.
Future.delayed(Duration(milliseconds: 3000), () {
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
});
} else {
showMsgBox(sessionId, type, title, text, link, hasRetry, dialogManager);
}
}
_updateSessionWidthHeight(SessionID sessionId) {
if (_rect == null) return;
if (_rect!.width <= 0 || _rect!.height <= 0) {
@@ -986,15 +1011,21 @@ class FfiModel with ChangeNotifier {
}
if (updateData.isEmpty) {
_pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays);
_pi.platformAdditions.remove(kPlatformAdditionsRustDeskVirtualDisplays);
_pi.platformAdditions.remove(kPlatformAdditionsAmyuniVirtualDisplays);
} else {
try {
final updateJson = json.decode(updateData) as Map<String, dynamic>;
for (final key in updateJson.keys) {
_pi.platformAdditions[key] = updateJson[key];
}
if (!updateJson.containsKey(kPlatformAdditionsVirtualDisplays)) {
_pi.platformAdditions.remove(kPlatformAdditionsVirtualDisplays);
if (!updateJson
.containsKey(kPlatformAdditionsRustDeskVirtualDisplays)) {
_pi.platformAdditions
.remove(kPlatformAdditionsRustDeskVirtualDisplays);
}
if (!updateJson.containsKey(kPlatformAdditionsAmyuniVirtualDisplays)) {
_pi.platformAdditions.remove(kPlatformAdditionsAmyuniVirtualDisplays);
}
} catch (e) {
debugPrint('Failed to decode platformAdditions $e');
@@ -2490,14 +2521,21 @@ class PeerInfo with ChangeNotifier {
bool get isInstalled =>
platform != kPeerPlatformWindows ||
platformAdditions[kPlatformAdditionsIsInstalled] == true;
List<int> get virtualDisplays => List<int>.from(
platformAdditions[kPlatformAdditionsVirtualDisplays] ?? []);
List<int> get RustDeskVirtualDisplays => List<int>.from(
platformAdditions[kPlatformAdditionsRustDeskVirtualDisplays] ?? []);
int get amyuniVirtualDisplayCount =>
platformAdditions[kPlatformAdditionsAmyuniVirtualDisplays] ?? 0;
bool get isSupportMultiDisplay =>
(isDesktop || isWebDesktop) && isSupportMultiUiSession;
bool get cursorEmbedded => tryGetDisplay()?.cursorEmbedded ?? false;
bool get isRustDeskIdd =>
platformAdditions[kPlatformAdditionsIddImpl] == 'rustdesk_idd';
bool get isAmyuniIdd =>
platformAdditions[kPlatformAdditionsIddImpl] == 'amyuni_idd';
Display? tryGetDisplay() {
if (displays.isEmpty) {
return null;