use crate::{
core::{
data_types::{Point, Region},
xconnection::Xid,
},
PenroseError, Result,
};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum Prop {
Atom(Vec<String>),
Bytes(Vec<u32>),
Cardinal(u32),
UTF8String(Vec<String>),
Window(Vec<Xid>),
WmHints(WmHints),
WmNormalHints(WmNormalHints),
}
bitflags! {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Default)]
pub struct WmHintsFlags: u32 {
const INPUT_HINT = 0b0000000001;
const STATE_HINT = 0b0000000010;
const ICON_PIXMAP_HINT = 0b0000000100;
const ICON_WINDOW_HINT = 0b0000001000;
const ICON_POSITION_HINT = 0b0000010000;
const ICON_MASK_HINT = 0b0000100000;
const WINDOW_GROUP_HINT = 0b0001000000;
const URGENCY_HINT = 0b0100000000;
}
}
bitflags! {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Default)]
pub struct WmNormalHintsFlags: u32 {
const U_POSITION = 0b0000000001;
const U_SIZE = 0b0000000010;
const P_POSITION = 0b0000000100;
const P_SIZE = 0b0000001000;
const P_MIN_SIZE = 0b0000010000;
const P_MAX_SIZE = 0b0000100000;
const P_RESIZE_INC = 0b0001000000;
const P_ASPECT = 0b0010000000;
const P_BASE_SIZE = 0b0100000000;
const P_WIN_GRAVITY = 0b1000000000;
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum WindowState {
Withdrawn,
Normal,
Iconic,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum MapState {
Unmapped,
UnViewable,
Viewable,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum WindowClass {
CopyFromParent,
InputOutput,
InputOnly,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct WmHints {
pub(crate) flags: WmHintsFlags,
pub(crate) accepts_input: bool,
pub(crate) initial_state: WindowState,
pub(crate) icon_pixmap: u32,
pub(crate) icon_win: Xid,
pub(crate) icon_position: Point,
pub(crate) icon_mask: u32,
pub(crate) window_group: u32,
}
impl WmHints {
pub fn new(
flags: WmHintsFlags,
accepts_input: bool,
initial_state: WindowState,
icon_pixmap: u32,
icon_win: Xid,
icon_position: Point,
icon_mask: u32,
window_group: u32,
) -> Self {
Self {
flags,
accepts_input,
initial_state,
icon_pixmap,
icon_win,
icon_position,
icon_mask,
window_group,
}
}
pub fn try_from_bytes(raw: &[u32]) -> Result<Self> {
if raw.len() != 9 {
return Err(PenroseError::InvalidHints(format!(
"raw bytes should be [u32; 9] for WmHints, got [u32; {}]",
raw.len()
)));
}
let flags = WmHintsFlags::from_bits(raw[0]).unwrap();
let accepts_input = !flags.contains(WmHintsFlags::INPUT_HINT) || raw[1] > 0;
let initial_state = match (flags.contains(WmHintsFlags::STATE_HINT), raw[2]) {
(true, 0) => WindowState::Withdrawn,
(true, 1) | (false, _) => WindowState::Normal,
(true, 2) => WindowState::Iconic,
_ => {
return Err(PenroseError::InvalidHints(format!(
"initial state flag should be 0, 1, 2: got {}",
raw[2]
)))
}
};
Ok(Self {
flags,
accepts_input,
initial_state,
icon_pixmap: raw[3],
icon_win: raw[4],
icon_position: Point::new(raw[5], raw[6]),
icon_mask: raw[7],
window_group: raw[8],
})
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct WmNormalHints {
pub(crate) flags: WmNormalHintsFlags,
pub(crate) base: Option<Region>,
pub(crate) min: Option<Region>,
pub(crate) max: Option<Region>,
pub(crate) user_specified: Option<Region>,
}
impl WmNormalHints {
pub fn new(
flags: WmNormalHintsFlags,
base: Option<Region>,
min: Option<Region>,
max: Option<Region>,
user_specified: Option<Region>,
) -> Self {
Self {
flags,
base,
min,
max,
user_specified,
}
}
pub fn try_from_bytes(raw: &[u32]) -> Result<Self> {
if raw.len() != 18 {
return Err(PenroseError::InvalidHints(format!(
"raw bytes should be [u32; 18] for WmNormalHints, got [u32; {}]",
raw.len()
)));
}
let flags = WmNormalHintsFlags::from_bits(raw[0]).unwrap();
let (x, y) = (raw[1], raw[2]);
let (user_w, user_h) = (raw[3], raw[4]);
let (min_w, min_h) = (raw[5], raw[6]);
let (max_w, max_h) = (raw[7], raw[8]);
let (base_w, base_h) = (raw[15], raw[16]);
let if_set = |x, y, w, h| {
if w > 0 && h > 0 {
Some(Region::new(x, y, w, h))
} else {
None
}
};
Ok(Self {
flags,
base: if_set(x, y, base_w, base_h),
min: if_set(x, y, min_w, min_h),
max: if_set(x, y, max_w, max_h),
user_specified: if_set(x, y, user_w, user_h),
})
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct WindowAttributes {
pub(crate) override_redirect: bool,
pub(crate) map_state: MapState,
pub(crate) window_class: WindowClass,
}
impl WindowAttributes {
pub fn new(override_redirect: bool, map_state: MapState, window_class: WindowClass) -> Self {
Self {
override_redirect,
map_state,
window_class,
}
}
}