pub mod awesome;
use crate::ported::lib::shell::run_cmd;
use regex::Regex;
use std::collections::HashMap;
use std::sync::OnceLock;
#[allow(non_upper_case_globals)]
pub const DEFAULT_UPDATE_INTERVAL: f64 = 0.5;
pub fn i3_subscribe<F>(_conn: &(), _event: &str, _callback: F)
where
F: Fn() + Send + 'static,
{
}
pub fn get_i3_connection() {
}
#[allow(non_snake_case)]
pub fn XRANDR_OUTPUT_RE() -> &'static Regex {
static R: OnceLock<Regex> = OnceLock::new();
R.get_or_init(|| {
Regex::new(
r"(?m)^(?P<name>[0-9A-Za-z-]+) connected(?P<primary> primary)? (?P<width>\d+)x(?P<height>\d+)\+(?P<x>\d+)\+(?P<y>\d+)",
)
.unwrap()
})
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct XrandrOutput {
pub name: String,
pub primary: bool,
pub width: u32,
pub height: u32,
pub x: i32,
pub y: i32,
}
pub fn get_connected_xrandr_outputs(pl: &()) -> Vec<XrandrOutput> {
let output = match run_cmd(pl, &["xrandr".to_string(), "-q".to_string()], None, true) {
Some(s) => s,
None => return Vec::new(),
};
let re = XRANDR_OUTPUT_RE();
re.captures_iter(&output)
.map(|cap| XrandrOutput {
name: cap
.name("name")
.map(|m| m.as_str().to_string())
.unwrap_or_default(),
primary: cap.name("primary").is_some(),
width: cap
.name("width")
.and_then(|m| m.as_str().parse().ok())
.unwrap_or(0),
height: cap
.name("height")
.and_then(|m| m.as_str().parse().ok())
.unwrap_or(0),
x: cap
.name("x")
.and_then(|m| m.as_str().parse().ok())
.unwrap_or(0),
y: cap
.name("y")
.and_then(|m| m.as_str().parse().ok())
.unwrap_or(0),
})
.collect()
}
#[allow(non_upper_case_globals)]
pub fn wm_threads() -> &'static HashMap<&'static str, &'static str> {
static M: OnceLock<HashMap<&'static str, &'static str>> = OnceLock::new();
M.get_or_init(|| {
let mut m = HashMap::new();
m.insert("awesome", "AwesomeThread");
m
})
}
pub fn run<F>(conn_main: F)
where
F: FnOnce(),
{
conn_main()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_update_interval_matches_upstream() {
assert_eq!(DEFAULT_UPDATE_INTERVAL, 0.5);
}
#[test]
fn xrandr_regex_matches_standard_line() {
let sample = "HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 521mm x 293mm";
let re = XRANDR_OUTPUT_RE();
assert!(re.is_match(sample));
let cap = re.captures(sample).unwrap();
assert_eq!(cap.name("name").unwrap().as_str(), "HDMI-1");
assert_eq!(cap.name("width").unwrap().as_str(), "1920");
assert_eq!(cap.name("height").unwrap().as_str(), "1080");
assert!(cap.name("primary").is_some());
}
#[test]
fn xrandr_regex_handles_non_primary() {
let sample = "DP-1 connected 2560x1440+1920+0";
let cap = XRANDR_OUTPUT_RE().captures(sample).unwrap();
assert!(cap.name("primary").is_none());
assert_eq!(cap.name("name").unwrap().as_str(), "DP-1");
}
#[test]
fn get_connected_xrandr_outputs_returns_empty_when_xrandr_unavailable() {
let outputs = get_connected_xrandr_outputs(&());
assert!(outputs.is_empty() || outputs.iter().all(|o| !o.name.is_empty()));
}
#[test]
fn wm_threads_registers_awesome() {
let m = wm_threads();
assert!(m.contains_key("awesome"));
}
}