x11-overlay 0.1.0

A library for creating overlay interfaces on X11 systems using Cairo for rendering
Documentation
#![allow(dead_code)] // Allow unused code for future functionality

use anyhow::{Context, Result};
use x11rb::connection::Connection;
use x11rb::protocol::xproto::*;

pub mod atoms;
pub mod utils;
pub mod visual;

// Unused imports removed to fix clippy warnings

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())
    }
}