made border colors configurable in the config file

This commit is contained in:
Janis 2021-11-28 22:39:38 +01:00
parent 3a56102ec2
commit ece0eb7903
6 changed files with 132 additions and 47 deletions

View file

@ -7,7 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
x11 = {version = "2.18.2", features = ["xlib"] }
x11 = {version = "2.18.2", features = ["xlib", "xft"] }
log = "0.4.13"
simple_logger = "1.11.0"
dirs = "3.0.2"

View file

@ -40,6 +40,9 @@ pub trait WindowServerBackend {
fn all_windows(&self) -> Option<Vec<Self::Window>>;
fn set_active_window_border_color(&mut self, color_name: &str);
fn set_inactive_window_border_color(&mut self, color_name: &str);
fn resize_window(&self, window: Self::Window, new_size: Point<i32>) {
self.configure_window(window, Some(new_size), None, None);
}

View file

@ -0,0 +1,45 @@
use std::mem::MaybeUninit;
use x11::{xft, xlib};
use super::Display;
pub struct XftColor {
inner: xft::XftColor,
}
impl XftColor {
pub fn pixel(&self) -> u64 {
self.inner.pixel
}
pub fn color(&self) -> x11::xrender::XRenderColor {
self.inner.color
}
pub fn new(
dpy: Display,
screen: i32,
mut color_name: String,
) -> Result<Self, std::io::Error> {
color_name.push('\0');
let mut color = MaybeUninit::<xft::XftColor>::zeroed();
unsafe {
xft::XftColorAllocName(
dpy.get(),
xlib::XDefaultVisual(dpy.get(), screen),
xlib::XDefaultColormap(dpy.get(), screen),
color_name.as_ptr() as *mut _,
color.as_mut_ptr(),
) != 0
}
.then(|| Self {
inner: unsafe { color.assume_init() },
})
.ok_or(std::io::Error::new(
std::io::ErrorKind::NotFound,
"Unable to allocate color.",
))
}
}

View file

@ -28,6 +28,7 @@ use super::{
WindowServerBackend,
};
pub mod color;
pub mod keysym;
pub type XLibWindowEvent = WindowEvent<xlib::Window>;
@ -100,31 +101,6 @@ impl From<u8> for XlibError {
}
}
// impl Into<i32> for XlibError {
// fn into(self) -> i32 {
// match self {
// XlibError::BadAccess => xlib::BadAccess.into(),
// XlibError::BadAlloc => xlib::BadAlloc.into(),
// XlibError::BadAtom => xlib::BadAtom.into(),
// XlibError::BadColor => xlib::BadColor.into(),
// XlibError::BadCursor => xlib::BadCursor.into(),
// XlibError::BadDrawable => xlib::BadDrawable.into(),
// XlibError::BadFont => xlib::BadFont.into(),
// XlibError::BadGC => xlib::BadGC.into(),
// XlibError::BadIDChoice => xlib::BadIDChoice.into(),
// XlibError::BadImplementation => xlib::BadImplementation.into(),
// XlibError::BadLength => xlib::BadLength.into(),
// XlibError::BadMatch => xlib::BadMatch.into(),
// XlibError::BadName => xlib::BadName.into(),
// XlibError::BadPixmap => xlib::BadPixmap.into(),
// XlibError::BadRequest => xlib::BadRequest.into(),
// XlibError::BadValue => xlib::BadValue.into(),
// XlibError::BadWindow => xlib::BadWindow.into(),
// XlibError::InvalidError(err) => err,
// }
// }
// }
impl Display {
pub fn new(display: *mut x11::xlib::Display) -> Self {
Self {
@ -144,6 +120,8 @@ pub struct XLib {
screen: i32,
atoms: XLibAtoms,
keybinds: Vec<KeyOrMouseBind>,
active_border_color: Option<color::XftColor>,
inactive_border_color: Option<color::XftColor>,
}
impl Drop for XLib {
@ -174,6 +152,8 @@ impl XLib {
modifier_state: ModifierState::empty(),
atoms,
keybinds: Vec::new(),
active_border_color: None,
inactive_border_color: None,
}
}
@ -684,12 +664,18 @@ impl WindowServerBackend for XLib {
xlib::CurrentTime,
);
// TODO: make painting the window border a seperate function, and configurable
let screen = xlib::XDefaultScreenOfDisplay(self.dpy()).as_ref();
let border_color = self
.active_border_color
.as_ref()
.map(|color| color.pixel())
.unwrap_or_else(|| {
xlib::XDefaultScreenOfDisplay(self.dpy())
.as_ref()
.unwrap()
.white_pixel
});
if let Some(screen) = screen {
xlib::XSetWindowBorder(self.dpy(), window, screen.white_pixel);
}
xlib::XSetWindowBorder(self.dpy(), window, border_color);
xlib::XChangeProperty(
self.dpy(),
@ -716,11 +702,19 @@ impl WindowServerBackend for XLib {
);
// TODO: make painting the window border a seperate function, and configurable
let screen = xlib::XDefaultScreenOfDisplay(self.dpy()).as_ref();
if let Some(screen) = screen {
xlib::XSetWindowBorder(self.dpy(), window, screen.black_pixel);
}
let border_color = self
.inactive_border_color
.as_ref()
.map(|color| color.pixel())
.unwrap_or_else(|| {
xlib::XDefaultScreenOfDisplay(self.dpy())
.as_ref()
.unwrap()
.black_pixel
});
xlib::XSetWindowBorder(self.dpy(), window, border_color);
xlib::XDeleteProperty(
self.dpy(),
@ -885,6 +879,24 @@ impl WindowServerBackend for XLib {
windows
})
}
fn set_active_window_border_color(&mut self, color_name: &str) {
self.active_border_color = color::XftColor::new(
self.display.clone(),
self.screen,
color_name.to_owned(),
)
.ok();
}
fn set_inactive_window_border_color(&mut self, color_name: &str) {
self.inactive_border_color = color::XftColor::new(
self.display.clone(),
self.screen,
color_name.to_owned(),
)
.ok();
}
}
struct XLibAtoms {

View file

@ -858,7 +858,7 @@ impl VirtualScreenStore {
fn go_to_nth(&mut self, n: usize) -> usize {
self.last_idx = Some(self.current_idx);
self.current_idx = n % self.screens.len();
self.current_idx = n.min(self.screens.len() - 1);
self.current_idx
}

View file

@ -34,6 +34,35 @@ pub struct WMConfig {
mod_key: ModifierKey,
gap: Option<i32>,
kill_clients_on_exit: bool,
#[serde(default = "WMConfig::default_active_window_border_color")]
active_window_border_color: String,
#[serde(default = "WMConfig::default_inactive_window_border_color")]
inactive_window_border_color: String,
}
impl WMConfig {
fn default_active_window_border_color() -> String {
"#ffffff".to_string()
}
fn default_inactive_window_border_color() -> String {
"#444444".to_string()
}
}
impl Default for WMConfig {
fn default() -> Self {
Self {
num_virtualscreens: 10,
mod_key: ModifierKey::Super,
gap: Some(2),
kill_clients_on_exit: false,
active_window_border_color:
Self::default_active_window_border_color(),
inactive_window_border_color:
Self::default_inactive_window_border_color(),
}
}
}
pub struct WindowManager<B = XLib>
@ -256,6 +285,13 @@ where
self.add_vs_switch_keybinds();
self.backend.set_active_window_border_color(
&self.config.active_window_border_color,
);
self.backend.set_inactive_window_border_color(
&self.config.inactive_window_border_color,
);
// add all already existing windows to the WM
if let Some(windows) = self.backend.all_windows() {
windows
@ -869,17 +905,6 @@ where
}
}
impl Default for WMConfig {
fn default() -> Self {
Self {
num_virtualscreens: 10,
mod_key: ModifierKey::Super,
gap: Some(2),
kill_clients_on_exit: false,
}
}
}
impl Direction {
fn west() -> Self {
Direction::West(1)