diff --git a/src/server/connection.rs b/src/server/connection.rs index 2dfa52df3..69dfbba65 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -3709,13 +3709,13 @@ impl Connection { #[cfg(not(target_os = "windows"))] let is_lower_win10 = false; #[cfg(target_os = "linux")] - let is_wayland = !crate::platform::linux::is_x11(); + let is_linux_supported = crate::whiteboard::is_supported(); #[cfg(not(target_os = "linux"))] - let is_wayland = false; + let is_linux_supported = false; let not_support_msg = if is_lower_win10 { "Windows 10 or greater is required." - } else if is_wayland { - "This feature is not supported on Wayland, please switch to X11." + } else if cfg!(target_os = "linux") && !is_linux_supported { + "This feature is not supported on native Wayland, please install XWayland or switch to X11." } else { "" }; diff --git a/src/whiteboard/linux.rs b/src/whiteboard/linux.rs index 806bf7848..686a0d0b1 100644 --- a/src/whiteboard/linux.rs +++ b/src/whiteboard/linux.rs @@ -61,7 +61,44 @@ extern "C" { const SHAPE_INPUT: std::ffi::c_int = 2; +fn get_display_from_xwayland() -> Option { + if let Ok(output) = crate::platform::run_cmds("pgrep -a Xwayland") { + // 1410 /usr/bin/Xwayland :1 -auth /run/user/1000/xauth_RoDZey -listenfd 8 -listenfd 9 -displayfd 76 -wm 78 -rootless -enable-ei-portal + if output.contains("Xwayland") { + if let Some(display) = output.split_whitespace().nth(2) { + if display.starts_with(':') { + return Some(display.to_string()); + } + } + } + } + None +} + +fn preset_env() -> bool { + if crate::platform::is_x11() { + return true; + } + if let Some(display) = get_display_from_xwayland() { + // https://github.com/rust-windowing/winit/blob/f6893a4390dfe6118ce4b33458d458fd3efd3025/src/event_loop.rs#L99 + // It is acceptable to modify global environment variables here because this process is an isolated, + // dedicated "whiteboard" process. + std::env::set_var("DISPLAY", display); + std::env::remove_var("WAYLAND_DISPLAY"); + return true; + } + false +} + +pub fn is_supported() -> bool { + crate::platform::is_x11() || get_display_from_xwayland().is_some() +} + pub fn run() { + if !preset_env() { + return; + } + let event_loop = match EventLoop::<(String, CustomEvent)>::with_user_event().build() { Ok(el) => el, Err(e) => { diff --git a/src/whiteboard/mod.rs b/src/whiteboard/mod.rs index 00d2d7791..42befe84f 100644 --- a/src/whiteboard/mod.rs +++ b/src/whiteboard/mod.rs @@ -16,6 +16,8 @@ mod win_linux; use windows::create_event_loop; #[cfg(target_os = "macos")] use macos::create_event_loop; +#[cfg(target_os = "linux")] +pub use linux::is_supported; pub use client::*; pub use server::*; diff --git a/src/whiteboard/win_linux.rs b/src/whiteboard/win_linux.rs index f279bebb7..9e4722fff 100644 --- a/src/whiteboard/win_linux.rs +++ b/src/whiteboard/win_linux.rs @@ -158,11 +158,11 @@ pub(super) fn create_font_face() -> ResultType> { let mut font_db = fontdb::Database::new(); font_db.load_system_fonts(); let query = fontdb::Query { - families: &[fontdb::Family::Monospace], + families: &[fontdb::Family::Monospace, fontdb::Family::SansSerif], ..fontdb::Query::default() }; let Some(font_id) = font_db.query(&query) else { - bail!("No monospace font found!"); + bail!("No monospace or sans-serif font found!"); }; let Some((font_source, face_index)) = font_db.face_source(font_id) else { bail!("No face found for font!");