Merge branch 'master' of github.com-rustdesk:rustdesk/rustdesk

This commit is contained in:
rustdesk 2022-09-16 22:39:31 +08:00
commit 30aa7efbf5
12 changed files with 430 additions and 281 deletions

View File

@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../common.dart';
import '../../models/platform_model.dart';
void changeIdDialog() {
var newId = "";
var msg = "";
var isInProgress = false;
TextEditingController controller = TextEditingController();
gFFI.dialogManager.show((setState, close) {
submit() async {
debugPrint("onSubmit");
newId = controller.text.trim();
setState(() {
msg = "";
isInProgress = true;
bind.mainChangeId(newId: newId);
});
var status = await bind.mainGetAsyncStatus();
while (status == " ") {
await Future.delayed(const Duration(milliseconds: 100));
status = await bind.mainGetAsyncStatus();
}
if (status.isEmpty) {
// ok
close();
return;
}
setState(() {
isInProgress = false;
msg = translate(status);
});
}
return CustomAlertDialog(
title: Text(translate("Change ID")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("id_change_tip")),
const SizedBox(
height: 12.0,
),
TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg)),
inputFormatters: [
LengthLimitingTextInputFormatter(16),
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
],
maxLength: 16,
controller: controller,
focusNode: FocusNode()..requestFocus(),
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
);
});
}

View File

@ -19,6 +19,8 @@ import 'package:tray_manager/tray_manager.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import '../../common/widgets/dialog.dart';
class _MenubarTheme { class _MenubarTheme {
static const Color commonColor = MyTheme.accent; static const Color commonColor = MyTheme.accent;
// kMinInteractiveDimension // kMinInteractiveDimension

View File

@ -11,6 +11,8 @@ import 'package:get/get.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import '../../common/widgets/dialog.dart';
const double _kTabWidth = 235; const double _kTabWidth = 235;
const double _kTabHeight = 42; const double _kTabHeight = 42;
const double _kCardFixedWidth = 560; const double _kCardFixedWidth = 560;
@ -219,17 +221,12 @@ class _GeneralState extends State<_General> {
} }
Widget hwcodec() { Widget hwcodec() {
return _futureBuilder(
future: bind.mainHasHwcodec(),
hasData: (data) {
return Offstage( return Offstage(
offstage: !(data as bool), offstage: !bind.mainHasHwcodec(),
child: _Card(title: 'Hardware Codec', children: [ child: _Card(title: 'Hardware Codec', children: [
_OptionCheckBox( _OptionCheckBox(context, 'Enable hardware codec', 'enable-hwcodec'),
context, 'Enable hardware codec', 'enable-hwcodec'),
]), ]),
); );
});
} }
Widget audio(BuildContext context) { Widget audio(BuildContext context) {
@ -1501,82 +1498,4 @@ void changeSocks5Proxy() async {
}); });
} }
void changeIdDialog() {
var newId = "";
var msg = "";
var isInProgress = false;
TextEditingController controller = TextEditingController();
gFFI.dialogManager.show((setState, close) {
submit() async {
newId = controller.text.trim();
setState(() {
msg = "";
isInProgress = true;
bind.mainChangeId(newId: newId);
});
var status = await bind.mainGetAsyncStatus();
while (status == " ") {
await Future.delayed(const Duration(milliseconds: 100));
status = await bind.mainGetAsyncStatus();
}
if (status.isEmpty) {
// ok
close();
return;
}
setState(() {
isInProgress = false;
msg = translate(status);
});
}
return CustomAlertDialog(
title: Text(translate("Change ID")),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(translate("id_change_tip")),
const SizedBox(
height: 8.0,
),
Row(
children: [
const Text("ID:").marginOnly(bottom: 16.0),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: msg.isEmpty ? null : translate(msg)),
inputFormatters: [
LengthLimitingTextInputFormatter(16),
// FilteringTextInputFormatter(RegExp(r"[a-zA-z][a-zA-z0-9\_]*"), allow: true)
],
maxLength: 16,
controller: controller,
focusNode: FocusNode()..requestFocus(),
),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
);
});
}
//#endregion //#endregion

