diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index bc5b19c97..53e304596 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -959,7 +959,6 @@ class CustomAlertDialog extends StatelessWidget { void msgBox(SessionID sessionId, String type, String title, String text, String link, OverlayDialogManager dialogManager, {bool? hasCancel, ReconnectHandle? reconnect, int? reconnectTimeout}) { - dialogManager.dismissAll(); List buttons = []; bool hasOk = false; @@ -2766,6 +2765,8 @@ parseParamScreenRect(Map params) { return screenRect; } +get isInputSourceFlutter => stateGlobal.getInputSource() == "Input source 2"; + class _ReconnectCountDownButton extends StatefulWidget { _ReconnectCountDownButton({ Key? key, diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 4236e96d4..00d9c5bd1 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -45,6 +45,7 @@ const String kAppTypeDesktopPortForward = "port forward"; const String kWindowMainWindowOnTop = "main_window_on_top"; const String kWindowGetWindowInfo = "get_window_info"; const String kWindowGetScreenList = "get_screen_list"; +// This method is not used, maybe it can be removed. const String kWindowDisableGrabKeyboard = "disable_grab_keyboard"; const String kWindowActionRebuild = "rebuild"; const String kWindowEventHide = "hide"; @@ -68,6 +69,8 @@ const String kOptionOpenInTabs = "allow-open-in-tabs"; const String kOptionOpenInWindows = "allow-open-in-windows"; const String kOptionForceAlwaysRelay = "force-always-relay"; +const String kOptionInputSource = "input-source"; + const String kUniLinksPrefix = "rustdesk://"; const String kUrlActionClose = "close"; diff --git a/flutter/lib/desktop/pages/remote_tab_page.dart b/flutter/lib/desktop/pages/remote_tab_page.dart index c97a0ef3f..dee2d2e29 100644 --- a/flutter/lib/desktop/pages/remote_tab_page.dart +++ b/flutter/lib/desktop/pages/remote_tab_page.dart @@ -156,7 +156,7 @@ class _ConnectionTabPageState extends State { ), )); } else if (call.method == kWindowDisableGrabKeyboard) { - stateGlobal.grabKeyboard = false; + // ??? } else if (call.method == "onDestroy") { tabController.clear(); } else if (call.method == kWindowActionRebuild) { diff --git a/flutter/lib/desktop/screen/desktop_remote_screen.dart b/flutter/lib/desktop/screen/desktop_remote_screen.dart index 4427cf8a3..255f1a5b2 100644 --- a/flutter/lib/desktop/screen/desktop_remote_screen.dart +++ b/flutter/lib/desktop/screen/desktop_remote_screen.dart @@ -12,9 +12,8 @@ class DesktopRemoteScreen extends StatelessWidget { final Map params; DesktopRemoteScreen({Key? key, required this.params}) : super(key: key) { - if (!bind.mainStartGrabKeyboard()) { - stateGlobal.grabKeyboard = true; - } + bind.mainInitInputSource(); + stateGlobal.getInputSource(force: true); } @override diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart index 271879428..36f11defc 100644 --- a/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart @@ -1585,7 +1585,7 @@ class _KeyboardMenu extends StatelessWidget { // If use flutter to grab keys, we can only use one mode. // Map mode and Legacy mode, at least one of them is supported. String? modeOnly; - if (stateGlobal.grabKeyboard) { + if (isInputSourceFlutter) { if (bind.sessionIsKeyboardModeSupported( sessionId: ffi.sessionId, mode: kKeyMapMode)) { modeOnly = kKeyMapMode; @@ -1604,6 +1604,8 @@ class _KeyboardMenu extends StatelessWidget { keyboardMode(modeOnly), localKeyboardType(), Divider(), + inputSource(), + Divider(), viewMode(), Divider(), reverseMouseWheel(), @@ -1678,6 +1680,39 @@ class _KeyboardMenu extends StatelessWidget { ); } + inputSource() { + final supportedInputSource = bind.mainSupportedInputSource(); + if (supportedInputSource.isEmpty) return Offstage(); + late final List supportedInputSourceList; + try { + supportedInputSourceList = jsonDecode(supportedInputSource); + } catch (e) { + debugPrint('Failed to decode $supportedInputSource, $e'); + return; + } + if (supportedInputSourceList.length < 2) return Offstage(); + final inputSource = stateGlobal.getInputSource(); + final enabled = !ffi.ffiModel.viewOnly; + return Column( + children: supportedInputSourceList.map((e) { + final d = e as List; + return RdoMenuButton( + child: Text(translate(d[1] as String)), + value: d[0] as String, + groupValue: inputSource, + onChanged: enabled + ? (e) { + if (e != null) { + stateGlobal.setInputSource(e); + } + } + : null, + ffi: ffi, + ); + }).toList(), + ); + } + viewMode() { final ffiModel = ffi.ffiModel; final enabled = versionCmp(pi.version, '1.2.0') >= 0 && ffiModel.keyboard; diff --git a/flutter/lib/models/input_model.dart b/flutter/lib/models/input_model.dart index 29c13f625..156a1201b 100644 --- a/flutter/lib/models/input_model.dart +++ b/flutter/lib/models/input_model.dart @@ -13,7 +13,6 @@ import '../../models/model.dart'; import '../../models/platform_model.dart'; import '../common.dart'; import '../consts.dart'; -import './state_model.dart'; /// Mouse button enum. enum MouseButtons { left, right, wheel } @@ -91,7 +90,7 @@ class InputModel { } KeyEventResult handleRawKeyEvent(FocusNode data, RawKeyEvent e) { - if (isDesktop && !stateGlobal.grabKeyboard) { + if (isDesktop && !isInputSourceFlutter) { return KeyEventResult.handled; } @@ -325,7 +324,9 @@ class InputModel { resetModifiers(); } _flingTimer?.cancel(); - bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter); + if (!isInputSourceFlutter) { + bind.sessionEnterOrLeave(sessionId: sessionId, enter: enter); + } } /// Send mouse movement event with distance in [x] and [y]. @@ -396,7 +397,8 @@ class InputModel { } if (x != 0 || y != 0) { if (peerPlatform == kPeerPlatformAndroid) { - handlePointerEvent('touch', 'pan_update', Offset(x.toDouble(), y.toDouble())); + handlePointerEvent( + 'touch', 'pan_update', Offset(x.toDouble(), y.toDouble())); } else { bind.sessionSendMouse( sessionId: sessionId, diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index 2de85aa11..78d1a273a 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -744,8 +744,7 @@ class FfiModel with ChangeNotifier { } // If current keyboard mode is not supported, change to another one. - - if (stateGlobal.grabKeyboard) { + if (isInputSourceFlutter) { for (final mode in [kKeyMapMode, kKeyLegacyMode]) { if (bind.sessionIsKeyboardModeSupported( sessionId: sessionId, mode: mode)) { diff --git a/flutter/lib/models/native_model.dart b/flutter/lib/models/native_model.dart index ef74a17a2..6778cdbb9 100644 --- a/flutter/lib/models/native_model.dart +++ b/flutter/lib/models/native_model.dart @@ -153,10 +153,10 @@ class PlatformFFI { AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; name = '${androidInfo.brand}-${androidInfo.model}'; id = androidInfo.id.hashCode.toString(); - androidVersion = androidInfo.version.sdkInt ?? 0; + androidVersion = androidInfo.version.sdkInt; } else if (Platform.isIOS) { IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - name = iosInfo.utsname.machine ?? ''; + name = iosInfo.utsname.machine; id = iosInfo.identifierForVendor.hashCode.toString(); } else if (Platform.isLinux) { LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo; diff --git a/flutter/lib/models/state_model.dart b/flutter/lib/models/state_model.dart index c80c3551e..4814bfcfe 100644 --- a/flutter/lib/models/state_model.dart +++ b/flutter/lib/models/state_model.dart @@ -5,12 +5,12 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../consts.dart'; +import './platform_model.dart'; enum SvcStatus { notReady, connecting, ready } class StateGlobal { int _windowId = -1; - bool grabKeyboard = false; final RxBool _fullscreen = false.obs; bool _isMinimized = false; final RxBool isMaximized = false.obs; @@ -22,6 +22,8 @@ class StateGlobal { // Only used for macOS bool? closeOnFullscreen; + String _inputSource = ''; + // Use for desktop -> remote toolbar -> resolution final Map> _lastResolutionGroupValues = {}; @@ -94,6 +96,18 @@ class StateGlobal { } } + String getInputSource({bool force = false}) { + if (force || _inputSource.isEmpty) { + _inputSource = bind.mainGetLocalOption(key: kOptionInputSource); + } + return _inputSource; + } + + void setInputSource(String v) async { + await bind.mainSetLocalOption(key: kOptionInputSource, value: v); + _inputSource = bind.mainGetLocalOption(key: kOptionInputSource); + } + StateGlobal._(); static final StateGlobal instance = StateGlobal._(); diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 106bc64e8..ea2894e57 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -469,13 +469,15 @@ pub fn session_handle_flutter_key_event( // This will cause the keyboard input to take no effect. pub fn session_enter_or_leave(_session_id: SessionID, _enter: bool) -> SyncReturn<()> { #[cfg(not(any(target_os = "android", target_os = "ios")))] - if let Some(session) = sessions::get_session_by_session_id(&_session_id) { - let keyboard_mode = session.get_keyboard_mode(); - if _enter { - set_cur_session_id_(_session_id, &keyboard_mode); - session.enter(keyboard_mode); - } else { - session.leave(keyboard_mode); + if crate::keyboard::input_source::is_cur_input_source_rdev() { + if let Some(session) = sessions::get_session_by_session_id(&_session_id) { + let keyboard_mode = session.get_keyboard_mode(); + if _enter { + set_cur_session_id_(_session_id, &keyboard_mode); + session.enter(keyboard_mode); + } else { + session.leave(keyboard_mode); + } } } SyncReturn(()) @@ -846,7 +848,12 @@ pub fn main_post_request(url: String, body: String, header: String) { } pub fn main_get_local_option(key: String) -> SyncReturn { - SyncReturn(get_local_option(key)) + let v = if key == crate::keyboard::input_source::CONFIG_OPTION_INPUT_SOURCE { + crate::keyboard::input_source::get_cur_session_input_source() + } else { + get_local_option(key) + }; + SyncReturn(v) } pub fn main_get_env(key: String) -> SyncReturn { @@ -854,7 +861,11 @@ pub fn main_get_env(key: String) -> SyncReturn { } pub fn main_set_local_option(key: String, value: String) { - set_local_option(key, value) + if key == crate::keyboard::input_source::CONFIG_OPTION_INPUT_SOURCE { + crate::keyboard::input_source::change_input_source(&value); + } else { + set_local_option(key, value); + } } pub fn main_get_my_id() -> String { @@ -1593,16 +1604,10 @@ pub fn main_is_installed() -> SyncReturn { SyncReturn(is_installed()) } -pub fn main_start_grab_keyboard() -> SyncReturn { - #[cfg(target_os = "linux")] - if !crate::platform::linux::is_x11() { - return SyncReturn(false); - } - crate::keyboard::client::start_grab_loop(); - if !is_can_input_monitoring(false) { - return SyncReturn(false); - } - SyncReturn(true) +pub fn main_init_input_source() -> SyncReturn<()> { + #[cfg(not(any(target_os = "android", target_os = "ios")))] + crate::keyboard::input_source::init_input_source(); + SyncReturn(()) } pub fn main_is_installed_lower_version() -> SyncReturn { @@ -1979,6 +1984,20 @@ pub fn main_supported_privacy_mode_impls() -> SyncReturn { ) } +pub fn main_supported_input_source() -> SyncReturn { + #[cfg(any(target_os = "android", target_os = "ios"))] + { + SyncReturn("".to_owned()) + } + #[cfg(not(any(target_os = "android", target_os = "ios")))] + { + SyncReturn( + serde_json::to_string(&crate::keyboard::input_source::get_supported_input_source()) + .unwrap_or_default(), + ) + } +} + #[cfg(target_os = "android")] pub mod server_side { use hbb_common::{config, log}; diff --git a/src/keyboard.rs b/src/keyboard.rs index be2827c3d..3d4c1550d 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -52,18 +52,6 @@ lazy_static::lazy_static! { pub mod client { use super::*; - lazy_static::lazy_static! { - static ref IS_GRAB_STARTED: Arc> = Arc::new(Mutex::new(false)); - } - - pub fn start_grab_loop() { - let mut lock = IS_GRAB_STARTED.lock().unwrap(); - if *lock { - return; - } - super::start_grab_loop(); - *lock = true; - } #[cfg(not(any(target_os = "android", target_os = "ios")))] pub fn change_grab_status(state: GrabState, keyboard_mode: &str) { @@ -327,6 +315,14 @@ pub fn start_grab_loop() { }; } +pub fn stop_grab_loop() -> Result<(), rdev::GrabError> { + #[cfg(any(target_os = "windows", target_os = "macos"))] + rdev::exit_grab()?; + #[cfg(target_os = "linux")] + rdev::exit_grab_listen()?; + Ok(()) +} + pub fn is_long_press(event: &Event) -> bool { let keys = MODIFIERS_STATE.lock().unwrap(); match event.event_type { @@ -1076,3 +1072,109 @@ pub fn keycode_to_rdev_key(keycode: u32) -> Key { #[cfg(target_os = "macos")] return rdev::macos_key_from_code(keycode.try_into().unwrap_or_default()); } + +#[cfg(feature = "flutter")] +#[cfg(not(any(target_os = "android", target_os = "ios")))] +pub mod input_source { + use crate::ui_interface::{get_local_option, set_local_option}; + use hbb_common::log; + + pub const CONFIG_OPTION_INPUT_SOURCE: &str = "input-source"; + // rdev grab mode + pub const CONFIG_INPUT_SOURCE_1: &str = "Input source 1"; + pub const CONFIG_INPUT_SOURCE_1_TIP: &str = "input_source_1_tip"; + // flutter grab mode + pub const CONFIG_INPUT_SOURCE_2: &str = "Input source 2"; + pub const CONFIG_INPUT_SOURCE_2_TIP: &str = "input_source_2_tip"; + + #[cfg(not(target_os = "macos"))] + pub const CONFIG_INPUT_SOURCE_DEFAULT: &str = CONFIG_INPUT_SOURCE_1; + #[cfg(target_os = "macos")] + pub const CONFIG_INPUT_SOURCE_DEFAULT: &str = CONFIG_INPUT_SOURCE_2; + + pub fn init_input_source() { + let cur_input_source = get_cur_session_input_source(); + if cur_input_source == CONFIG_INPUT_SOURCE_1 { + #[cfg(target_os = "macos")] + if !crate::platform::macos::is_can_input_monitoring(false) { + log::error!("init_input_source, is_can_input_monitoring() false"); + set_local_option( + CONFIG_OPTION_INPUT_SOURCE.to_string(), + CONFIG_INPUT_SOURCE_2.to_string(), + ); + return; + } + #[cfg(target_os = "linux")] + if !crate::platform::linux::is_x11() { + // If switching from X11 to Wayland, the grab loop will not be started. + // Do not change the config here. + return; + } + super::start_grab_loop(); + } + } + + pub fn change_input_source(input_source: &str) { + let cur_input_source = get_cur_session_input_source(); + if cur_input_source == input_source { + return; + } + if input_source == CONFIG_INPUT_SOURCE_1 { + #[cfg(target_os = "macos")] + if !crate::platform::macos::is_can_input_monitoring(false) { + log::error!("change_input_source, is_can_input_monitoring() false"); + return; + } + super::start_grab_loop(); + } else if input_source == CONFIG_INPUT_SOURCE_2 { + if let Err(e) = super::stop_grab_loop() { + log::error!("change_input_source, stop_grab_loop error: {:?}", e); + return; + } + } + set_local_option( + CONFIG_OPTION_INPUT_SOURCE.to_string(), + input_source.to_string(), + ); + } + + #[inline] + pub fn get_cur_session_input_source() -> String { + #[cfg(target_os = "linux")] + if !crate::platform::linux::is_x11() { + return CONFIG_INPUT_SOURCE_2.to_string(); + } + let input_source = get_local_option(CONFIG_OPTION_INPUT_SOURCE.to_string()); + if input_source.is_empty() { + CONFIG_INPUT_SOURCE_DEFAULT.to_string() + } else { + input_source + } + } + + #[inline] + pub fn is_cur_input_source_rdev() -> bool { + get_cur_session_input_source() == CONFIG_INPUT_SOURCE_1 + } + + #[inline] + pub fn get_supported_input_source() -> Vec<(String, String)> { + #[cfg(target_os = "linux")] + if !crate::platform::linux::is_x11() { + return vec![( + CONFIG_INPUT_SOURCE_2.to_string(), + CONFIG_INPUT_SOURCE_2_TIP.to_string(), + )]; + } + vec![ + ( + CONFIG_INPUT_SOURCE_1.to_string(), + CONFIG_INPUT_SOURCE_1_TIP.to_string(), + ), + ( + CONFIG_INPUT_SOURCE_2.to_string(), + CONFIG_INPUT_SOURCE_2_TIP.to_string(), + ), + ] + } +} diff --git a/src/lang/ar.rs b/src/lang/ar.rs index bdab9e466..d281facee 100644 --- a/src/lang/ar.rs +++ b/src/lang/ar.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 36aba208c..eafc06864 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 86a01bd6b..66e65db72 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "进入隐私模式"), ("Exit privacy mode", "退出隐私模式"), ("idd_not_support_under_win10_2004_tip", "不支持 Indirect display driver 。需要 windows 10, version 2004 及更高的版本。"), + ("input_source_1_tip", "输入源 1"), + ("input_source_2_tip", "输入源 2"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 616071e88..6e185ce83 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Vstup do režimu soukromí"), ("Exit privacy mode", "Ukončit režim soukromí"), ("idd_not_support_under_win10_2004_tip", "Ovladač nepřímého zobrazení není podporován. Je vyžadován systém Windows 10, verze 2004 nebo novější."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index ed926f0df..739e12690 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 1473119c4..4af92444d 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Datenschutzmodus aktivieren"), ("Exit privacy mode", "Datenschutzmodus beenden"), ("idd_not_support_under_win10_2004_tip", "Indirekter Grafiktreiber wird nicht unterstützt. Windows 10, Version 2004 oder neuer ist erforderlich."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index 8bb3a3d79..a18812b98 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index 101bc63a3..365076018 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -206,5 +206,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("privacy_mode_impl_mag_tip", "Mode 1"), ("privacy_mode_impl_virtual_display_tip", "Mode 2"), ("idd_not_support_under_win10_2004_tip", "Indirect display driver is not supported. Windows 10, version 2004 or newer is required."), + ("input_source_1_tip", "Input source 1"), + ("input_source_2_tip", "Input source 2"), ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 73eb77aa5..5efda9cf7 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index 40a23f317..3b8b8ab46 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Entrar al modo privado"), ("Exit privacy mode", "Salir del modo privado"), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index af0b8e944..4d1ad99d5 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index ea90ff654..b0d4782e5 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index f179da1df..79f0505bf 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 780b24bbd..e3bc5d4ba 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Masuk mode privasi"), ("Exit privacy mode", "Keluar mode privasi"), ("idd_not_support_under_win10_2004_tip", "Driver grafis yang Anda gunakan tidak kompatibel dengan versi Windows Anda dan memerlukan Windows 10 versi 2004 atau yang lebih baru"), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index e148ece66..d049d79ef 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Entra in modalità privacy"), ("Exit privacy mode", "Esci dalla modalità privacy"), ("idd_not_support_under_win10_2004_tip", "Il driver video indiretto non è supportato. È richiesto Windows 10, versione 2004 o successiva."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 0ff52484c..2b646c8ac 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 36d8338b9..2455b4099 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "개인정보 보호 모드 사용"), ("Exit privacy mode", "개인정보 보호 모드 종료"), ("idd_not_support_under_win10_2004_tip", "간접 디스플레이 드라이버는 지원되지 않습니다. Windows 10 버전 2004 이상이 필요합니다."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index 7a552e96a..a485d78bb 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index b4990d9c6..78716e3a2 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/lv.rs b/src/lang/lv.rs index 53b714723..a13ad8520 100644 --- a/src/lang/lv.rs +++ b/src/lang/lv.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Ieiet privātuma režīmā"), ("Exit privacy mode", "Iziet no privātuma režīma"), ("idd_not_support_under_win10_2004_tip", "Netiešā displeja draiveris netiek atbalstīts. Nepieciešama operētājsistēma Windows 10, versija 2004 vai jaunāka."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nb.rs b/src/lang/nb.rs index 4f8945721..b3f1360cf 100644 --- a/src/lang/nb.rs +++ b/src/lang/nb.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 7b66fb3f3..9267d9be0 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 3aa80786e..763a7ed19 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Wejdź w tryb prywatności"), ("Exit privacy mode", "Wyjdź z trybu prywatności"), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 6b89eaa8c..79b3374b6 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index c5c4f2768..5f477f853 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 5e806e426..30434268b 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 98994795d..b4e12f93d 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Включить режим конфиденциальности"), ("Exit privacy mode", "Отключить режим конфиденциальности"), ("idd_not_support_under_win10_2004_tip", "Драйвер непрямого отображения не поддерживается. Требуется Windows 10 версии 2004 или новее."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 46848da73..9173f7467 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Vstup do režimu súkromia"), ("Exit privacy mode", "Ukončiť režim súkromia"), ("idd_not_support_under_win10_2004_tip", "Ovládač nepriameho zobrazenia nie je podporovaný. Vyžaduje sa systém Windows 10, verzia 2004 alebo novšia."), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index be9774be8..9a2b39366 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index ff8851b94..499c2fd09 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index ae4c4e364..8ded31ae3 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index cfefe48a1..56e64e8fb 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index e3f8f6f38..2431d0130 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index ea3a72af2..971745e56 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index e14be47db..c5b2f4816 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 57b7d7b9f..c1072f373 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 6fa172311..ffe887436 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", "Увійти в режим конфіденційності"), ("Exit privacy mode", "Вийти з режиму конфіденційності"), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 84b0bf752..4ef8825fa 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -573,5 +573,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Enter privacy mode", ""), ("Exit privacy mode", ""), ("idd_not_support_under_win10_2004_tip", ""), + ("input_source_1_tip", ""), + ("input_source_2_tip", ""), ].iter().cloned().collect(); }