x11-overlay 0.1.0

A library for creating overlay interfaces on X11 systems using Cairo for rendering
Documentation
use x11rb::protocol::xproto::*;

pub fn find_visual_by_depth(screen: &Screen, depth: u8) -> Option<Visualtype> {
    screen
        .allowed_depths
        .iter()
        .filter(|depth_info| depth_info.depth == depth)
        .flat_map(|depth_info| &depth_info.visuals)
        .find(|visual| visual.class == VisualClass::TRUE_COLOR)
        .copied()
}

pub fn find_argb_visual(screen: &Screen) -> Option<Visualtype> {
    find_visual_by_depth(screen, 32)
}

pub fn find_rgb_visual(screen: &Screen) -> Option<Visualtype> {
    find_visual_by_depth(screen, 24)
}

pub fn get_visual_info(visual: &Visualtype) -> VisualInfo {
    let r_bits = visual.red_mask.count_ones() as u8;
    let g_bits = visual.green_mask.count_ones() as u8;
    let b_bits = visual.blue_mask.count_ones() as u8;

    let r_shift = visual.red_mask.trailing_zeros() as u8;
    let g_shift = visual.green_mask.trailing_zeros() as u8;
    let b_shift = visual.blue_mask.trailing_zeros() as u8;

    VisualInfo {
        visual_id: visual.visual_id,
        class: visual.class,
        bits_per_rgb: visual.bits_per_rgb_value,
        colormap_entries: visual.colormap_entries,
        red_mask: visual.red_mask,
        green_mask: visual.green_mask,
        blue_mask: visual.blue_mask,
        red_bits: r_bits,
        green_bits: g_bits,
        blue_bits: b_bits,
        red_shift: r_shift,
        green_shift: g_shift,
        blue_shift: b_shift,
        total_bits: r_bits + g_bits + b_bits,
    }
}

#[derive(Debug, Clone)]
pub struct VisualInfo {
    pub visual_id: Visualid,
    pub class: VisualClass,
    pub bits_per_rgb: u8,
    pub colormap_entries: u16,
    pub red_mask: u32,
    pub green_mask: u32,
    pub blue_mask: u32,
    pub red_bits: u8,
    pub green_bits: u8,
    pub blue_bits: u8,
    pub red_shift: u8,
    pub green_shift: u8,
    pub blue_shift: u8,
    pub total_bits: u8,
}

impl VisualInfo {
    pub fn supports_transparency(&self) -> bool {
        self.total_bits > 24
    }

    pub fn pack_rgb(&self, r: u8, g: u8, b: u8) -> u32 {
        ((r as u32) << self.red_shift)
            | ((g as u32) << self.green_shift)
            | ((b as u32) << self.blue_shift)
    }

    pub fn pack_argb(&self, a: u8, r: u8, g: u8, b: u8) -> u32 {
        if self.supports_transparency() {
            ((a as u32) << 24) | self.pack_rgb(r, g, b)
        } else {
            self.pack_rgb(r, g, b)
        }
    }

    pub fn unpack_rgb(&self, pixel: u32) -> (u8, u8, u8) {
        let r = ((pixel & self.red_mask) >> self.red_shift) as u8;
        let g = ((pixel & self.green_mask) >> self.green_shift) as u8;
        let b = ((pixel & self.blue_mask) >> self.blue_shift) as u8;
        (r, g, b)
    }
}