use crate::{ config::{BORDER_FOCUSED, BORDER_NORMAL}, error::Result, }; use xcb::{ x::{AllocColor, Colormap, FreeColors}, Connection as RawConnection, }; /// Caches colours in an X11 color map. pub struct Colours { #[allow(unused)] // Make sure the colour map we're using doesn't go anywhere cmap: Colormap, border_normal: u32, border_focused: u32, } impl Colours { /// Load the colours into the given colour map pub fn new_with(conn: &RawConnection, cmap: Colormap) -> Result { // TODO: Move these colours out to config.rs let (border_normal, border_focused) = ( conn.send_request(&AllocColor { cmap, red: BORDER_NORMAL.0, green: BORDER_NORMAL.1, blue: BORDER_NORMAL.2, }), conn.send_request(&AllocColor { cmap, red: BORDER_FOCUSED.0, green: BORDER_FOCUSED.1, blue: BORDER_FOCUSED.2, }), ); let (border_normal, border_focused) = ( conn.wait_for_reply(border_normal)?, conn.wait_for_reply(border_focused)?, ); Ok(Self { cmap, border_normal: border_normal.pixel(), border_focused: border_focused.pixel(), }) } /// Get the pixel ID of the colour for an unfocused window's border. pub const fn border_normal(&self) -> u32 { self.border_normal } /// Get the pixel ID of the colour for a focused window's border. pub const fn border_focused(&self) -> u32 { self.border_focused } /// Free the associated resources to avoid leaking them. /// This object must not be used again after this method is called, as all resources will be invalid. pub unsafe fn free(&self, conn: &RawConnection) { conn.send_request(&FreeColors { cmap: self.cmap, plane_mask: 0, pixels: &[self.border_normal, self.border_focused], }); } } /// RGB Colour helper struct to make configuration more convenient. pub struct Colour(u16, u16, u16); impl Colour { /// Get colour from a hex value, such as `0xff00ff`. The top 8 bits are ignored. pub const fn from_hex(hex: u32) -> Self { Self( ((hex >> 16 & 0xff) as u16) << 8, ((hex >> 8 & 0xff) as u16) << 8, ((hex & 0xff) as u16) << 8, ) } }