use std::ffi::{CStr, CString}; use anyhow::{anyhow, bail}; use x11::{xft::{FcPattern, XftColor, XftFont, XftFontOpenName, XftFontOpenPattern, XftNameParse}, xlib::{CapButt, Cursor, Drawable, JoinMiter, LineSolid, Window, XCreateGC, XCreatePixmap, XDefaultDepth, XSetLineAttributes, _XDisplay, GC}}; #[derive(Debug)] pub struct Drw { w: i32, h: i32, display: *mut _XDisplay, screen: i32, drawable: Drawable, gc: GC, scheme: *mut Clr, fontset: Vec, root: Window, } #[derive(Debug)] pub struct Cur { cursor: Cursor, } type Clr = XftColor; #[derive(Debug)] pub struct Fnt { display: *mut _XDisplay, h: i32, xfont: *mut XftFont, pattern: *mut FcPattern, } impl Drw { pub fn new(display: *mut _XDisplay, screen: i32, root: Window, w: i32, h: i32, fonts: Vec<&str>) -> anyhow::Result { unsafe { let mut s = Self { display, screen, root, w, h, drawable: Drawable::from(XCreatePixmap(display, root, w as u32, h as u32, XDefaultDepth(display, screen) as u32)), gc: XCreateGC(display, root, 0, std::ptr::null_mut()), fontset: Vec::new(), scheme: std::ptr::null_mut(), }; XSetLineAttributes(display, s.gc, 1, LineSolid, CapButt, JoinMiter); s.fontset = s.font_set_create(fonts)?; Ok(s) } } fn font_set_create(&mut self, fonts: Vec<&str>) -> anyhow::Result> { let mut set = Vec::new(); for i in 1..=fonts.len() { if let Ok(next) = unsafe { self.font_create(Some(fonts[fonts.len() - i]), std::ptr::null_mut()) } { set.push(next); } } Ok(set) } unsafe fn font_create(&mut self, fontname: Option<&str>, fontpattern: *mut FcPattern) -> anyhow::Result { let mut font: Fnt = std::mem::zeroed(); let xfont: *mut XftFont; let mut pattern: *mut FcPattern = std::ptr::null_mut(); if let Some(fontname) = fontname { let font_name_c = CString::new(fontname)?.as_ptr(); xfont = XftFontOpenName(self.display, self.screen, font_name_c); if xfont.is_null() { log::error!("Cannot load font from name {}", fontname); bail!(""); } pattern = XftNameParse(font_name_c); if pattern.is_null() { log::error!("Cannot parse font name to pattern"); bail!(""); } } else if !fontpattern.is_null() { xfont = XftFontOpenPattern(self.display, fontpattern); if xfont.is_null() { log::error!("Cannot load font from pattern"); bail!(""); } } else { log::error!("No font name specified"); bail!(""); } font.xfont = xfont; font.pattern = pattern; font.h = (*xfont).ascent + (*xfont).descent; font.display = self.display; Ok(font) } }