#![allow(dead_code)]
use anyhow::{Context, Result};
use x11rb::connection::Connection;
use x11rb::protocol::xproto::*;
pub mod atoms;
pub mod utils;
pub mod visual;
pub trait X11Extensions {
fn get_screen_dimensions(&self, screen_num: usize) -> Result<(u16, u16)>;
fn is_compositor_running(&self) -> Result<bool>;
fn get_window_manager_name(&self) -> Result<String>;
}
impl<C: Connection> X11Extensions for C {
fn get_screen_dimensions(&self, screen_num: usize) -> Result<(u16, u16)> {
let setup = self.setup();
let screen = setup
.roots
.get(screen_num)
.with_context(|| format!("Screen {} not found", screen_num))?;
Ok((screen.width_in_pixels, screen.height_in_pixels))
}
fn is_compositor_running(&self) -> Result<bool> {
let setup = self.setup();
let _screen = &setup.roots[0];
let selection_name = format!("_NET_WM_CM_S{}", 0);
let atom = self
.intern_atom(false, selection_name.as_bytes())?
.reply()?
.atom;
let owner = self.get_selection_owner(atom)?.reply()?;
Ok(owner.owner != x11rb::NONE)
}
fn get_window_manager_name(&self) -> Result<String> {
let net_supporting_wm_check = self
.intern_atom(false, b"_NET_SUPPORTING_WM_CHECK")?
.reply()?
.atom;
let net_wm_name = self.intern_atom(false, b"_NET_WM_NAME")?.reply()?.atom;
let utf8_string = self.intern_atom(false, b"UTF8_STRING")?.reply()?.atom;
let setup = self.setup();
let root = setup.roots[0].root;
let supporting_window = self
.get_property(false, root, net_supporting_wm_check, AtomEnum::WINDOW, 0, 1)?
.reply()?;
if supporting_window.value.len() >= 4 {
let window = u32::from_ne_bytes([
supporting_window.value[0],
supporting_window.value[1],
supporting_window.value[2],
supporting_window.value[3],
]);
let name_prop = self
.get_property(false, window, net_wm_name, utf8_string, 0, 1024)?
.reply()?;
if !name_prop.value.is_empty() {
return Ok(String::from_utf8_lossy(&name_prop.value).into_owned());
}
}
Ok("Unknown".to_string())
}
}