View File

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
@ -298,6 +299,12 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
Widget _buildDisplay(BuildContext context) { Widget _buildDisplay(BuildContext context) {
return FutureBuilder(future: () async {
final supportedHwcodec =
await bind.sessionSupportedHwcodec(id: widget.id);
return {'supportedHwcodec': supportedHwcodec};
}(), builder: (context, snapshot) {
if (snapshot.hasData) {
return mod_menu.PopupMenuButton( return mod_menu.PopupMenuButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
icon: const Icon( icon: const Icon(
@ -306,7 +313,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
), ),
tooltip: translate('Display Settings'), tooltip: translate('Display Settings'),
position: mod_menu.PopupMenuPosition.under, position: mod_menu.PopupMenuPosition.under,
itemBuilder: (BuildContext context) => _getDisplayMenu() itemBuilder: (BuildContext context) => _getDisplayMenu(snapshot.data!)
.map((entry) => entry.build( .map((entry) => entry.build(
context, context,
const MenuConfig( const MenuConfig(
@ -317,6 +324,10 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
.expand((i) => i) .expand((i) => i)
.toList(), .toList(),
); );
} else {
return const Offstage();
}
});
} }
Widget _buildKeyboard(BuildContext context) { Widget _buildKeyboard(BuildContext context) {
@ -532,7 +543,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
return displayMenu; return displayMenu;
} }
List<MenuEntryBase<String>> _getDisplayMenu() { List<MenuEntryBase<String>> _getDisplayMenu(dynamic futureData) {
final displayMenu = [ final displayMenu = [
MenuEntryRadios<String>( MenuEntryRadios<String>(
text: translate('Ratio'), text: translate('Ratio'),
@ -653,9 +664,49 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
}), }),
MenuEntryDivider<String>(), MenuEntryDivider<String>(),
// {show_codec ? <div> ];
// MenuEntryDivider<String>(),
() { /// Show Codec Preference
if (bind.mainHasHwcodec()) {
final List<bool> codecs = [];
try {
final Map codecsJson = jsonDecode(futureData['supportedHwcodec']);
final h264 = codecsJson['h264'] ?? false;
final h265 = codecsJson['h265'] ?? false;
codecs.add(h264);
codecs.add(h265);
} finally {}
if (codecs.length == 2 && (codecs[0] || codecs[1])) {
displayMenu.add(MenuEntryRadios<String>(
text: translate('Codec Preference'),
optionsGetter: () {
final list = [
MenuEntryRadioOption(text: translate('Auto'), value: 'auto'),
MenuEntryRadioOption(text: 'VP9', value: 'vp9'),
];
if (codecs[0]) {
list.add(MenuEntryRadioOption(text: 'H264', value: 'h264'));
}
if (codecs[1]) {
list.add(MenuEntryRadioOption(text: 'H265', value: 'h265'));
}
return list;
},
curOptionGetter: () async {
return await bind.sessionGetOption(
id: widget.id, arg: 'codec-preference') ??
'auto';
},
optionSetter: (String oldValue, String newValue) async {
await bind.sessionPeerOption(
id: widget.id, name: "codec-preference", value: newValue);
bind.sessionChangePreferCodec(id: widget.id);
}));
}
}
/// Show remote cursor
displayMenu.add(() {
final state = ShowRemoteCursorState.find(widget.id); final state = ShowRemoteCursorState.find(widget.id);
return MenuEntrySwitch2<String>( return MenuEntrySwitch2<String>(
text: translate('Show remote cursor'), text: translate('Show remote cursor'),
@ -667,8 +718,10 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
await bind.sessionToggleOption( await bind.sessionToggleOption(
id: widget.id, value: 'show-remote-cursor'); id: widget.id, value: 'show-remote-cursor');
}); });
}(), }());
MenuEntrySwitch<String>(
/// Show quality monitor
displayMenu.add(MenuEntrySwitch<String>(
text: translate('Show quality monitor'), text: translate('Show quality monitor'),
getter: () async { getter: () async {
return bind.sessionGetToggleOptionSync( return bind.sessionGetToggleOptionSync(
@ -678,8 +731,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
await bind.sessionToggleOption( await bind.sessionToggleOption(
id: widget.id, value: 'show-quality-monitor'); id: widget.id, value: 'show-quality-monitor');
widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
}), }));
];
final perms = widget.ffi.ffiModel.permissions; final perms = widget.ffi.ffiModel.permissions;
final pi = widget.ffi.ffiModel.pi; final pi = widget.ffi.ffiModel.pi;

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
@ -1011,17 +1012,22 @@ class QualityMonitor extends StatelessWidget {
void showOptions(String id, OverlayDialogManager dialogManager) async { void showOptions(String id, OverlayDialogManager dialogManager) async {
String quality = await bind.sessionGetImageQuality(id: id) ?? 'balanced'; String quality = await bind.sessionGetImageQuality(id: id) ?? 'balanced';
if (quality == '') quality = 'balanced'; if (quality == '') quality = 'balanced';
String codec =
await bind.sessionGetOption(id: id, arg: 'codec-preference') ?? 'auto';
if (codec == '') codec = 'auto';
String viewStyle = String viewStyle =
await bind.sessionGetOption(id: id, arg: 'view-style') ?? ''; await bind.sessionGetOption(id: id, arg: 'view-style') ?? '';
var displays = <Widget>[]; var displays = <Widget>[];
final pi = gFFI.ffiModel.pi; final pi = gFFI.ffiModel.pi;
final image = gFFI.ffiModel.getConnectionImage(); final image = gFFI.ffiModel.getConnectionImage();
if (image != null) if (image != null) {
displays.add(Padding(padding: const EdgeInsets.only(top: 8), child: image)); displays.add(Padding(padding: const EdgeInsets.only(top: 8), child: image));
}
if (pi.displays.length > 1) { if (pi.displays.length > 1) {
final cur = pi.currentDisplay; final cur = pi.currentDisplay;
final children = <Widget>[]; final children = <Widget>[];
for (var i = 0; i < pi.displays.length; ++i) for (var i = 0; i < pi.displays.length; ++i) {
children.add(InkWell( children.add(InkWell(
onTap: () { onTap: () {
if (i == cur) return; if (i == cur) return;
@ -1038,6 +1044,7 @@ void showOptions(String id, OverlayDialogManager dialogManager) async {
child: Text((i + 1).toString(), child: Text((i + 1).toString(),
style: TextStyle( style: TextStyle(
color: i == cur ? Colors.white : Colors.black87)))))); color: i == cur ? Colors.white : Colors.black87))))));
}
displays.add(Padding( displays.add(Padding(
padding: const EdgeInsets.only(top: 8), padding: const EdgeInsets.only(top: 8),
child: Wrap( child: Wrap(
@ -1047,9 +1054,21 @@ void showOptions(String id, OverlayDialogManager dialogManager) async {
))); )));
} }
if (displays.isNotEmpty) { if (displays.isNotEmpty) {
displays.add(Divider(color: MyTheme.border)); displays.add(const Divider(color: MyTheme.border));
} }
final perms = gFFI.ffiModel.permissions; final perms = gFFI.ffiModel.permissions;
final hasHwcodec = bind.mainHasHwcodec();
final List<bool> codecs = [];
if (hasHwcodec) {
try {
final Map codecsJson =
jsonDecode(await bind.sessionSupportedHwcodec(id: id));
final h264 = codecsJson['h264'] ?? false;
final h265 = codecsJson['h265'] ?? false;
codecs.add(h264);
codecs.add(h265);
} finally {}
}
dialogManager.show((setState, close) { dialogManager.show((setState, close) {
final more = <Widget>[]; final more = <Widget>[];
@ -1057,50 +1076,77 @@ void showOptions(String id, OverlayDialogManager dialogManager) async {
more.add(getToggle(id, setState, 'disable-audio', 'Mute')); more.add(getToggle(id, setState, 'disable-audio', 'Mute'));
} }
if (perms['keyboard'] != false) { if (perms['keyboard'] != false) {
if (perms['clipboard'] != false) if (perms['clipboard'] != false) {
more.add( more.add(
getToggle(id, setState, 'disable-clipboard', 'Disable clipboard')); getToggle(id, setState, 'disable-clipboard', 'Disable clipboard'));
}
more.add(getToggle( more.add(getToggle(
id, setState, 'lock-after-session-end', 'Lock after session end')); id, setState, 'lock-after-session-end', 'Lock after session end'));
if (pi.platform == 'Windows') { if (pi.platform == 'Windows') {
more.add(getToggle(id, setState, 'privacy-mode', 'Privacy mode')); more.add(getToggle(id, setState, 'privacy-mode', 'Privacy mode'));
} }
} }
var setQuality = (String? value) { setQuality(String? value) {
if (value == null) return; if (value == null) return;
setState(() { setState(() {
quality = value; quality = value;
bind.sessionSetImageQuality(id: id, value: value); bind.sessionSetImageQuality(id: id, value: value);
}); });
}; }
var setViewStyle = (String? value) {
setViewStyle(String? value) {
if (value == null) return; if (value == null) return;
setState(() { setState(() {
viewStyle = value; viewStyle = value;
bind.sessionPeerOption(id: id, name: "view-style", value: value); bind
gFFI.canvasModel.updateViewStyle(); .sessionPeerOption(id: id, name: "view-style", value: value)
.then((_) => gFFI.canvasModel.updateViewStyle());
}); });
}; }
return CustomAlertDialog(
title: SizedBox.shrink(), setCodec(String? value) {
content: Column( if (value == null) return;
mainAxisSize: MainAxisSize.min, setState(() {
children: displays + codec = value;
<Widget>[ bind
getRadio('Scale Original', 'original', viewStyle, setViewStyle), .sessionPeerOption(id: id, name: "codec-preference", value: value)
.then((_) => bind.sessionChangePreferCodec(id: id));
});
}
final radios = [
getRadio('Scale original', 'original', viewStyle, setViewStyle),
getRadio('Scale adaptive', 'adaptive', viewStyle, setViewStyle), getRadio('Scale adaptive', 'adaptive', viewStyle, setViewStyle),
Divider(color: MyTheme.border), const Divider(color: MyTheme.border),
getRadio('Good image quality', 'best', quality, setQuality), getRadio('Good image quality', 'best', quality, setQuality),
getRadio('Balanced', 'balanced', quality, setQuality), getRadio('Balanced', 'balanced', quality, setQuality),
getRadio('Optimize reaction time', 'low', quality, setQuality), getRadio('Optimize reaction time', 'low', quality, setQuality),
Divider(color: MyTheme.border), const Divider(color: MyTheme.border)
getToggle( ];
id, setState, 'show-remote-cursor', 'Show remote cursor'),
getToggle(id, setState, 'show-quality-monitor', if (hasHwcodec && codecs.length == 2 && (codecs[0] || codecs[1])) {
'Show quality monitor'), radios.addAll([
] + getRadio(translate('Auto'), 'auto', codec, setCodec),
more), getRadio('VP9', 'vp9', codec, setCodec),
actions: [], ]);
if (codecs[0]) {
radios.add(getRadio('H264', 'h264', codec, setCodec));
}
if (codecs[1]) {
radios.add(getRadio('H265', 'h265', codec, setCodec));
}
radios.add(const Divider(color: MyTheme.border));
}
final toggles = [
getToggle(id, setState, 'show-remote-cursor', 'Show remote cursor'),
getToggle(id, setState, 'show-quality-monitor', 'Show quality monitor'),
];
return CustomAlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: displays + radios + toggles + more),
contentPadding: 0, contentPadding: 0,
); );
}, clickMaskDismiss: true, backDismiss: true); }, clickMaskDismiss: true, backDismiss: true);

View File

@ -3,6 +3,7 @@ import 'package:flutter_hbb/mobile/widgets/dialog.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../common.dart'; import '../../common.dart';
import '../../common/widgets/dialog.dart';
import '../../models/platform_model.dart'; import '../../models/platform_model.dart';
import '../../models/server_model.dart'; import '../../models/server_model.dart';
import 'home_page.dart'; import 'home_page.dart';
@ -12,39 +13,37 @@ class ServerPage extends StatefulWidget implements PageShape {
final title = translate("Share Screen"); final title = translate("Share Screen");
@override @override
final icon = Icon(Icons.mobile_screen_share); final icon = const Icon(Icons.mobile_screen_share);
@override @override
final appBarActions = [ final appBarActions = [
PopupMenuButton<String>( PopupMenuButton<String>(
icon: Icon(Icons.more_vert), icon: const Icon(Icons.more_vert),
itemBuilder: (context) { itemBuilder: (context) {
return [ return [
PopupMenuItem( PopupMenuItem(
child: Text(translate("Change ID")), padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: EdgeInsets.symmetric(horizontal: 16.0),
value: "changeID", value: "changeID",
enabled: false, child: Text(translate("Change ID")),
), ),
PopupMenuItem( PopupMenuItem(
child: Text(translate("Set permanent password")), padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: EdgeInsets.symmetric(horizontal: 16.0),
value: "setPermanentPassword", value: "setPermanentPassword",
enabled: enabled:
gFFI.serverModel.verificationMethod != kUseTemporaryPassword, gFFI.serverModel.verificationMethod != kUseTemporaryPassword,
child: Text(translate("Set permanent password")),
), ),
PopupMenuItem( PopupMenuItem(
child: Text(translate("Set temporary password length")), padding: const EdgeInsets.symmetric(horizontal: 16.0),
padding: EdgeInsets.symmetric(horizontal: 16.0),
value: "setTemporaryPasswordLength", value: "setTemporaryPasswordLength",
enabled: enabled:
gFFI.serverModel.verificationMethod != kUsePermanentPassword, gFFI.serverModel.verificationMethod != kUsePermanentPassword,
child: Text(translate("Set temporary password length")),
), ),
const PopupMenuDivider(), const PopupMenuDivider(),
PopupMenuItem( PopupMenuItem(
padding: EdgeInsets.symmetric(horizontal: 0.0), padding: const EdgeInsets.symmetric(horizontal: 0.0),
value: kUseTemporaryPassword, value: kUseTemporaryPassword,
child: Container(
child: ListTile( child: ListTile(
title: Text(translate("Use temporary password")), title: Text(translate("Use temporary password")),
trailing: Icon( trailing: Icon(
@ -52,11 +51,11 @@ class ServerPage extends StatefulWidget implements PageShape {
color: gFFI.serverModel.verificationMethod == color: gFFI.serverModel.verificationMethod ==
kUseTemporaryPassword kUseTemporaryPassword
? null ? null
: Color(0xFFFFFFFF), : Colors.transparent,
))), )),
), ),
PopupMenuItem( PopupMenuItem(
padding: EdgeInsets.symmetric(horizontal: 0.0), padding: const EdgeInsets.symmetric(horizontal: 0.0),
value: kUsePermanentPassword, value: kUsePermanentPassword,
child: ListTile( child: ListTile(
title: Text(translate("Use permanent password")), title: Text(translate("Use permanent password")),
@ -65,11 +64,11 @@ class ServerPage extends StatefulWidget implements PageShape {
color: gFFI.serverModel.verificationMethod == color: gFFI.serverModel.verificationMethod ==
kUsePermanentPassword kUsePermanentPassword
? null ? null
: Color(0xFFFFFFFF), : Colors.transparent,
)), )),
), ),
PopupMenuItem( PopupMenuItem(
padding: EdgeInsets.symmetric(horizontal: 0.0), padding: const EdgeInsets.symmetric(horizontal: 0.0),
value: kUseBothPasswords, value: kUseBothPasswords,
child: ListTile( child: ListTile(
title: Text(translate("Use both passwords")), title: Text(translate("Use both passwords")),
@ -80,14 +79,14 @@ class ServerPage extends StatefulWidget implements PageShape {
gFFI.serverModel.verificationMethod != gFFI.serverModel.verificationMethod !=
kUsePermanentPassword kUsePermanentPassword
? null ? null
: Color(0xFFFFFFFF), : Colors.transparent,
)), )),
), ),
]; ];
}, },
onSelected: (value) { onSelected: (value) {
if (value == "changeID") { if (value == "changeID") {
// TODO changeIdDialog();
} else if (value == "setPermanentPassword") { } else if (value == "setPermanentPassword") {
setPermanentPasswordDialog(gFFI.dialogManager); setPermanentPasswordDialog(gFFI.dialogManager);
} else if (value == "setTemporaryPasswordLength") { } else if (value == "setTemporaryPasswordLength") {
@ -101,6 +100,8 @@ class ServerPage extends StatefulWidget implements PageShape {
}) })
]; ];
ServerPage({Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() => _ServerPageState(); State<StatefulWidget> createState() => _ServerPageState();
} }
@ -125,9 +126,9 @@ class _ServerPageState extends State<ServerPage> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
ServerInfo(), ServerInfo(),
PermissionChecker(), const PermissionChecker(),
ConnectionManager(), const ConnectionManager(),
SizedBox.fromSize(size: Size(0, 15.0)), SizedBox.fromSize(size: const Size(0, 15.0)),
], ],
), ),
), ),
@ -148,6 +149,8 @@ class ServerInfo extends StatelessWidget {
final model = gFFI.serverModel; final model = gFFI.serverModel;
final emptyController = TextEditingController(text: "-"); final emptyController = TextEditingController(text: "-");
ServerInfo({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isPermanent = model.verificationMethod == kUsePermanentPassword; final isPermanent = model.verificationMethod == kUsePermanentPassword;
@ -158,7 +161,7 @@ class ServerInfo extends StatelessWidget {
children: [ children: [
TextFormField( TextFormField(
readOnly: true, readOnly: true,
style: TextStyle( style: const TextStyle(
fontSize: 25.0, fontSize: 25.0,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: MyTheme.accent), color: MyTheme.accent),
@ -166,14 +169,14 @@ class ServerInfo extends StatelessWidget {
decoration: InputDecoration( decoration: InputDecoration(
icon: const Icon(Icons.perm_identity), icon: const Icon(Icons.perm_identity),
labelText: translate("ID"), labelText: translate("ID"),
labelStyle: TextStyle( labelStyle: const TextStyle(
fontWeight: FontWeight.bold, color: MyTheme.accent50), fontWeight: FontWeight.bold, color: MyTheme.accent50),
), ),
onSaved: (String? value) {}, onSaved: (String? value) {},
), ),
TextFormField( TextFormField(
readOnly: true, readOnly: true,
style: TextStyle( style: const TextStyle(
fontSize: 25.0, fontSize: 25.0,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: MyTheme.accent), color: MyTheme.accent),
@ -181,7 +184,7 @@ class ServerInfo extends StatelessWidget {
decoration: InputDecoration( decoration: InputDecoration(
icon: const Icon(Icons.lock), icon: const Icon(Icons.lock),
labelText: translate("Password"), labelText: translate("Password"),
labelStyle: TextStyle( labelStyle: const TextStyle(
fontWeight: FontWeight.bold, color: MyTheme.accent50), fontWeight: FontWeight.bold, color: MyTheme.accent50),
suffix: isPermanent suffix: isPermanent
? null ? null
@ -200,13 +203,13 @@ class ServerInfo extends StatelessWidget {
Center( Center(
child: Row( child: Row(
children: [ children: [
Icon(Icons.warning_amber_sharp, const Icon(Icons.warning_amber_sharp,
color: Colors.redAccent, size: 24), color: Colors.redAccent, size: 24),
SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: Text( child: Text(
translate("Service is not running"), translate("Service is not running"),
style: TextStyle( style: const TextStyle(
fontFamily: 'WorkSans', fontFamily: 'WorkSans',
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,
@ -215,11 +218,11 @@ class ServerInfo extends StatelessWidget {
)) ))
], ],
)), )),
SizedBox(height: 5), const SizedBox(height: 5),
Center( Center(
child: Text( child: Text(
translate("android_start_service_tip"), translate("android_start_service_tip"),
style: TextStyle(fontSize: 12, color: MyTheme.darkGray), style: const TextStyle(fontSize: 12, color: MyTheme.darkGray),
)) ))
], ],
)); ));
@ -227,8 +230,10 @@ class ServerInfo extends StatelessWidget {
} }
class PermissionChecker extends StatefulWidget { class PermissionChecker extends StatefulWidget {
const PermissionChecker({Key? key}) : super(key: key);
@override @override
_PermissionCheckerState createState() => _PermissionCheckerState(); State<PermissionChecker> createState() => _PermissionCheckerState();
} }
class _PermissionCheckerState extends State<PermissionChecker> { class _PermissionCheckerState extends State<PermissionChecker> {
@ -236,7 +241,7 @@ class _PermissionCheckerState extends State<PermissionChecker> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serverModel = Provider.of<ServerModel>(context); final serverModel = Provider.of<ServerModel>(context);
final hasAudioPermission = androidVersion >= 30; final hasAudioPermission = androidVersion >= 30;
final status; final String status;
if (serverModel.connectStatus == -1) { if (serverModel.connectStatus == -1) {
status = 'not_ready_status'; status = 'not_ready_status';
} else if (serverModel.connectStatus == 0) { } else if (serverModel.connectStatus == 0) {
@ -260,9 +265,9 @@ class _PermissionCheckerState extends State<PermissionChecker> {
serverModel.toggleAudio) serverModel.toggleAudio)
: Text( : Text(
"* ${translate("android_version_audio_tip")}", "* ${translate("android_version_audio_tip")}",
style: TextStyle(color: MyTheme.darkGray), style: const TextStyle(color: MyTheme.darkGray),
), ),
SizedBox(height: 8), const SizedBox(height: 8),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
@ -273,11 +278,11 @@ class _PermissionCheckerState extends State<PermissionChecker> {
style: ButtonStyle( style: ButtonStyle(
backgroundColor: backgroundColor:
MaterialStateProperty.all(Colors.red)), MaterialStateProperty.all(Colors.red)),
icon: Icon(Icons.stop), icon: const Icon(Icons.stop),
onPressed: serverModel.toggleService, onPressed: serverModel.toggleService,
label: Text(translate("Stop service"))) label: Text(translate("Stop service")))
: ElevatedButton.icon( : ElevatedButton.icon(
icon: Icon(Icons.play_arrow), icon: const Icon(Icons.play_arrow),
onPressed: serverModel.toggleService, onPressed: serverModel.toggleService,
label: Text(translate("Start Service")))), label: Text(translate("Start Service")))),
Expanded( Expanded(
@ -287,8 +292,8 @@ class _PermissionCheckerState extends State<PermissionChecker> {
Expanded( Expanded(
flex: 0, flex: 0,
child: Padding( child: Padding(
padding: padding: const EdgeInsets.only(
EdgeInsets.only(left: 20, right: 5), left: 20, right: 5),
child: Icon(Icons.circle, child: Icon(Icons.circle,
color: serverModel.connectStatus > 0 color: serverModel.connectStatus > 0
? Colors.greenAccent ? Colors.greenAccent
@ -297,12 +302,12 @@ class _PermissionCheckerState extends State<PermissionChecker> {
Expanded( Expanded(
child: Text(translate(status), child: Text(translate(status),
softWrap: true, softWrap: true,
style: TextStyle( style: const TextStyle(
fontSize: 14.0, fontSize: 14.0,
color: MyTheme.accent50))) color: MyTheme.accent50)))
], ],
) )
: SizedBox.shrink()) : const SizedBox.shrink())
], ],
), ),
], ],
@ -311,7 +316,8 @@ class _PermissionCheckerState extends State<PermissionChecker> {
} }
class PermissionRow extends StatelessWidget { class PermissionRow extends StatelessWidget {
PermissionRow(this.name, this.isOk, this.onPressed); const PermissionRow(this.name, this.isOk, this.onPressed, {Key? key})
: super(key: key);
final String name; final String name;
final bool isOk; final bool isOk;
@ -327,8 +333,8 @@ class PermissionRow extends StatelessWidget {
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text(name, child: Text(name,
style: style: const TextStyle(
TextStyle(fontSize: 16.0, color: MyTheme.accent50)))), fontSize: 16.0, color: MyTheme.accent50)))),
Expanded( Expanded(
flex: 2, flex: 2,
child: FittedBox( child: FittedBox(
@ -347,7 +353,7 @@ class PermissionRow extends StatelessWidget {
onPressed: onPressed, onPressed: onPressed,
child: Text( child: Text(
translate(isOk ? "CLOSE" : "OPEN"), translate(isOk ? "CLOSE" : "OPEN"),
style: TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(fontWeight: FontWeight.bold),
)))), )))),
], ],
); );
@ -355,6 +361,8 @@ class PermissionRow extends StatelessWidget {
} }
class ConnectionManager extends StatelessWidget { class ConnectionManager extends StatelessWidget {
const ConnectionManager({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serverModel = Provider.of<ServerModel>(context); final serverModel = Provider.of<ServerModel>(context);
@ -377,7 +385,7 @@ class ConnectionManager extends StatelessWidget {
Expanded( Expanded(
flex: -1, flex: -1,
child: client.isFileTransfer || !client.authorized child: client.isFileTransfer || !client.authorized
? SizedBox.shrink() ? const SizedBox.shrink()
: IconButton( : IconButton(
onPressed: () { onPressed: () {
gFFI.chatModel.changeCurrentID(client.id); gFFI.chatModel.changeCurrentID(client.id);
@ -388,24 +396,24 @@ class ConnectionManager extends StatelessWidget {
bar.onTap!(1); bar.onTap!(1);
} }
}, },
icon: Icon( icon: const Icon(
Icons.chat, Icons.chat,
color: MyTheme.accent80, color: MyTheme.accent80,
))) )))
], ],
), ),
client.authorized client.authorized
? SizedBox.shrink() ? const SizedBox.shrink()
: Text( : Text(
translate("android_new_connection_tip"), translate("android_new_connection_tip"),
style: TextStyle(color: Colors.black54), style: const TextStyle(color: Colors.black54),
), ),
client.authorized client.authorized
? ElevatedButton.icon( ? ElevatedButton.icon(
style: ButtonStyle( style: ButtonStyle(
backgroundColor: backgroundColor:
MaterialStateProperty.all(Colors.red)), MaterialStateProperty.all(Colors.red)),
icon: Icon(Icons.close), icon: const Icon(Icons.close),
onPressed: () { onPressed: () {
bind.cmCloseConnection(connId: client.id); bind.cmCloseConnection(connId: client.id);
gFFI.invokeMethod( gFFI.invokeMethod(
@ -418,7 +426,7 @@ class ConnectionManager extends StatelessWidget {
onPressed: () { onPressed: () {
serverModel.sendLoginResponse(client, false); serverModel.sendLoginResponse(client, false);
}), }),
SizedBox(width: 20), const SizedBox(width: 20),
ElevatedButton( ElevatedButton(
child: Text(translate("Accept")), child: Text(translate("Accept")),
onPressed: () { onPressed: () {
@ -432,7 +440,8 @@ class ConnectionManager extends StatelessWidget {
} }
class PaddingCard extends StatelessWidget { class PaddingCard extends StatelessWidget {
PaddingCard({required this.child, this.title, this.titleIcon}); const PaddingCard({Key? key, required this.child, this.title, this.titleIcon})
: super(key: key);
final String? title; final String? title;
final IconData? titleIcon; final IconData? titleIcon;
@ -445,18 +454,18 @@ class PaddingCard extends StatelessWidget {
children.insert( children.insert(
0, 0,
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 5.0), padding: const EdgeInsets.symmetric(vertical: 5.0),
child: Row( child: Row(
children: [ children: [
titleIcon != null titleIcon != null
? Padding( ? Padding(
padding: EdgeInsets.only(right: 10), padding: const EdgeInsets.only(right: 10),
child: Icon(titleIcon, child: Icon(titleIcon,
color: MyTheme.accent80, size: 30)) color: MyTheme.accent80, size: 30))
: SizedBox.shrink(), : const SizedBox.shrink(),
Text( Text(
title!, title!,
style: TextStyle( style: const TextStyle(
fontFamily: 'WorkSans', fontFamily: 'WorkSans',
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 20, fontSize: 20,
@ -466,12 +475,13 @@ class PaddingCard extends StatelessWidget {
], ],
))); )));
} }
return Container( return SizedBox(
width: double.maxFinite, width: double.maxFinite,
child: Card( child: Card(
margin: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0), margin: const EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0), padding:
const EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: children, children: children,
@ -483,27 +493,29 @@ class PaddingCard extends StatelessWidget {
Widget clientInfo(Client client) { Widget clientInfo(Client client) {
return Padding( return Padding(
padding: EdgeInsets.symmetric(vertical: 8), padding: const EdgeInsets.symmetric(vertical: 8),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Row( Row(
children: [ children: [
Expanded( Expanded(
flex: -1, flex: -1,
child: Padding( child: Padding(
padding: EdgeInsets.only(right: 12), padding: const EdgeInsets.only(right: 12),
child: CircleAvatar( child: CircleAvatar(
child: Text(client.name[0]), backgroundColor: MyTheme.border,
backgroundColor: MyTheme.border))), child: Text(client.name[0])))),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text(client.name, Text(client.name,
style: TextStyle(color: MyTheme.idColor, fontSize: 18)), style: const TextStyle(
SizedBox(width: 8), color: MyTheme.idColor, fontSize: 18)),
const SizedBox(width: 8),
Text(client.peerId, Text(client.peerId,
style: TextStyle(color: MyTheme.idColor, fontSize: 10)) style:
const TextStyle(color: MyTheme.idColor, fontSize: 10))
])) ]))
], ],
), ),

View File

@ -50,6 +50,7 @@ lazy_static::lazy_static! {
pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default(); pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default();
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned())); pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned()));
static ref KEY_PAIR: Arc<Mutex<Option<(Vec<u8>, Vec<u8>)>>> = Default::default(); static ref KEY_PAIR: Arc<Mutex<Option<(Vec<u8>, Vec<u8>)>>> = Default::default();
static ref HW_CODEC_CONFIG: Arc<RwLock<HwCodecConfig>> = Arc::new(RwLock::new(HwCodecConfig::load()));
} }
// #[cfg(any(target_os = "android", target_os = "ios"))] // #[cfg(any(target_os = "android", target_os = "ios"))]
@ -1023,6 +1024,16 @@ impl HwCodecConfig {
pub fn remove() { pub fn remove() {
std::fs::remove_file(Config::file_("_hwcodec")).ok(); std::fs::remove_file(Config::file_("_hwcodec")).ok();
} }
/// refresh current global HW_CODEC_CONFIG, usually uesd after HwCodecConfig::remove()
pub fn refresh() {
*HW_CODEC_CONFIG.write().unwrap() = HwCodecConfig::load();
log::debug!("HW_CODEC_CONFIG refreshed successfully");
}
pub fn get() -> HwCodecConfig {
return HW_CODEC_CONFIG.read().unwrap().clone();
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -267,7 +267,7 @@ impl HwDecoderImage<'_> {
} }
fn get_config(k: &str) -> ResultType<CodecInfos> { fn get_config(k: &str) -> ResultType<CodecInfos> {
let v = HwCodecConfig::load() let v = HwCodecConfig::get()
.options .options
.get(k) .get(k)
.unwrap_or(&"".to_owned()) .unwrap_or(&"".to_owned())
@ -323,7 +323,8 @@ pub fn check_config_process(force_reset: bool) {
std::process::Command::new(exe) std::process::Command::new(exe)
.arg("--check-hwcodec-config") .arg("--check-hwcodec-config")
.status() .status()
.ok() .ok();
HwCodecConfig::refresh();
}); });
}; };
} }

View File

@ -17,15 +17,15 @@ use crate::flutter::{self, SESSIONS};
use crate::start_server; use crate::start_server;
use crate::ui_interface; use crate::ui_interface;
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::ui_interface::{change_id, get_sound_inputs}; use crate::ui_interface::get_sound_inputs;
use crate::ui_interface::{ use crate::ui_interface::{
check_mouse_time, check_super_user_permission, discover, forget_password, get_api_server, change_id, check_mouse_time, check_super_user_permission, discover, forget_password,
get_app_name, get_async_job_status, get_connect_status, get_fav, get_id, get_lan_peers, get_api_server, get_app_name, get_async_job_status, get_connect_status, get_fav, get_id,
get_langs, get_license, get_local_option, get_mouse_time, get_option, get_options, get_peer, get_lan_peers, get_langs, get_license, get_local_option, get_mouse_time, get_option,
get_peer_option, get_socks, get_uuid, get_version, has_hwcodec, has_rendezvous_service, get_options, get_peer, get_peer_option, get_socks, get_uuid, get_version, has_hwcodec,
post_request, send_to_cm, set_local_option, set_option, set_options, set_peer_option, has_rendezvous_service, post_request, send_to_cm, set_local_option, set_option, set_options,
set_permanent_password, set_socks, store_fav, test_if_valid_server, update_temporary_password, set_peer_option, set_permanent_password, set_socks, store_fav, test_if_valid_server,
using_public_server, update_temporary_password, using_public_server,
}; };
use crate::{ use crate::{
client::file_trait::FileManager, client::file_trait::FileManager,
@ -426,7 +426,6 @@ pub fn main_get_sound_inputs() -> Vec<String> {
} }
pub fn main_change_id(new_id: String) { pub fn main_change_id(new_id: String) {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
change_id(new_id) change_id(new_id)
} }
@ -754,8 +753,8 @@ pub fn main_remove_peer(id: String) {
PeerConfig::remove(&id); PeerConfig::remove(&id);
} }
pub fn main_has_hwcodec() -> bool { pub fn main_has_hwcodec() -> SyncReturn<bool> {
has_hwcodec() SyncReturn(has_hwcodec())
} }
pub fn session_send_mouse(id: String, msg: String) { pub fn session_send_mouse(id: String, msg: String) {
@ -816,6 +815,22 @@ pub fn session_send_note(id: String, note: String) {
} }
} }
pub fn session_supported_hwcodec(id: String) -> String {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
let (h264, h265) = session.supported_hwcodec();
let msg = HashMap::from([("h264", h264), ("h265", h265)]);
serde_json::ser::to_string(&msg).unwrap_or("".to_owned())
} else {
String::new()
}
}
pub fn session_change_prefer_codec(id: String) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.change_prefer_codec();
}
}
pub fn main_set_home_dir(home: String) { pub fn main_set_home_dir(home: String) {
*config::APP_HOME_DIR.write().unwrap() = home; *config::APP_HOME_DIR.write().unwrap() = home;
} }

