diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index eca7fa05a..0650b1b5b 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -1578,7 +1578,7 @@ bool option2bool(String option, String value) { option == kOptionForceAlwaysRelay) { res = value == "Y"; } else { - assert(false); + // "" is true res = value != "N"; } return res; @@ -1596,9 +1596,6 @@ String bool2option(String option, bool b) { option == kOptionForceAlwaysRelay) { res = b ? 'Y' : defaultOptionNo; } else { - if (option != kOptionEnableUdpPunch && option != kOptionEnableIpv6Punch) { - assert(false); - } res = b ? 'Y' : 'N'; } return res; @@ -2684,20 +2681,44 @@ class SimpleWrapper { /// This manager handles multiple tabs within the same isolate. class WakelockManager { static final Set _enabledKeys = {}; + // Don't use WakelockPlus.enabled, it causes error on Android: + // Unhandled Exception: FormatException: Message corrupted + // + // On Linux, multiple enable() calls create only one inhibit, but each disable() + // only releases if _cookie != null. So we need our own _enabled state to avoid + // calling disable() when not enabled. + // See: https://github.com/fluttercommunity/wakelock_plus/blob/0c74e5bbc6aefac57b6c96bb7ef987705ed559ec/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart#L48 + static bool _enabled = false; - static void enable(UniqueKey key) { - if (isLinux) return; - _enabledKeys.add(key); - WakelockPlus.enable(); + static void enable(UniqueKey key, {bool isServer = false}) { + // Check if we should keep awake during outgoing sessions + if (!isServer) { + final keepAwake = + mainGetLocalBoolOptionSync(kOptionKeepAwakeDuringOutgoingSessions); + if (!keepAwake) { + return; // Don't enable wakelock if user disabled keep awake + } + } + if (isDesktop) { + _enabledKeys.add(key); + } + if (!_enabled) { + _enabled = true; + WakelockPlus.enable(); + } } static void disable(UniqueKey key) { - if (isLinux) return; - if (_enabledKeys.remove(key)) { - if (_enabledKeys.isEmpty) { - WakelockPlus.disable(); + if (isDesktop) { + _enabledKeys.remove(key); + if (_enabledKeys.isNotEmpty) { + return; } } + if (_enabled) { + WakelockPlus.disable(); + _enabled = false; + } } } diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 78b1f261a..3b9940c9c 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -194,6 +194,9 @@ const String kOptionDisableFloatingWindow = "disable-floating-window"; const String kOptionKeepScreenOn = "keep-screen-on"; +const String kOptionKeepAwakeDuringIncomingSessions = "keep-awake-during-incoming-sessions"; +const String kOptionKeepAwakeDuringOutgoingSessions = "keep-awake-during-outgoing-sessions"; + const String kOptionShowMobileAction = "showMobileActions"; const String kUrlActionClose = "close"; diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index a431efee4..b513bd4d9 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -557,6 +557,17 @@ class _GeneralState extends State<_General> { ], ], ]; + + // Add client-side wakelock option for desktop platforms + if (!bind.isIncomingOnly()) { + children.add(_OptionCheckBox( + context, + 'keep-awake-during-outgoing-sessions-label', + kOptionKeepAwakeDuringOutgoingSessions, + isServer: false, + )); + } + if (!isWeb && bind.mainShowOption(key: kOptionAllowLinuxHeadless)) { children.add(_OptionCheckBox( context, 'Allow linux headless', kOptionAllowLinuxHeadless)); @@ -1219,6 +1230,9 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin { ...directIp(context), whitelist(), ...autoDisconnect(context), + _OptionCheckBox(context, 'keep-awake-during-incoming-sessions-label', + kOptionKeepAwakeDuringIncomingSessions, + reverse: false, enabled: enabled), if (bind.mainIsInstalled()) _OptionCheckBox(context, 'allow-only-conn-window-open-tip', 'allow-only-conn-window-open', diff --git a/flutter/lib/mobile/pages/file_manager_page.dart b/flutter/lib/mobile/pages/file_manager_page.dart index 745df67b5..1e793bca7 100644 --- a/flutter/lib/mobile/pages/file_manager_page.dart +++ b/flutter/lib/mobile/pages/file_manager_page.dart @@ -5,7 +5,6 @@ import 'package:flutter_breadcrumb/flutter_breadcrumb.dart'; import 'package:flutter_hbb/models/file_model.dart'; import 'package:get/get.dart'; import 'package:toggle_switch/toggle_switch.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; import '../../common.dart'; import '../../common/widgets/dialog.dart'; @@ -72,6 +71,7 @@ class _FileManagerPageState extends State { showLocal ? model.localController : model.remoteController; FileDirectory get currentDir => currentFileController.directory.value; DirectoryOptions get currentOptions => currentFileController.options.value; + final _uniqueKey = UniqueKey(); @override void initState() { @@ -86,7 +86,7 @@ class _FileManagerPageState extends State { .showLoading(translate('Connecting...'), onCancel: closeConnection); }); gFFI.ffiModel.updateEventListener(gFFI.sessionId, widget.id); - WakelockPlus.enable(); + WakelockManager.enable(_uniqueKey); } @override @@ -94,7 +94,7 @@ class _FileManagerPageState extends State { model.close().whenComplete(() { gFFI.close(); gFFI.dialogManager.dismissAll(); - WakelockPlus.disable(); + WakelockManager.disable(_uniqueKey); }); model.jobController.clear(); super.dispose(); diff --git a/flutter/lib/mobile/pages/remote_page.dart b/flutter/lib/mobile/pages/remote_page.dart index 22dbebce6..1850f2093 100644 --- a/flutter/lib/mobile/pages/remote_page.dart +++ b/flutter/lib/mobile/pages/remote_page.dart @@ -14,7 +14,6 @@ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; import '../../common.dart'; import '../../common/widgets/overlay.dart'; @@ -67,7 +66,7 @@ class _RemotePageState extends State with WidgetsBindingObserver { String _value = ''; Orientation? _currentOrientation; double _viewInsetsBottom = 0; - + final _uniqueKey = UniqueKey(); Timer? _timerDidChangeMetrics; final _blockableOverlayState = BlockableOverlayState(); @@ -105,9 +104,7 @@ class _RemotePageState extends State with WidgetsBindingObserver { gFFI.dialogManager .showLoading(translate('Connecting...'), onCancel: closeConnection); }); - if (!isWeb) { - WakelockPlus.enable(); - } + WakelockManager.enable(_uniqueKey); _physicalFocusNode.requestFocus(); gFFI.inputModel.listenToMouse(true); gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId); @@ -146,9 +143,7 @@ class _RemotePageState extends State with WidgetsBindingObserver { gFFI.dialogManager.dismissAll(); await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values); - if (!isWeb) { - await WakelockPlus.disable(); - } + WakelockManager.disable(_uniqueKey); await keyboardSubscription.cancel(); removeSharedStates(widget.id); // `on_voice_call_closed` should be called when the connection is ended. diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index afe8ae446..c2e2ef57d 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -100,6 +100,7 @@ class _SettingsState extends State with WidgetsBindingObserver { var _enableIpv6Punch = false; var _isUsingPublicServer = false; var _allowAskForNoteAtEndOfConnection = false; + var _preventSleepWhileConnected = true; _SettingsState() { _enableAbr = option2bool( @@ -140,6 +141,8 @@ class _SettingsState extends State with WidgetsBindingObserver { _enableIpv6Punch = mainGetLocalBoolOptionSync(kOptionEnableIpv6Punch); _allowAskForNoteAtEndOfConnection = mainGetLocalBoolOptionSync(kOptionAllowAskForNoteAtEndOfConnection); + _preventSleepWhileConnected = + mainGetLocalBoolOptionSync(kOptionKeepAwakeDuringOutgoingSessions); _showTerminalExtraKeys = mainGetLocalBoolOptionSync(kOptionEnableShowTerminalExtraKeys); } @@ -823,7 +826,18 @@ class _SettingsState extends State with WidgetsBindingObserver { _allowAskForNoteAtEndOfConnection = newValue; }); }, - ) + ), + if (!incomingOnly) + SettingsTile.switchTile( + title: Text(translate('keep-awake-during-outgoing-sessions-label')), + initialValue: _preventSleepWhileConnected, + onToggle: (v) async { + await mainSetLocalBoolOption(kOptionKeepAwakeDuringOutgoingSessions, v); + setState(() { + _preventSleepWhileConnected = v; + }); + }, + ), ]), if (isAndroid) SettingsSection(title: Text(translate('Hardware Codec')), tiles: [ diff --git a/flutter/lib/mobile/pages/view_camera_page.dart b/flutter/lib/mobile/pages/view_camera_page.dart index 018d22980..0898125c4 100644 --- a/flutter/lib/mobile/pages/view_camera_page.dart +++ b/flutter/lib/mobile/pages/view_camera_page.dart @@ -11,7 +11,6 @@ import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; import '../../common.dart'; import '../../common/widgets/overlay.dart'; @@ -62,7 +61,7 @@ class _ViewCameraPageState extends State bool _showGestureHelp = false; Orientation? _currentOrientation; double _viewInsetsBottom = 0; - + final _uniqueKey = UniqueKey(); Timer? _timerDidChangeMetrics; final _blockableOverlayState = BlockableOverlayState(); @@ -100,9 +99,7 @@ class _ViewCameraPageState extends State gFFI.dialogManager .showLoading(translate('Connecting...'), onCancel: closeConnection); }); - if (!isWeb) { - WakelockPlus.enable(); - } + WakelockManager.enable(_uniqueKey); _physicalFocusNode.requestFocus(); gFFI.inputModel.listenToMouse(true); gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId); @@ -139,9 +136,7 @@ class _ViewCameraPageState extends State gFFI.dialogManager.dismissAll(); await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values); - if (!isWeb) { - await WakelockPlus.disable(); - } + WakelockManager.disable(_uniqueKey); removeSharedStates(widget.id); // `on_voice_call_closed` should be called when the connection is ended. // The inner logic of `on_voice_call_closed` will check if the voice call is active. diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart index c3e6fab71..8ead158ac 100644 --- a/flutter/lib/models/server_model.dart +++ b/flutter/lib/models/server_model.dart @@ -8,7 +8,6 @@ import 'package:flutter_hbb/mobile/pages/settings_page.dart'; import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:get/get.dart'; -import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:window_manager/window_manager.dart'; import '../common.dart'; @@ -51,6 +50,8 @@ class ServerModel with ChangeNotifier { Timer? cmHiddenTimer; + final _wakelockKey = UniqueKey(); + bool get isStart => _isStart; bool get mediaOk => _mediaOk; @@ -466,10 +467,8 @@ class ServerModel with ChangeNotifier { await parent.target?.invokeMethod("stop_service"); await bind.mainStopService(); notifyListeners(); - if (!isLinux) { - // current linux is not supported - WakelockPlus.disable(); - } + // for androidUpdatekeepScreenOn only + WakelockManager.disable(_wakelockKey); } Future setPermanentPassword(String newPW) async { @@ -613,12 +612,12 @@ class ServerModel with ChangeNotifier { void showLoginDialog(Client client) { showClientDialog( client, - client.isFileTransfer - ? "Transfer file" + client.isFileTransfer + ? "Transfer file" : client.isViewCamera ? "View camera" - : client.isTerminal - ? "Terminal" + : client.isTerminal + ? "Terminal" : "Share screen", 'Do you accept?', 'android_new_connection_tip', @@ -797,12 +796,10 @@ class ServerModel with ChangeNotifier { final on = ((keepScreenOn == KeepScreenOn.serviceOn) && _isStart) || (keepScreenOn == KeepScreenOn.duringControlled && _clients.map((e) => !e.disconnected).isNotEmpty); - if (on != await WakelockPlus.enabled) { - if (on) { - WakelockPlus.enable(); - } else { - WakelockPlus.disable(); - } + if (on) { + WakelockManager.enable(_wakelockKey, isServer: true); + } else { + WakelockManager.disable(_wakelockKey); } } } diff --git a/libs/hbb_common b/libs/hbb_common index 073403edb..7d93d5af4 160000 --- a/libs/hbb_common +++ b/libs/hbb_common @@ -1 +1 @@ -Subproject commit 073403edbf1fffcb3acfe8cbe7582ee873b23398 +Subproject commit 7d93d5af48db34dbd4a9d317e4a69d04b0bcf703 diff --git a/libs/portable/src/main.rs b/libs/portable/src/main.rs index 1c754cc74..b7ff44ec5 100644 --- a/libs/portable/src/main.rs +++ b/libs/portable/src/main.rs @@ -187,7 +187,10 @@ fn main() { i += 1; } let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe"); + #[cfg(windows)] let quick_support = args.is_empty() && win::is_quick_support_exe(&arg_exe); + #[cfg(not(windows))] + let quick_support = false; let mut ui = false; let reader = BinaryReader::default(); diff --git a/src/lang/ar.rs b/src/lang/ar.rs index cee43eaad..14f74f048 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/be.rs b/src/lang/be.rs index 6d090d45f..7e0322deb 100644 --- a/src/lang/be.rs +++ b/src/lang/be.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/bg.rs b/src/lang/bg.rs index e7e56f22b..573a7824e 100644 --- a/src/lang/bg.rs +++ b/src/lang/bg.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index fc75a83b9..adbbd3d09 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 1f3b02577..24a2bf5cc 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "按下 {} 退出"), ("rel-mouse-permission-lost-tip", "键盘权限被撤销。相对鼠标模式已被禁用。"), ("Changelog", "更新日志"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index ccba57553..ff8b9856a 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index c90fa7118..9d0b6960a 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index f7521daff..86545b3df 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Drücken Sie {} zum Beenden."), ("rel-mouse-permission-lost-tip", "Die Tastaturberechtigung wurde widerrufen. Der relative Mausmodus wurde deaktiviert."), ("Changelog", "Änderungsprotokoll"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index edfa93e55..caf0b4566 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 60cb7b123..1399601de 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -267,5 +267,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-lock-failed-tip", "Failed to lock cursor. Relative Mouse Mode has been disabled."), ("rel-mouse-exit-{}-tip", "Press {} to exit."), ("rel-mouse-permission-lost-tip", "Keyboard permission was revoked. Relative Mouse Mode has been disabled."), + ("keep-awake-during-outgoing-sessions-label", "Keep screen awake during outgoing sessions"), + ("keep-awake-during-incoming-sessions-label", "Keep screen awake during incoming sessions"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index c41845731..5edd85ccf 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index d6958e643..a6e010568 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/et.rs b/src/lang/et.rs index f78990e99..910db4df7 100644 --- a/src/lang/et.rs +++ b/src/lang/et.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/eu.rs b/src/lang/eu.rs index cb1fdc143..daaedb24c 100644 --- a/src/lang/eu.rs +++ b/src/lang/eu.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 18d331007..47df53bc9 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fi.rs b/src/lang/fi.rs index 00f9692c4..d63d8ce20 100644 --- a/src/lang/fi.rs +++ b/src/lang/fi.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 6a4f4b562..a5deb4596 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Appuyez sur {} pour quitter."), ("rel-mouse-permission-lost-tip", "L’autorisation de contrôle du clavier a été révoquée. Le mode souris relative a été désactivé."), ("Changelog", "Journal des modifications"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ge.rs b/src/lang/ge.rs index e59fca4dd..178906587 100644 --- a/src/lang/ge.rs +++ b/src/lang/ge.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/he.rs b/src/lang/he.rs index a92905bd9..3a58c1235 100644 --- a/src/lang/he.rs +++ b/src/lang/he.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hr.rs b/src/lang/hr.rs index e998b0672..b946ab2de 100644 --- a/src/lang/hr.rs +++ b/src/lang/hr.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index d7b82ff7a..609773681 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "A kilépéshez nyomja meg a(z) {} gombot."), ("rel-mouse-permission-lost-tip", "A billentyűzet-hozzáférés vissza lett vonva. A relatív egérmód le lett tilva."), ("Changelog", "Változáslista"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 0bd200e4b..d4e6290ac 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 3785f5e0d..5bb4f2349 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Premi {} per uscire."), ("rel-mouse-permission-lost-tip", "È stata revocato l'accesso alla tastiera. La modalità mouse relativa è stata disabilitata."), ("Changelog", "Novità programma"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index fd479c266..989432c87 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 812c87e7c..1c3200629 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "종료하려면 {}을(를) 누르세요."), ("rel-mouse-permission-lost-tip", "키보드 권한이 취소되었습니다. 상대 마우스 모드가 비활성화되었습니다."), ("Changelog", "변경 기록"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 9f5cabc78..74a709f46 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 0e0711d4d..fd0c0df77 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index 20a1abb94..820b67f1e 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nb.rs b/src/lang/nb.rs index 67bfebdf7..e812b174b 100644 --- a/src/lang/nb.rs +++ b/src/lang/nb.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 2c3400dc8..c5627abfd 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Druk op {} om af te sluiten."), ("rel-mouse-permission-lost-tip", "De toetsenbordcontrole is uitgeschakeld. De relatieve muismodus is uitgeschakeld."), ("Changelog", "Wijzigingenlogboek"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 955d55b2c..9f71948ab 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Aby wyłączyć tryb przechwytywania myszy, naciśnij {}"), ("rel-mouse-permission-lost-tip", "Utracono uprawnienia do trybu przechwytywania myszy"), ("Changelog", "Dziennik zmian"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index d97013c90..0a851273c 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 25624b87f..ed8f2a4ba 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index bd76b34c3..54469bfda 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index ecc768a59..d9a7f15b7 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Нажмите {} для выхода."), ("rel-mouse-permission-lost-tip", "Разрешение на использование клавиатуры отменено. Режим относительного перемещения мыши отключён."), ("Changelog", "Журнал изменений"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sc.rs b/src/lang/sc.rs index a775bf234..ef1e160b2 100644 --- a/src/lang/sc.rs +++ b/src/lang/sc.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index efbcac7ed..75ef252e9 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index bf0a1e6b4..eb757f613 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 8f1e333a4..adf64a108 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 407725e9b..ae2170c28 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index d82883dc2..917306a30 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ta.rs b/src/lang/ta.rs index a4ac03d78..460b0dca9 100644 --- a/src/lang/ta.rs +++ b/src/lang/ta.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index a0a8e31c8..936eef3e1 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 86b3522d3..a36b7f61b 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 00b76b0c3..f81bfdca7 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -735,7 +735,9 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-not-ready-tip", "Göreli fare modu henüz hazır değil"), ("rel-mouse-lock-failed-tip", "Göreli fare kilitlenemedi"), ("rel-mouse-exit-{}-tip", "Göreli fare modundan çıkmak için {}"), - ("rel-mouse-permission-lost-tip", "Göreli fare izinleri geçerli değil"), + ("rel-mouse-permission-lost-tip", "Göreli fare izinleri geçerli değil"), ("Changelog", "Değişiklik Günlüğü"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index e93ae0f15..6bde1e7c8 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/uk.rs b/src/lang/uk.rs index 7c58f7e91..8c2acdd3e 100644 --- a/src/lang/uk.rs +++ b/src/lang/uk.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", ""), ("rel-mouse-permission-lost-tip", ""), ("Changelog", ""), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vi.rs b/src/lang/vi.rs index 3d03966da..4f9611840 100644 --- a/src/lang/vi.rs +++ b/src/lang/vi.rs @@ -737,5 +737,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("rel-mouse-exit-{}-tip", "Thoát chế độ chuột tương đối: {}"), ("rel-mouse-permission-lost-tip", "Mất quyền điều khiển chuột tương đối."), ("Changelog", "Nhật ký thay đổi"), + ("keep-awake-during-outgoing-sessions-label", ""), + ("keep-awake-during-incoming-sessions-label", ""), ].iter().cloned().collect(); } diff --git a/src/server/connection.rs b/src/server/connection.rs index d28373459..f90aad115 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -74,6 +74,7 @@ lazy_static::lazy_static! { pub static ref CONTROL_PERMISSIONS_ARRAY: Arc::>> = Default::default(); static ref SWITCH_SIDES_UUID: Arc::>> = Default::default(); static ref WAKELOCK_SENDER: Arc::>> = Arc::new(Mutex::new(start_wakelock_thread())); + static ref WAKELOCK_KEEP_AWAKE_OPTION: Arc::>> = Default::default(); } #[cfg(any(target_os = "windows", target_os = "linux"))] @@ -906,6 +907,7 @@ impl Connection { _ = second_timer.tick() => { #[cfg(windows)] conn.portable_check(); + raii::AuthedConnID::check_wake_lock_on_setting_changed(); if let Some((instant, minute)) = conn.auto_disconnect_timer.as_ref() { if instant.elapsed().as_secs() > minute * 60 { conn.send_close_reason_no_retry("Connection failed due to inactivity").await; @@ -5008,6 +5010,7 @@ impl FileRemoveLogControl { } fn start_wakelock_thread() -> std::sync::mpsc::Sender<(usize, usize)> { + // Check if we should keep awake during incoming sessions use crate::platform::{get_wakelock, WakeLock}; let (tx, rx) = std::sync::mpsc::channel::<(usize, usize)>(); std::thread::spawn(move || { @@ -5016,9 +5019,15 @@ fn start_wakelock_thread() -> std::sync::mpsc::Sender<(usize, usize)> { loop { match rx.recv() { Ok((conn_count, remote_count)) => { - if conn_count == 0 { - wakelock = None; - log::info!("drop wakelock"); + let keep_awake = config::Config::get_bool_option( + keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS, + ); + *WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap() = Some(keep_awake); + if conn_count == 0 || !keep_awake { + if wakelock.is_some() { + wakelock = None; + log::info!("drop wakelock"); + } } else { let mut display = remote_count > 0; if let Some(_w) = wakelock.as_mut() { @@ -5329,6 +5338,16 @@ mod raii { .send((conn_count, remote_count))); } + pub fn check_wake_lock_on_setting_changed() { + let current = config::Config::get_bool_option( + keys::OPTION_KEEP_AWAKE_DURING_INCOMING_SESSIONS, + ); + let cached = *WAKELOCK_KEEP_AWAKE_OPTION.lock().unwrap(); + if cached != Some(current) { + Self::check_wake_lock(); + } + } + #[cfg(windows)] pub fn non_port_forward_conn_count() -> usize { AUTHED_CONNS diff --git a/src/ui/index.tis b/src/ui/index.tis index 8dd4da3d4..09aa0c306 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -268,6 +268,7 @@ class Enhancements: Reactor.Component {
  • {svg_checkmark}{translate("Adaptive bitrate")} (beta)
  • {translate("Recording")}
  • {support_remove_wallpaper ?
  • {svg_checkmark}{translate("Remove wallpaper during incoming sessions")}
  • : ""} +
  • {svg_checkmark}{translate("keep-awake-during-incoming-sessions-label")}
  • ; } @@ -288,6 +289,13 @@ class Enhancements: Reactor.Component { if (is_opt_fixed) { el.state.disabled = true; } + } else if (el.id == "keep-awake-during-incoming-sessions") { + var enabled = handler.get_option(el.id) != "N"; + el.attributes.toggleClass("selected", enabled); + var is_opt_fixed = handler.is_option_fixed(el.id); + if (is_opt_fixed) { + el.state.disabled = true; + } } } @@ -304,6 +312,8 @@ class Enhancements: Reactor.Component { } } else if (v.indexOf("allow-") == 0) { handler.set_option(v, handler.get_option(v) == 'Y' ? default_option_no : 'Y'); + } else if (v == 'keep-awake-during-incoming-sessions') { + handler.set_option(v, handler.get_option(v) != 'N' ? 'N' : default_option_yes); } else if (v == 'screen-recording') { var show_root_dir = is_win && handler.is_installed(); var user_dir = handler.video_save_directory(false);