Rewrite X11 backend to drop xcap

Use x11rb directly for screenshot capture and window metadata so the Linux build no longer drags in Wayland build dependencies.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Harivansh Rathi 2026-03-25 12:28:23 -04:00
parent cc7490993a
commit e392ba1055
11 changed files with 488 additions and 2128 deletions

View file

@ -21,10 +21,14 @@ pub struct Response {
impl Request {
pub fn new(action: &str) -> Self {
Self {
id: format!("r{}", std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_micros() % 1_000_000),
id: format!(
"r{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_micros()
% 1_000_000
),
action: action.to_string(),
extra: Value::Object(serde_json::Map::new()),
}
@ -40,10 +44,18 @@ impl Request {
impl Response {
pub fn ok(data: Value) -> Self {
Self { success: true, data: Some(data), error: None }
Self {
success: true,
data: Some(data),
error: None,
}
}
pub fn err(msg: impl Into<String>) -> Self {
Self { success: false, data: None, error: Some(msg.into()) }
Self {
success: false,
data: None,
error: Some(msg.into()),
}
}
}

View file

@ -1,5 +1,5 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[allow(dead_code)]
@ -26,7 +26,10 @@ pub struct RefMap {
#[allow(dead_code)]
impl RefMap {
pub fn new() -> Self {
Self { map: HashMap::new(), next_ref: 1 }
Self {
map: HashMap::new(),
next_ref: 1,
}
}
pub fn clear(&mut self) {
@ -57,16 +60,14 @@ impl RefMap {
// Try substring match on app_class or title (case-insensitive)
let lower = selector.to_lowercase();
self.map.values().find(|e| {
e.app_class.to_lowercase().contains(&lower)
|| e.title.to_lowercase().contains(&lower)
e.app_class.to_lowercase().contains(&lower) || e.title.to_lowercase().contains(&lower)
})
}
/// Resolve a selector to the center coordinates of the window.
pub fn resolve_to_center(&self, selector: &str) -> Option<(i32, i32)> {
self.resolve(selector).map(|e| {
(e.x + e.width as i32 / 2, e.y + e.height as i32 / 2)
})
self.resolve(selector)
.map(|e| (e.x + e.width as i32 / 2, e.y + e.height as i32 / 2))
}
pub fn entries(&self) -> impl Iterator<Item = (&String, &RefEntry)> {