/* Color management in X has become an obscure topic because everyone prefers * to assume they have 24-bit direct. In dealing with it, [1] has been an * important resource. * * [1] https://xcb.freedesktop.org/xlibtoxcbtranslationguide/ */ use crate::x::connection::*; use crate::x::display::*; use x11::xrender::XRenderColor; use x11::xft::XftColor; use xcb::x::{ AllocColor, Visualtype }; pub struct Color { /* We need to store both the original 16-bit components and the pixel * value. Additionally, there are situations in which we need to return * an XftColor, which contains both of those. So, we might as well use it * as the authoritative format. * * We treat the contents as opaque, to allow us to pretend it's * something cleaner. :) */ font_color: XftColor, } impl Color { /* Please notice that the constructor is private. */ fn new(pixel: u32, red: u16, green: u16, blue: u16) -> Self { Color { font_color: XftColor { pixel: pixel as u64, color: XRenderColor { red, green, blue, alpha: 65535, } } } } pub fn as_pixel(&self) -> u32 { self.font_color.pixel as u32 } pub fn as_xft_color(&self) -> &XftColor { &self.font_color } } pub trait DisplayColorExt: DisplayExt { /* This is sufficiently obscure knowledge that it's worth keeping here * even though it's unused. */ #[allow(dead_code)] fn find_root_visual(&self) -> Option<&Visualtype> { let visual_id = self.screen().root_visual(); for depth in self.screen().allowed_depths() { for visual in depth.visuals() { if visual_id == visual.visual_id() { return Some(visual); } } } None } fn allocate_color(&self, red: u16, green: u16, blue: u16) -> xcb::Result { let connection = self.connection(); let colormap = self.screen().default_colormap(); let cookie = connection.send_request(&AllocColor { cmap: colormap, red, green, blue, }); let pixel = connection.wait_for_reply(cookie)?.pixel(); Ok(Color::new(pixel, red, green, blue)) } } impl DisplayColorExt for T { }