View File

@ -28,6 +28,7 @@ use hbb_common::{
use crate::clipboard_file::*; use crate::clipboard_file::*;
use crate::{ use crate::{
client::*, client::*,
ui_interface::has_hwcodec,
ui_session_interface::{InvokeUiSession, Session}, ui_session_interface::{InvokeUiSession, Session},
}; };
@ -440,6 +441,10 @@ impl SciterSession {
v v
} }
fn has_hwcodec(&self) -> bool {
has_hwcodec()
}
pub fn t(&self, name: String) -> String { pub fn t(&self, name: String) -> String {
crate::client::translate(name) crate::client::translate(name)
} }
@ -449,28 +454,12 @@ impl SciterSession {
} }
fn supported_hwcodec(&self) -> Value { fn supported_hwcodec(&self) -> Value {
#[cfg(feature = "hwcodec")] let (h264, h265) = self.0.supported_hwcodec();
{
let mut v = Value::array(0); let mut v = Value::array(0);
let decoder = scrap::codec::Decoder::video_codec_state(&self.id);
let mut h264 = decoder.score_h264 > 0;
let mut h265 = decoder.score_h265 > 0;
if let Some((encoding_264, encoding_265)) = self.lc.read().unwrap().supported_encoding {
h264 = h264 && encoding_264;
h265 = h265 && encoding_265;
}
v.push(h264); v.push(h264);
v.push(h265); v.push(h265);
v v
} }
#[cfg(not(feature = "hwcodec"))]
{
let mut v = Value::array(0);
v.push(false);
v.push(false);
v
}
}
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) { fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {
let size = (x, y, w, h); let size = (x, y, w, h);

View File

@ -687,7 +687,6 @@ pub fn open_url(url: String) {
} }
#[inline] #[inline]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub fn change_id(id: String) { pub fn change_id(id: String) {
*ASYNC_JOB_STATUS.lock().unwrap() = " ".to_owned(); *ASYNC_JOB_STATUS.lock().unwrap() = " ".to_owned();
let old_id = get_id(); let old_id = get_id();
@ -744,9 +743,9 @@ pub fn get_api_server() -> String {
#[inline] #[inline]
pub fn has_hwcodec() -> bool { pub fn has_hwcodec() -> bool {
#[cfg(not(feature = "hwcodec"))] #[cfg(not(any(feature = "hwcodec", feature = "mediacodec")))]
return false; return false;
#[cfg(feature = "hwcodec")] #[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
return true; return true;
} }
@ -864,17 +863,27 @@ pub(crate) async fn send_to_cm(data: &ipc::Data) {
const INVALID_FORMAT: &'static str = "Invalid format"; const INVALID_FORMAT: &'static str = "Invalid format";
const UNKNOWN_ERROR: &'static str = "Unknown error"; const UNKNOWN_ERROR: &'static str = "Unknown error";
#[cfg(not(any(target_os = "android", target_os = "ios")))]
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn change_id_(id: String, old_id: String) -> &'static str { async fn change_id_(id: String, old_id: String) -> &'static str {
if !hbb_common::is_valid_custom_id(&id) { if !hbb_common::is_valid_custom_id(&id) {
return INVALID_FORMAT; return INVALID_FORMAT;
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let uuid = machine_uid::get().unwrap_or("".to_owned()); let uuid = machine_uid::get().unwrap_or("".to_owned());
#[cfg(any(target_os = "android", target_os = "ios"))]
let uuid = base64::encode(hbb_common::get_uuid());
if uuid.is_empty() { if uuid.is_empty() {
log::error!("Failed to change id, uuid is_empty");
return UNKNOWN_ERROR; return UNKNOWN_ERROR;
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let rendezvous_servers = crate::ipc::get_rendezvous_servers(1_000).await; let rendezvous_servers = crate::ipc::get_rendezvous_servers(1_000).await;
#[cfg(any(target_os = "android", target_os = "ios"))]
let rendezvous_servers = Config::get_rendezvous_servers();
let mut futs = Vec::new(); let mut futs = Vec::new();
let err: Arc<Mutex<&str>> = Default::default(); let err: Arc<Mutex<&str>> = Default::default();
for rendezvous_server in rendezvous_servers { for rendezvous_server in rendezvous_servers {
@ -892,7 +901,13 @@ async fn change_id_(id: String, old_id: String) -> &'static str {
join_all(futs).await; join_all(futs).await;
let err = *err.lock().unwrap(); let err = *err.lock().unwrap();
if err.is_empty() { if err.is_empty() {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
crate::ipc::set_config_async("id", id.to_owned()).await.ok(); crate::ipc::set_config_async("id", id.to_owned()).await.ok();
#[cfg(any(target_os = "android", target_os = "ios"))]
{
Config::set_key_confirmed(false);
Config::set_id(&id);
}
} }
err err
} }
@ -937,6 +952,9 @@ async fn check_id(
register_pk_response::Result::NOT_SUPPORT => { register_pk_response::Result::NOT_SUPPORT => {
return "server_not_support"; return "server_not_support";
} }
register_pk_response::Result::SERVER_ERROR => {
return "Server error";
}
register_pk_response::Result::INVALID_ID_FORMAT => { register_pk_response::Result::INVALID_ID_FORMAT => {
return INVALID_FORMAT; return INVALID_FORMAT;
} }

View File

@ -11,9 +11,9 @@ use async_trait::async_trait;
use hbb_common::config::{Config, LocalConfig, PeerConfig}; use hbb_common::config::{Config, LocalConfig, PeerConfig};
use hbb_common::rendezvous_proto::ConnType; use hbb_common::rendezvous_proto::ConnType;
use hbb_common::tokio::{self, sync::mpsc}; use hbb_common::tokio::{self, sync::mpsc};
use rdev::{Event, EventType::*, Key as RdevKey, KeyboardState};
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use rdev::Keyboard as RdevKeyboard; use rdev::Keyboard as RdevKeyboard;
use rdev::{Event, EventType::*, Key as RdevKey, KeyboardState};
use hbb_common::{allow_err, message_proto::*}; use hbb_common::{allow_err, message_proto::*};
use hbb_common::{fs, get_version_number, log, Stream}; use hbb_common::{fs, get_version_number, log, Stream};
@ -136,11 +136,19 @@ impl<T: InvokeUiSession> Session<T> {
true true
} }
pub fn has_hwcodec(&self) -> bool { pub fn supported_hwcodec(&self) -> (bool, bool) {
#[cfg(not(feature = "hwcodec"))] #[cfg(any(feature = "hwcodec", feature = "mediacodec"))]
return false; {
#[cfg(feature = "hwcodec")] let decoder = scrap::codec::Decoder::video_codec_state(&self.id);
return true; let mut h264 = decoder.score_h264 > 0;
let mut h265 = decoder.score_h265 > 0;
if let Some((encoding_264, encoding_265)) = self.lc.read().unwrap().supported_encoding {
h264 = h264 && encoding_264;
h265 = h265 && encoding_265;
}
return (h264, h265);
}
(false, false)
} }
pub fn change_prefer_codec(&self) { pub fn change_prefer_codec(&self) {
@ -658,18 +666,20 @@ impl<T: InvokeUiSession> Session<T> {
} }
self.map_keyboard_mode(down_or_up, key, Some(evt)); self.map_keyboard_mode(down_or_up, key, Some(evt));
} }
KeyboardMode::Legacy => { KeyboardMode::Legacy =>
{
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.legacy_keyboard_mode(down_or_up, key, evt) self.legacy_keyboard_mode(down_or_up, key, evt)
}, }
KeyboardMode::Translate => { KeyboardMode::Translate => {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.translate_keyboard_mode(down_or_up, key, evt); self.translate_keyboard_mode(down_or_up, key, evt);
} }
_ => { _ =>
{
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.legacy_keyboard_mode(down_or_up, key, evt) self.legacy_keyboard_mode(down_or_up, key, evt)
}, }
} }
} }
@ -1178,7 +1188,7 @@ impl<T: InvokeUiSession> Session<T> {
if self.is_port_forward() || self.is_file_transfer() { if self.is_port_forward() || self.is_file_transfer() {
return; return;
} }
if !KEYBOARD_HOOKED.load(Ordering::SeqCst){ if !KEYBOARD_HOOKED.load(Ordering::SeqCst) {
return; return;
} }
log::info!("keyboard hooked"); log::info!("keyboard hooked");