diff --git a/Cargo.lock b/Cargo.lock index e734249de..1ec3929b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4562,6 +4562,7 @@ dependencies = [ "arboard", "async-process", "async-trait", + "backtrace", "base64", "bytes", "cc", diff --git a/Cargo.toml b/Cargo.toml index 82c35de79..2713df11d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,6 +119,7 @@ dbus-crossroads = "0.5" gtk = "0.15" libappindicator = "0.7" glib = "0.16.5" +backtrace = "0.3" [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.11" diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index 15f78daeb..45588171b 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -274,6 +274,15 @@ class _GeneralState extends State<_General> { _OptionCheckBox(context, 'Confirm before closing multiple tabs', 'enable-confirm-closing-tabs'), _OptionCheckBox(context, 'Adaptive Bitrate', 'enable-abr'), + if (Platform.isLinux) + Tooltip( + message: translate('software_render_tip'), + child: _OptionCheckBox( + context, + "Always use software rendering", + 'allow-always-software-render', + ), + ) ]); } @@ -1223,7 +1232,7 @@ Widget _OptionCheckBox(BuildContext context, String label, String key, ref.value = option; if (reverse) option = !option; String value = bool2option(key, option); - bind.mainSetOption(key: key, value: value); + await bind.mainSetOption(key: key, value: value); update?.call(); } } diff --git a/src/core_main.rs b/src/core_main.rs index 1f42f8aad..bf6866df5 100644 --- a/src/core_main.rs +++ b/src/core_main.rs @@ -38,6 +38,17 @@ pub fn core_main() -> Option> { } i += 1; } + #[cfg(target_os = "linux")] + #[cfg(feature = "flutter")] + { + crate::platform::linux::register_breakdown_handler(); + let (k, v) = ("LIBGL_ALWAYS_SOFTWARE", "true"); + if !hbb_common::config::Config::get_option("allow-always-software-render").is_empty() { + std::env::set_var(k, v); + } else { + std::env::remove_var(k); + } + } #[cfg(feature = "flutter")] if _is_flutter_connect { return core_main_invoke_new_connection(std::env::args()); diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 093f2572c..eb38cd436 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index 307cbfd9b..c5e4407a6 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "被web控制台手动关闭"), ("Local keyboard type", "本地键盘类型"), ("Select local keyboard type", "请选择本地键盘类型"), + ("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装nouveau驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"), + ("Always use software rendering", "使用软件渲染"), ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index 027de13ba..18b2673c9 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 3361804e8..a1e74259c 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index 7226550f5..44404d52f 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "Manuell über die Webkonsole beendet"), ("Local keyboard type", "Lokaler Tastaturtyp"), ("Select local keyboard type", "Lokalen Tastaturtyp auswählen"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/en.rs b/src/lang/en.rs index f351b575d..b8c8f074d 100644 --- a/src/lang/en.rs +++ b/src/lang/en.rs @@ -36,5 +36,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("hide_cm_tip", "Allow hiding only if accepting sessions via password and using permanent password"), ("wayland_experiment_tip", "Wayland support is in experimental stage, please use X11 if you require unattended access."), ("Slogan_tip", "Made with heart in this chaotic world!"), + ("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required.") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index a21a2e91e..7b32c1708 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index b3276949a..4a9f9251c 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "Cerrado manualmente por la consola web"), ("Local keyboard type", "Tipo de teclado local"), ("Select local keyboard type", "Seleccionar tipo de teclado local"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 3d4579b27..8c0c426ed 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 1e3beb2e4..22b522a9d 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "Fermé manuellement par la console Web"), ("Local keyboard type", "Disposition du clavier local"), ("Select local keyboard type", "Selectionner la disposition du clavier local"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/gr.rs b/src/lang/gr.rs index 4b2777729..9ca035e65 100644 --- a/src/lang/gr.rs +++ b/src/lang/gr.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 2f22ab511..2b81b90eb 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index 362a7fb85..ecc21b3f0 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 390670df4..31cfd345e 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "Chiudi manualmente dalla console Web"), ("Local keyboard type", "Tipo di tastiera locale"), ("Select local keyboard type", "Seleziona il tipo di tastiera locale"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index c247a7582..4673d2e41 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index a4f2fde77..5d0b8c8a7 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index d8037ff62..0b55a79ff 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 2cf91af4a..5ca41e3ac 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index fc95cb548..3e203a250 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 5a89efd4b..c17620bc1 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 82d8d357e..1fa6d7528 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "Закрыто вручную через веб-консоль"), ("Local keyboard type", "Тип локальной клавиатуры"), ("Select local keyboard type", "Выберите тип локальной клавиатуры"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index e61ac9c58..13bbcf4f7 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index c55562942..d08036bf3 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index d74baf8b2..f9386004d 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index 6a770c24a..9f2d1c9f4 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index b4113b91a..145cf45bb 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index 792f4f97a..d6bbe806d 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -280,7 +280,6 @@ lazy_static::lazy_static! { ("android_stop_service_tip", "การปิดการใช้งานเซอร์วิสจะปิดการเชื่อมต่อทั้งหมดโดยอัตโนมัติ"), ("android_version_audio_tip", "เวอร์ชั่นแอนดรอยด์ปัจจุบันของคุณไม่รองรับการบันทึกข้อมูลเสียง กรุณาอัปเกรดเป็นแอนดรอยด์เวอร์ชั่น 10 หรือสูงกว่า"), ("android_start_service_tip", "แตะ [เริ่มต้นใช้งานเซอร์วิส] หรือเปิดสิทธิ์ [การบันทึกหน้าจอ] เพื่อเริ่มเซอร์วิสการแชร์หน้าจอ"), - ("Account", "บัญชี"), ("Overwrite", "เขียนทับ"), ("This file exists, skip or overwrite this file?", "พบไฟล์ที่มีอยู่แล้ว ต้องการเขียนทับหรือไม่?"), ("Quit", "ออก"), @@ -334,6 +333,7 @@ lazy_static::lazy_static! { ("Scale adaptive", "ขนาดยืดหยุ่น"), ("General", "ทั่วไป"), ("Security", "ความปลอดภัย"), + ("Account", "บัญชี"), ("Theme", "ธีม"), ("Dark Theme", "ธีมมืด"), ("Dark", "มืด"), @@ -405,5 +405,8 @@ lazy_static::lazy_static! { ("Closed manually by the web console", "ถูกปิดโดยเว็บคอนโซล"), ("Local keyboard type", "ประเภทคีย์บอร์ด"), ("Select local keyboard type", "เลือกประเภทคีย์บอร์ด"), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } + \ No newline at end of file diff --git a/src/lang/tr.rs b/src/lang/tr.rs index 60bc9dda1..00c620c34 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index 0e08fa508..cb83d28ea 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", "被web控制台手動關閉"), ("Local keyboard type", "本地鍵盤類型"), ("Select local keyboard type", "請選擇本地鍵盤類型"), + ("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"), + ("Always use software rendering", "使用軟件渲染"), ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 343b62b4f..1c6ac5828 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index a2fc416f2..d2e067b3b 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -405,5 +405,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Closed manually by the web console", ""), ("Local keyboard type", ""), ("Select local keyboard type", ""), + ("software_render_tip", ""), + ("Always use software rendering", ""), ].iter().cloned().collect(); } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index ab436ed30..b2c2e81cb 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -717,3 +717,92 @@ pub fn get_double_click_time() -> u32 { } } +/// forever: may not work +pub fn system_message(title: &str, msg: &str, forever: bool) -> ResultType<()> { + if std::process::Command::new("notify-send") + .arg(title) + .arg(msg) + .spawn() + .is_ok() + { + return Ok(()); + } + if std::process::Command::new("zenity") + .arg("--info") + .arg("--timeout") + .arg(if forever { "0" } else { "3" }) + .arg("--title") + .arg(title) + .arg("--text") + .arg(msg) + .spawn() + .is_ok() + { + return Ok(()); + } + if std::process::Command::new("kdialog") + .arg("--title") + .arg(title) + .arg("--msgbox") + .arg(msg) + .spawn() + .is_ok() + { + return Ok(()); + } + if std::process::Command::new("xmessage") + .arg("-center") + .arg("-timeout") + .arg(if forever { "0" } else { "3" }) + .arg(title) + .arg(msg) + .spawn() + .is_ok() + { + return Ok(()); + } + bail!("failed to post system message"); +} + +extern "C" fn breakdown_signal_handler(sig: i32) { + let mut stack = vec![]; + backtrace::trace(|frame| { + backtrace::resolve_frame(frame, |symbol| { + if let Some(name) = symbol.name() { + stack.push(name.to_string()); + } + }); + true // keep going to the next frame + }); + let mut info = String::default(); + if stack.iter().any(|s| { + s.contains(&"nouveau_pushbuf_kick") + || s.to_lowercase().contains("nvidia") + || s.contains("gdk_window_end_draw_frame") + }) { + hbb_common::config::Config::set_option( + "allow-always-software-render".to_string(), + "Y".to_string(), + ); + info = "Always use software rendering will be set.".to_string(); + log::info!("{}", info); + } + log::error!( + "Got signal {} and exit. stack:\n{}", + sig, + stack.join("\n").to_string() + ); + system_message( + "RustDesk", + &format!("Got signal {} and exit.{}", sig, info), + true, + ) + .ok(); + std::process::exit(0); +} + +pub fn register_breakdown_handler() { + unsafe { + libc::signal(libc::SIGSEGV, breakdown_signal_handler as _); + } +}