From 00dc473703b38b70d2ecc3dbc0a47fab9519a6d8 Mon Sep 17 00:00:00 2001 From: fufesou Date: Wed, 20 Jul 2022 10:44:27 -0700 Subject: [PATCH] linux_wayland_support: dup detecting function of x11 or wayland Signed-off-by: fufesou --- Cargo.lock | 1 + libs/enigo/Cargo.toml | 1 + libs/enigo/src/lib.rs | 2 +- libs/enigo/src/linux/mod.rs | 32 -------- libs/enigo/src/linux/nix_impl.rs | 2 +- libs/hbb_common/src/lib.rs | 1 + libs/hbb_common/src/platform/linux.rs | 102 +++++++++++++++++++++++++ libs/hbb_common/src/platform/mod.rs | 2 + libs/scrap/src/common/linux.rs | 23 +++--- src/platform/linux.rs | 103 +------------------------- src/server/video_service.rs | 10 +-- src/server/wayland.rs | 6 +- 12 files changed, 130 insertions(+), 155 deletions(-) create mode 100644 libs/hbb_common/src/platform/linux.rs create mode 100644 libs/hbb_common/src/platform/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 70c76a9cc..c91272112 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1266,6 +1266,7 @@ name = "enigo" version = "0.0.14" dependencies = [ "core-graphics 0.22.3", + "hbb_common", "libc", "log", "objc", diff --git a/libs/enigo/Cargo.toml b/libs/enigo/Cargo.toml index 6842dab56..b0028b564 100644 --- a/libs/enigo/Cargo.toml +++ b/libs/enigo/Cargo.toml @@ -22,6 +22,7 @@ appveyor = { repository = "pythoneer/enigo-85xiy" } serde = { version = "1.0", optional = true } serde_derive = { version = "1.0", optional = true } log = "0.4" +hbb_common = { path = "../hbb_common" } [features] with_serde = ["serde", "serde_derive"] diff --git a/libs/enigo/src/lib.rs b/libs/enigo/src/lib.rs index 40ba1c1db..164fb1c17 100644 --- a/libs/enigo/src/lib.rs +++ b/libs/enigo/src/lib.rs @@ -74,7 +74,7 @@ pub use macos::Enigo; #[cfg(target_os = "linux")] mod linux; #[cfg(target_os = "linux")] -pub use crate::linux::{is_x11, Enigo}; +pub use crate::linux::Enigo; /// DSL parser module pub mod dsl; diff --git a/libs/enigo/src/linux/mod.rs b/libs/enigo/src/linux/mod.rs index 3c0784660..42e1dfebf 100644 --- a/libs/enigo/src/linux/mod.rs +++ b/libs/enigo/src/linux/mod.rs @@ -3,35 +3,3 @@ mod pynput; mod xdo; pub use self::nix_impl::Enigo; - -/// Check if display manager is x11. -pub fn is_x11() -> bool { - let stdout = - match std::process::Command::new("sh") - .arg("-c") - .arg("loginctl show-session $(loginctl | awk '/tty/ {print $1}') -p Type | awk -F= '{print $2}'") - .output() { - Ok(output) => { - output.stdout - }, - Err(_) => { - match std::process::Command::new("sh") - .arg("-c") - .arg("echo $XDG_SESSION_TYPE") - .output() { - Ok(output) => { - output.stdout - }, - Err(_) => { - return false; - } - } - } - }; - - if let Ok(display_manager) = std::str::from_utf8(&stdout) { - display_manager.trim() == "x11" - } else { - false - } -} diff --git a/libs/enigo/src/linux/nix_impl.rs b/libs/enigo/src/linux/nix_impl.rs index 332b6d16e..840290b2b 100644 --- a/libs/enigo/src/linux/nix_impl.rs +++ b/libs/enigo/src/linux/nix_impl.rs @@ -40,7 +40,7 @@ impl Enigo { impl Default for Enigo { fn default() -> Self { Self { - is_x11: crate::linux::is_x11(), + is_x11: "x11" == hbb_common::platform::linux::get_display_server(), uinput_keyboard: None, uinput_mouse: None, xdo: EnigoXdo::default(), diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index fdd32c4c7..a5443db0f 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -1,5 +1,6 @@ pub mod compress; pub mod protos; +pub mod platform; pub use protos::message as message_proto; pub use protos::rendezvous as rendezvous_proto; pub use bytes; diff --git a/libs/hbb_common/src/platform/linux.rs b/libs/hbb_common/src/platform/linux.rs new file mode 100644 index 000000000..da79e9e39 --- /dev/null +++ b/libs/hbb_common/src/platform/linux.rs @@ -0,0 +1,102 @@ +use crate::ResultType; + +pub fn get_display_server() -> String { + let session = get_value_of_seat0(0); + get_display_server_of_session(&session) +} + +fn get_display_server_of_session(session: &str) -> String { + if let Ok(output) = std::process::Command::new("loginctl") + .args(vec!["show-session", "-p", "Type", session]) + .output() + // Check session type of the session + { + let display_server = String::from_utf8_lossy(&output.stdout) + .replace("Type=", "") + .trim_end() + .into(); + if display_server == "tty" { + // If the type is tty... + if let Ok(output) = std::process::Command::new("loginctl") + .args(vec!["show-session", "-p", "TTY", session]) + .output() + // Get the tty number + { + let tty: String = String::from_utf8_lossy(&output.stdout) + .replace("TTY=", "") + .trim_end() + .into(); + if let Ok(xorg_results) = run_cmds(format!("ps -e | grep \"{}.\\\\+Xorg\"", tty)) + // And check if Xorg is running on that tty + { + if xorg_results.trim_end().to_string() != "" { + // If it is, manually return "x11", otherwise return tty + "x11".to_owned() + } else { + display_server + } + } else { + // If any of these commands fail just fall back to the display server + display_server + } + } else { + display_server + } + } else { + // If the session is not a tty, then just return the type as usual + display_server + } + } else { + "".to_owned() + } +} + +pub fn get_value_of_seat0(i: usize) -> String { + if let Ok(output) = std::process::Command::new("loginctl").output() { + for line in String::from_utf8_lossy(&output.stdout).lines() { + if line.contains("seat0") { + if let Some(sid) = line.split_whitespace().nth(0) { + if is_active(sid) { + if let Some(uid) = line.split_whitespace().nth(i) { + return uid.to_owned(); + } + } + } + } + } + } + + // some case, there is no seat0 https://github.com/rustdesk/rustdesk/issues/73 + if let Ok(output) = std::process::Command::new("loginctl").output() { + for line in String::from_utf8_lossy(&output.stdout).lines() { + if let Some(sid) = line.split_whitespace().nth(0) { + let d = get_display_server_of_session(sid); + if is_active(sid) && d != "tty" { + if let Some(uid) = line.split_whitespace().nth(i) { + return uid.to_owned(); + } + } + } + } + } + + return "".to_owned(); +} + +fn is_active(sid: &str) -> bool { + if let Ok(output) = std::process::Command::new("loginctl") + .args(vec!["show-session", "-p", "State", sid]) + .output() + { + String::from_utf8_lossy(&output.stdout).contains("active") + } else { + false + } +} + +pub fn run_cmds(cmds: String) -> ResultType { + let output = std::process::Command::new("sh") + .args(vec!["-c", &cmds]) + .output()?; + Ok(String::from_utf8_lossy(&output.stdout).to_string()) +} diff --git a/libs/hbb_common/src/platform/mod.rs b/libs/hbb_common/src/platform/mod.rs new file mode 100644 index 000000000..8daba257f --- /dev/null +++ b/libs/hbb_common/src/platform/mod.rs @@ -0,0 +1,2 @@ +#[cfg(target_os = "linux")] +pub mod linux; diff --git a/libs/scrap/src/common/linux.rs b/libs/scrap/src/common/linux.rs index 2a921477e..8498ab7ff 100644 --- a/libs/scrap/src/common/linux.rs +++ b/libs/scrap/src/common/linux.rs @@ -52,31 +52,30 @@ pub enum Display { } #[inline] -pub fn is_wayland() -> bool { - std::env::var("IS_WAYLAND").is_ok() - || std::env::var("XDG_SESSION_TYPE") == Ok("wayland".to_owned()) +pub fn is_x11() -> bool { + "x11" == hbb_common::platform::linux::get_display_server() } impl Display { pub fn primary() -> io::Result { - Ok(if is_wayland() { - Display::WAYLAND(wayland::Display::primary()?) - } else { + Ok(if is_x11() { Display::X11(x11::Display::primary()?) + } else { + Display::WAYLAND(wayland::Display::primary()?) }) } pub fn all() -> io::Result> { - Ok(if is_wayland() { - wayland::Display::all()? - .drain(..) - .map(|x| Display::WAYLAND(x)) - .collect() - } else { + Ok(if is_x11() { x11::Display::all()? .drain(..) .map(|x| Display::X11(x)) .collect() + } else { + wayland::Display::all()? + .drain(..) + .map(|x| Display::WAYLAND(x)) + .collect() }) } diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 14d43e0e1..5a12f5ac0 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,4 +1,5 @@ use super::{CursorData, ResultType}; +pub use hbb_common::platform::linux::*; use hbb_common::{allow_err, bail, log}; use libc::{c_char, c_int, c_void}; use std::{ @@ -8,6 +9,7 @@ use std::{ Arc, }, }; + type Xdo = *const c_void; pub const PA_SAMPLE_RATE: u32 = 48000; @@ -335,17 +337,6 @@ pub fn get_active_userid() -> String { get_value_of_seat0(1) } -fn is_active(sid: &str) -> bool { - if let Ok(output) = std::process::Command::new("loginctl") - .args(vec!["show-session", "-p", "State", sid]) - .output() - { - String::from_utf8_lossy(&output.stdout).contains("active") - } else { - false - } -} - fn get_cm() -> bool { if let Ok(output) = std::process::Command::new("ps").args(vec!["aux"]).output() { for line in String::from_utf8_lossy(&output.stdout).lines() { @@ -401,89 +392,6 @@ fn get_display() -> String { last } -fn get_value_of_seat0(i: usize) -> String { - if let Ok(output) = std::process::Command::new("loginctl").output() { - for line in String::from_utf8_lossy(&output.stdout).lines() { - if line.contains("seat0") { - if let Some(sid) = line.split_whitespace().nth(0) { - if is_active(sid) { - if let Some(uid) = line.split_whitespace().nth(i) { - return uid.to_owned(); - } - } - } - } - } - } - - // some case, there is no seat0 https://github.com/rustdesk/rustdesk/issues/73 - if let Ok(output) = std::process::Command::new("loginctl").output() { - for line in String::from_utf8_lossy(&output.stdout).lines() { - if let Some(sid) = line.split_whitespace().nth(0) { - let d = get_display_server_of_session(sid); - if is_active(sid) && d != "tty" { - if let Some(uid) = line.split_whitespace().nth(i) { - return uid.to_owned(); - } - } - } - } - } - - return "".to_owned(); -} - -pub fn get_display_server() -> String { - let session = get_value_of_seat0(0); - get_display_server_of_session(&session) -} - -fn get_display_server_of_session(session: &str) -> String { - if let Ok(output) = std::process::Command::new("loginctl") - .args(vec!["show-session", "-p", "Type", session]) - .output() - // Check session type of the session - { - let display_server = String::from_utf8_lossy(&output.stdout) - .replace("Type=", "") - .trim_end() - .into(); - if display_server == "tty" { - // If the type is tty... - if let Ok(output) = std::process::Command::new("loginctl") - .args(vec!["show-session", "-p", "TTY", session]) - .output() - // Get the tty number - { - let tty: String = String::from_utf8_lossy(&output.stdout) - .replace("TTY=", "") - .trim_end() - .into(); - if let Ok(xorg_results) = run_cmds(format!("ps -e | grep \"{}.\\\\+Xorg\"", tty)) - // And check if Xorg is running on that tty - { - if xorg_results.trim_end().to_string() != "" { - // If it is, manually return "x11", otherwise return tty - "x11".to_owned() - } else { - display_server - } - } else { - // If any of these commands fail just fall back to the display server - display_server - } - } else { - display_server - } - } else { - // If the session is not a tty, then just return the type as usual - display_server - } - } else { - "".to_owned() - } -} - pub fn is_login_wayland() -> bool { if let Ok(contents) = std::fs::read_to_string("/etc/gdm3/custom.conf") { contents.contains("#WaylandEnable=false") @@ -690,13 +598,6 @@ pub fn is_installed() -> bool { true } -pub fn run_cmds(cmds: String) -> ResultType { - let output = std::process::Command::new("sh") - .args(vec!["-c", &cmds]) - .output()?; - Ok(String::from_utf8_lossy(&output.stdout).to_string()) -} - fn get_env_tries(name: &str, uid: &str, n: usize) -> String { for _ in 0..n { let x = get_env(name, uid); diff --git a/src/server/video_service.rs b/src/server/video_service.rs index ede62efee..e6ea713a1 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -193,7 +193,7 @@ fn check_display_changed( #[cfg(target_os = "linux")] { // wayland do not support changing display for now - if scrap::is_wayland() { + if !scrap::is_x11() { return false; } } @@ -369,7 +369,7 @@ impl DerefMut for CapturerInfo { fn get_capturer(use_yuv: bool) -> ResultType { #[cfg(target_os = "linux")] { - if scrap::is_wayland() { + if !scrap::is_x11() { return super::wayland::get_capturer(); } } @@ -702,7 +702,7 @@ pub fn handle_one_frame_encoded( fn get_display_num() -> usize { #[cfg(target_os = "linux")] { - if scrap::is_wayland() { + if !scrap::is_x11() { return if let Ok(n) = super::wayland::get_display_num() { n } else { @@ -745,7 +745,7 @@ pub(super) fn get_displays_2(all: &Vec) -> (usize, Vec) { pub async fn get_displays() -> ResultType<(usize, Vec)> { #[cfg(target_os = "linux")] { - if scrap::is_wayland() { + if !scrap::is_x11() { return super::wayland::get_displays().await; } } @@ -774,7 +774,7 @@ pub fn refresh() { fn get_primary() -> usize { #[cfg(target_os = "linux")] { - if scrap::is_wayland() { + if !scrap::is_x11() { return match super::wayland::get_primary() { Ok(n) => n, Err(_) => 0, diff --git a/src/server/wayland.rs b/src/server/wayland.rs index b81d378a6..e84be3f7c 100644 --- a/src/server/wayland.rs +++ b/src/server/wayland.rs @@ -28,7 +28,7 @@ impl super::video_service::TraitCapturer for *mut Capturer { } async fn check_init() -> ResultType<()> { - if scrap::is_wayland() { + if !scrap::is_x11() { let mut minx = 0; let mut maxx = 0; let mut miny = 0; @@ -96,7 +96,7 @@ async fn check_init() -> ResultType<()> { } pub fn clear() { - if !scrap::is_wayland() { + if scrap::is_x11() { return; } @@ -153,7 +153,7 @@ pub(super) fn get_display_num() -> ResultType { } pub(super) fn get_capturer() -> ResultType { - if !scrap::is_wayland() { + if scrap::is_x11() { bail!("Do not call this function if not wayland"); } let addr = *CAP_DISPLAY_INFO.read().unwrap();