diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 0c7586e7036c..577b1e8c5a68 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -1362,11 +1362,30 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { bool get wantKeepAlive => true; bool locked = !isWeb && bind.mainIsInstalled(); + final scrollController = ScrollController(); + late final TextEditingController idController; + late final TextEditingController relayController; + late final TextEditingController apiController; + late final TextEditingController keyController; + + @override + void initState() { + super.initState(); + Map oldOptions = jsonDecode(bind.mainGetOptionsSync()); + old(String key) { + return (oldOptions[key] ?? '').trim(); + } + + idController = TextEditingController(text: old('custom-rendezvous-server')); + relayController = TextEditingController(text: old('relay-server')); + apiController = TextEditingController(text: old('api-server')); + keyController = TextEditingController(text: old('key')); + } + @override Widget build(BuildContext context) { super.build(context); bool enabled = !locked; - final scrollController = ScrollController(); final hideServer = bind.mainGetBuildinOption(key: kOptionHideServerSetting) == 'Y'; // TODO: support web proxy @@ -1395,19 +1414,10 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin { // Simple temp wrapper for PR check tmpWrapper() { // Setting page is not modal, oldOptions should only be used when getting options, never when setting. - Map oldOptions = jsonDecode(bind.mainGetOptionsSync()); - old(String key) { - return (oldOptions[key] ?? '').trim(); - } RxString idErrMsg = ''.obs; RxString relayErrMsg = ''.obs; RxString apiErrMsg = ''.obs; - var idController = - TextEditingController(text: old('custom-rendezvous-server')); - var relayController = TextEditingController(text: old('relay-server')); - var apiController = TextEditingController(text: old('api-server')); - var keyController = TextEditingController(text: old('key')); final controllers = [ idController, relayController, @@ -2251,26 +2261,39 @@ _LabeledTextField( String errorText, bool enabled, bool secure) { - return Row( + return Table( + columnWidths: const { + 0: FixedColumnWidth(150), + 1: FlexColumnWidth(), + }, + defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ - ConstrainedBox( - constraints: const BoxConstraints(minWidth: 140), - child: Text( - '${translate(label)}:', - textAlign: TextAlign.right, - style: TextStyle( - fontSize: 16, color: disabledTextColor(context, enabled)), - ).marginOnly(right: 10)), - Expanded( - child: TextField( + TableRow( + children: [ + Padding( + padding: const EdgeInsets.only(right: 10), + child: Text( + '${translate(label)}:', + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 16, + color: disabledTextColor(context, enabled), + ), + ), + ), + TextField( controller: controller, enabled: enabled, obscureText: secure, + autocorrect: false, decoration: InputDecoration( - errorText: errorText.isNotEmpty ? errorText : null), + errorText: errorText.isNotEmpty ? errorText : null, + ), style: TextStyle( color: disabledTextColor(context, enabled), - )), + ), + ), + ], ), ], ).marginOnly(bottom: 8); diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock index dc5ed1413f4f..dbcb28b1c2d3 100644 --- a/flutter/pubspec.lock +++ b/flutter/pubspec.lock @@ -335,7 +335,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: "4f562ab49d289cfa36bfda7cff12746ec0200033" + resolved-ref: "925df98a740b168ae3dad42592db4af66401053c" url: "https://github.com/rustdesk-org/rustdesk_desktop_multi_window" source: git version: "0.1.0" diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 527813d09eba..93c174894119 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -653,7 +653,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Upload folder", "폴더 업로드"), ("Upload files", "파일 업로드"), ("Clipboard is synchronized", "클립보드가 동기화됨"), - ("Update client clipboard", ""), - ("Untagged", ""), + ("Update client clipboard", "클라이언트 클립보드 업데이트"), + ("Untagged", "태그 없음"), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 582fdf6dcc6a..5979961ddf91 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -654,6 +654,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Upload files", "Загрузить файлы"), ("Clipboard is synchronized", "Буфер обмена синхронизирован"), ("Update client clipboard", "Обновить буфер обмена клиента"), - ("Untagged", ""), + ("Untagged", "Без метки"), ].iter().cloned().collect(); } diff --git a/src/platform/windows.cc b/src/platform/windows.cc index 9ee3c1f5c9a6..04095a2d63f0 100644 --- a/src/platform/windows.cc +++ b/src/platform/windows.cc @@ -222,6 +222,11 @@ extern "C" return IsWindowsServer(); } + bool is_windows_10_or_greater() + { + return IsWindows10OrGreater(); + } + HANDLE LaunchProcessWin(LPCWSTR cmd, DWORD dwSessionId, BOOL as_user, DWORD *pDwTokenPid) { HANDLE hProcess = NULL; diff --git a/src/platform/windows.rs b/src/platform/windows.rs index 4495af538a7b..c0839dc55acd 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -479,6 +479,7 @@ extern "C" { fn selectInputDesktop() -> BOOL; fn inputDesktopSelected() -> BOOL; fn is_windows_server() -> BOOL; + fn is_windows_10_or_greater() -> BOOL; fn handleMask( out: *mut u8, mask: *const u8, @@ -1559,6 +1560,11 @@ pub fn is_win_server() -> bool { unsafe { is_windows_server() > 0 } } +#[inline] +pub fn is_win_10_or_greater() -> bool { + unsafe { is_windows_10_or_greater() > 0 } +} + pub fn bootstrap() { if let Ok(lic) = get_license_from_exe_name() { *config::EXE_RENDEZVOUS_SERVER.write().unwrap() = lic.host.clone(); diff --git a/src/ui_interface.rs b/src/ui_interface.rs index caff46b84f33..5d7f9ee039cd 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -173,21 +173,36 @@ pub fn get_option>(key: T) -> String { } #[inline] -#[cfg(target_os = "macos")] pub fn use_texture_render() -> bool { - cfg!(feature = "flutter") && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y" -} + #[cfg(target_os = "android")] + return false; + #[cfg(target_os = "ios")] + return false; -#[inline] -#[cfg(any(target_os = "windows", target_os = "linux"))] -pub fn use_texture_render() -> bool { - cfg!(feature = "flutter") && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N" -} + #[cfg(target_os = "macos")] + return cfg!(feature = "flutter") + && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y"; -#[inline] -#[cfg(any(target_os = "android", target_os = "ios"))] -pub fn use_texture_render() -> bool { - false + #[cfg(target_os = "linux")] + return cfg!(feature = "flutter") + && LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N"; + + #[cfg(target_os = "windows")] + { + if !cfg!(feature = "flutter") { + return false; + } + // https://learn.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1 + #[cfg(debug_assertions)] + let default_texture = true; + #[cfg(not(debug_assertions))] + let default_texture = crate::platform::is_win_10_or_greater(); + if default_texture { + LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) != "N" + } else { + return LocalConfig::get_option(config::keys::OPTION_TEXTURE_RENDER) == "Y"; + } + } } #[inline]