config stuff

This commit is contained in:
missing 2022-06-26 13:40:34 -05:00
parent c9d07378c0
commit 204518016b
4 changed files with 137 additions and 73 deletions

2
run.sh
View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
cargo build; cargo build || exit;
XEPHYR=$(which Xephyr | cut -f2 -d' ') XEPHYR=$(which Xephyr | cut -f2 -d' ')
xinit ./xinitrc -- \ xinit ./xinitrc -- \

View file

@ -7,30 +7,34 @@ use serde::{Deserialize, Serialize};
pub struct XcrabConfig { pub struct XcrabConfig {
border_color: Option<u32>, border_color: Option<u32>,
border_size: Option<u16>, border_size: Option<u16>,
gap_width: Option<u16>, gap_size: Option<u16>,
} }
const DEFAULT_BORDER_COLOR: u32 = 0xff_00_00; // red
const DEFAULT_BORDER_SIZE: u16 = 5;
const DEFAULT_GAP_SIZE: u16 = 10;
impl Default for XcrabConfig { impl Default for XcrabConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
border_color: Some(0xff_00_00), // red border_color: Some(DEFAULT_BORDER_COLOR),
border_size: Some(5), border_size: Some(DEFAULT_BORDER_SIZE),
gap_width: Some(10), gap_size: Some(DEFAULT_GAP_SIZE),
} }
} }
} }
impl XcrabConfig { impl XcrabConfig {
pub fn border_color(&self) -> u32 { pub fn border_color(&self) -> u32 {
self.border_color.unwrap_or(0xff_00_00) self.border_color.unwrap_or(DEFAULT_BORDER_COLOR)
} }
pub fn border_size(&self) -> u16 { pub fn border_size(&self) -> u16 {
self.border_size.unwrap_or(5) self.border_size.unwrap_or(DEFAULT_BORDER_SIZE)
} }
pub fn gap_width(&self) -> u16 { pub fn gap_size(&self) -> u16 {
self.gap_width.unwrap_or(10) self.gap_size.unwrap_or(DEFAULT_GAP_SIZE)
} }
} }

View file

