rwm/src/server/drw.rs
2024-07-23 14:27:31 +03:00

104 lines
3.1 KiB
Rust

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<Fnt>,
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<Self> {
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<Vec<Fnt>> {
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<Fnt> {
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)
}
}