diff --git a/Cargo.lock b/Cargo.lock index b62f82745..e632114af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1224,38 +1224,14 @@ dependencies = [ "zvariant", ] -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core 0.10.2", - "darling_macro 0.10.2", -] - [[package]] name = "darling" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2 1.0.51", - "quote 1.0.23", - "strsim 0.9.3", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -1272,24 +1248,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core 0.10.2", - "quote 1.0.23", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ - "darling_core 0.13.4", + "darling_core", "quote 1.0.23", "syn 1.0.109", ] @@ -1488,18 +1453,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_setters" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1cf41b4580a37cca5ef2ada2cc43cf5d6be3983f4522e83010d67ab6925e84b" -dependencies = [ - "darling 0.10.2", - "proc-macro2 1.0.51", - "quote 1.0.23", - "syn 1.0.109", -] - [[package]] name = "detect-desktop-environment" version = "0.2.0" @@ -3705,7 +3658,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" dependencies = [ - "darling 0.13.4", + "darling", "proc-macro-crate 1.3.1", "proc-macro2 1.0.51", "quote 1.0.23", @@ -5048,7 +5001,6 @@ dependencies = [ "winreg 0.10.1", "winres", "wol-rs", - "xrandr-parser", ] [[package]] @@ -5648,12 +5600,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - [[package]] name = "strsim" version = "0.10.0" @@ -7182,16 +7128,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" -[[package]] -name = "xrandr-parser" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5af43ba661cee58bd86b9f81a899e45a15ac7f42fa4401340f73c0c2950030c1" -dependencies = [ - "derive_setters", - "serde 1.0.154", -] - [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index 7ad979f8c..bf81664e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,7 +121,6 @@ mouce = { git="https://github.com/fufesou/mouce.git" } evdev = { git="https://github.com/fufesou/evdev" } dbus = "0.9" dbus-crossroads = "0.5" -xrandr-parser = "0.3.0" [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.11" diff --git a/src/platform/linux.rs b/src/platform/linux.rs index bde2a5c58..6980385c8 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -1,12 +1,11 @@ use super::{CursorData, ResultType}; pub use hbb_common::platform::linux::*; use hbb_common::{ - allow_err, - anyhow::anyhow, - bail, + allow_err, bail, libc::{c_char, c_int, c_long, c_void}, log, message_proto::Resolution, + regex::{Captures, Regex}, }; use std::{ cell::RefCell, @@ -18,7 +17,6 @@ use std::{ }, time::{Duration, Instant}, }; -use xrandr_parser::Parser; type Xdo = *const c_void; @@ -671,44 +669,99 @@ pub fn get_double_click_time() -> u32 { } } +#[inline] +fn get_width_height_from_captures<'t>(caps: &Captures<'t>) -> Option<(i32, i32)> { + match (caps.name("width"), caps.name("height")) { + (Some(width), Some(height)) => { + match ( + width.as_str().parse::(), + height.as_str().parse::(), + ) { + (Ok(width), Ok(height)) => { + return Some((width, height)); + } + _ => {} + } + } + _ => {} + } + None +} + +#[inline] +fn get_xrandr_conn_pat(name: &str) -> String { + format!( + r"{}\s+connected.+?(?P\d+)x(?P\d+)\+(?P\d+)\+(?P\d+).*?\n", + name + ) +} + pub fn resolutions(name: &str) -> Vec { + let resolutions_pat = r"(?P(\s*\d+x\d+\s+\d+.*\n)+)"; + let connected_pat = get_xrandr_conn_pat(name); let mut v = vec![]; - let mut parser = Parser::new(); - if parser.parse().is_ok() { - if let Ok(connector) = parser.get_connector(name) { - if let Ok(resolutions) = &connector.available_resolutions() { - for r in resolutions { - if let Ok(width) = r.horizontal.parse::() { - if let Ok(height) = r.vertical.parse::() { - let resolution = Resolution { - width, - height, - ..Default::default() - }; - if !v.contains(&resolution) { - v.push(resolution); + if let Ok(re) = Regex::new(&format!("{}{}", connected_pat, resolutions_pat)) { + match run_cmds("xrandr --query | tr -s ' '".to_owned()) { + Ok(xrandr_output) => { + // There'are different kinds of xrandr output. + /* + 1. + Screen 0: minimum 320 x 175, current 1920 x 1080, maximum 1920 x 1080 + default connected 1920x1080+0+0 0mm x 0mm + 1920x1080 10.00* + 1280x720 25.00 + 1680x1050 60.00 + Virtual2 disconnected (normal left inverted right x axis y axis) + Virtual3 disconnected (normal left inverted right x axis y axis) + + XWAYLAND0 connected primary 1920x984+0+0 (normal left inverted right x axis y axis) 0mm x 0mm + Virtual1 connected primary 1920x984+0+0 (normal left inverted right x axis y axis) 0mm x 0mm + HDMI-0 connected (normal left inverted right x axis y axis) + + rdp0 connected primary 1920x1080+0+0 0mm x 0mm + */ + if let Some(caps) = re.captures(&xrandr_output) { + if let Some(resolutions) = caps.name("resolutions") { + let resolution_pat = + r"\s*(?P\d+)x(?P\d+)\s+(?P(\d+\.\d+[* ]*)+)\s*\n"; + let resolution_re = Regex::new(&format!(r"{}", resolution_pat)).unwrap(); + for resolution_caps in resolution_re.captures_iter(resolutions.as_str()) { + if let Some((width, height)) = + get_width_height_from_captures(&resolution_caps) + { + let resolution = Resolution { + width, + height, + ..Default::default() + }; + if !v.contains(&resolution) { + v.push(resolution); + } } } } } } + Err(e) => log::error!("Failed to run xrandr query, {}", e), } } + v } pub fn current_resolution(name: &str) -> ResultType { - let mut parser = Parser::new(); - parser.parse().map_err(|e| anyhow!(e))?; - let connector = parser.get_connector(name).map_err(|e| anyhow!(e))?; - let r = connector.current_resolution(); - let width = r.horizontal.parse::()?; - let height = r.vertical.parse::()?; - Ok(Resolution { - width, - height, - ..Default::default() - }) + let xrandr_output = run_cmds("xrandr --query | tr -s ' '".to_owned())?; + let re = Regex::new(&get_xrandr_conn_pat(name))?; + if let Some(caps) = re.captures(&xrandr_output) { + if let Some((width, height)) = get_width_height_from_captures(&caps) { + return Ok(Resolution { + width, + height, + ..Default::default() + }); + } + } + bail!("Failed to find current resolution for {}", name); } pub fn change_resolution(name: &str, width: usize, height: usize) -> ResultType<()> {