@ -2,7 +2,7 @@ use breadx::prelude::{AsyncDisplayXprotoExt, SetMode};
use breadx::{AsyncDisplay, ConfigureWindowParameters, EventMask, Window}; use breadx::{AsyncDisplay, ConfigureWindowParameters, EventMask, Window};
use std::collections::HashMap; use std::collections::HashMap;
use crate::{Result, XcrabError}; use crate::{Result, XcrabError, CONFIG};
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Direction { pub enum Direction {
@ -23,6 +23,12 @@ pub struct XcrabWindowManager {
#[allow(clippy::module_name_repetitions)] #[allow(clippy::module_name_repetitions)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct XcrabClient { struct XcrabClient {
frame: FramedWindow,
geo: XcrabGeometry,
}
#[derive(Debug, Clone, Copy)]
struct XcrabGeometry {
x: u32, x: u32,
y: u32, y: u32,
width: u32, width: u32,
@ -51,6 +57,7 @@ impl XcrabWindowManager {
let frame = frame(conn, win).await?; let frame = frame(conn, win).await?;
if let Some(focused) = self.focused { if let Some(focused) = self.focused {
#[allow(clippy::enum_glob_use)]
use Direction::*; use Direction::*;
let focused_client = *self let focused_client = *self
@ -60,10 +67,10 @@ impl XcrabWindowManager {
let new_client = match direction { let new_client = match direction {
Up | Down => { Up | Down => {
if focused_client.height % 2 == 1 { if focused_client.geo.height % 2 == 1 {
for client in self.clients.values_mut() { for client in self.clients.values_mut() {
client.y *= 2; client.geo.y *= 2;
client.height *= 2; client.geo.height *= 2;
} }
self.grid_height *= 2; self.grid_height *= 2;
@ -71,24 +78,24 @@ impl XcrabWindowManager {
let focused_client = self.clients.get_mut(&focused).unwrap(); let focused_client = self.clients.get_mut(&focused).unwrap();
focused_client.height /= 2; focused_client.geo.height /= 2;
let height = focused_client.height; let height = focused_client.geo.height;
let mut new_client = *focused_client; let mut new_client = XcrabClient { frame, geo: focused_client.geo };
if let Up = direction { if let Up = direction {
focused_client.y += height; focused_client.geo.y += height;
} else { } else {
new_client.y += height; new_client.geo.y += height;
} }
new_client new_client
} }
Left | Right => { Left | Right => {
if focused_client.width % 2 == 1 { if focused_client.geo.width % 2 == 1 {
for client in self.clients.values_mut() { for client in self.clients.values_mut() {
client.x *= 2; client.geo.x *= 2;
client.width *= 2; client.geo.width *= 2;
} }
self.grid_width *= 2; self.grid_width *= 2;
@ -96,15 +103,15 @@ impl XcrabWindowManager {
let focused_client = self.clients.get_mut(&focused).unwrap(); let focused_client = self.clients.get_mut(&focused).unwrap();
focused_client.width /= 2; focused_client.geo.width /= 2;
let width = focused_client.width; let width = focused_client.geo.width;
let mut new_client = *focused_client; let mut new_client = XcrabClient { frame, geo: focused_client.geo };
if let Left = direction { if let Left = direction {
focused_client.x += width; focused_client.geo.x += width;
} else { } else {
new_client.x += width; new_client.geo.x += width;
} }
new_client new_client
@ -121,13 +128,15 @@ impl XcrabWindowManager {
self.grid_width = 1; self.grid_width = 1;
self.grid_height = 1; self.grid_height = 1;
let client = XcrabClient { let geo = XcrabGeometry {
x: 0, x: 0,
y: 0, y: 0,
width: 1, width: 1,
height: 1, height: 1,
}; };
let client = XcrabClient { frame, geo };
self.clients.insert(win, client); self.clients.insert(win, client);
self.update_client(conn, win).await?; self.update_client(conn, win).await?;
@ -135,8 +144,7 @@ impl XcrabWindowManager {
self.focused = Some(win); self.focused = Some(win);
} }
win.map_async(conn).await?; frame.map(conn).await?;
frame.map_async(conn).await?;
Ok(()) Ok(())
} }
@ -156,15 +164,14 @@ impl XcrabWindowManager {
let root_width: u32 = root_geo.width.into(); let root_width: u32 = root_geo.width.into();
let root_height: u32 = root_geo.height.into(); let root_height: u32 = root_geo.height.into();
let x = (client.x * root_width) / self.grid_width; let x = (client.geo.x * root_width) / self.grid_width;
let y = (client.y * root_height) / self.grid_height; let y = (client.geo.y * root_height) / self.grid_height;
let width = (client.width * root_width) / self.grid_width; let width = (client.geo.width * root_width) / self.grid_width;
let height = (client.height * root_height) / self.grid_height; let height = (client.geo.height * root_height) / self.grid_height;
let parent = win.query_tree_immediate_async(conn).await?.parent; client
.frame
parent .configure(
.configure_async(
conn, conn,
ConfigureWindowParameters { ConfigureWindowParameters {
x: Some(x.try_into().unwrap()), x: Some(x.try_into().unwrap()),
@ -176,18 +183,6 @@ impl XcrabWindowManager {
) )
.await?; .await?;
win.configure_async(
conn,
ConfigureWindowParameters {
x: Some(0),
y: Some(0),
width: Some(width),
height: Some(height),
..Default::default()
},
)
.await?;
Ok(()) Ok(())
} }
@ -200,47 +195,112 @@ impl XcrabWindowManager {
conn: &mut Dpy, conn: &mut Dpy,
win: Window, win: Window,
) -> Result<()> { ) -> Result<()> {
// TODO: maybe an `unframe` method? self.clients
let root = conn.default_root(); .remove(&win)
.ok_or(XcrabError::ClientDoesntExist)?
let parent = win.query_tree_immediate_async(conn).await?.parent; .frame
.unframe(conn)
parent.unmap_async(conn).await?; .await?;
win.reparent_async(conn, root, 0, 0).await?;
// no longer related to us, remove from save set
win.change_save_set_async(conn, SetMode::Delete).await?;
parent.free_async(conn).await?;
self.clients.remove(&win);
Ok(()) Ok(())
} }
} }
async fn frame<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy, win: Window) -> Result<Window> { #[derive(Debug, Clone, Copy)]
const GAP_WIDTH: u16 = 10; struct FramedWindow {
frame: Window,
win: Window,
}
impl FramedWindow {
async fn configure<Dpy: AsyncDisplay + ?Sized>(
self,
conn: &mut Dpy,
props: ConfigureWindowParameters,
) -> Result<()> {
let border_size = CONFIG.border_size();
let gap_size = CONFIG.gap_size();
let coordinate_inset = i32::from(gap_size);
let dimension_inset = 2 * (u32::from(gap_size) + u32::from(border_size));
let width = props.width.map(|v| v - dimension_inset);
let height = props.height.map(|v| v - dimension_inset);
self.frame
.configure_async(
conn,
ConfigureWindowParameters {
x: props.x.map(|v| v + coordinate_inset),
y: props.y.map(|v| v + coordinate_inset),
width,
height,
border_width: Some(border_size.into()),
..Default::default()
},
)
.await?;
self.win
.configure_async(
conn,
ConfigureWindowParameters {
x: Some(-1),
y: Some(-1),
width,
height,
..Default::default()
},
)
.await?;
Ok(())
}
async fn map<Dpy: AsyncDisplay + ?Sized>(self, conn: &mut Dpy) -> Result<()> {
self.win.map_async(conn).await?;
self.frame.map_async(conn).await?;
Ok(())
}
async fn unframe<Dpy: AsyncDisplay + ?Sized>(self, conn: &mut Dpy) -> Result<()> {
let root = conn.default_root();
self.frame.unmap_async(conn).await?;
self.win.reparent_async(conn, root, 0, 0).await?;
// no longer related to us, remove from save set
self.win
.change_save_set_async(conn, SetMode::Delete)
.await?;
self.frame.free_async(conn).await?;
Ok(())
}
}
async fn frame<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy, win: Window) -> Result<FramedWindow> {
let root = conn.default_root(); let root = conn.default_root();
let geometry = win.geometry_immediate_async(conn).await?; let geometry = win.geometry_immediate_async(conn).await?;
let parent = conn let frame = conn
.create_simple_window_async( .create_simple_window_async(
root, root,
geometry.x, geometry.x,
geometry.y, geometry.y,
geometry.width, geometry.width,
geometry.height, geometry.height,
crate::CONFIG.border_size(), CONFIG.border_size(),
crate::CONFIG.border_color(), CONFIG.border_color(),
0x00_00_00, 0x00_00_00,
) )
.await?; .await?;
parent frame
.set_event_mask_async( .set_event_mask_async(
conn, conn,
EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY, EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY,
@ -249,7 +309,7 @@ async fn frame<Dpy: AsyncDisplay + ?Sized>(conn: &mut Dpy, win: Window) -> Resul
win.change_save_set_async(conn, SetMode::Insert).await?; win.change_save_set_async(conn, SetMode::Insert).await?;
win.reparent_async(conn, parent, 0, 0).await?; win.reparent_async(conn, frame, 0, 0).await?;
Ok(parent) Ok(FramedWindow { frame, win })
} }

View file

@ -3,6 +3,6 @@
xclock & xclock &
xterm & xterm &
sleep 2; sleep 0.5;
target/debug/xcrab target/debug/xcrab