summaryrefslogtreecommitdiff
path: root/src/clients/hints.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-07-05 15:34:03 +0100
committertcmal <me@aria.rip>2024-07-15 15:29:55 +0100
commit641d4db398357bd50e83dc77464558acf83d9b1d (patch)
tree135d1783c4b3b3ddcbe155de207f781d06c436a8 /src/clients/hints.rs
parent6d586c8156c20b3dbf7e10e4dae5e14fd34618a5 (diff)
Add deserialisation code for size hints
Diffstat (limited to 'src/clients/hints.rs')
-rw-r--r--src/clients/hints.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/clients/hints.rs b/src/clients/hints.rs
index 182c655..fdfbead 100644
--- a/src/clients/hints.rs
+++ b/src/clients/hints.rs
@@ -103,6 +103,100 @@ impl Ewm {
}
}
+#[derive(Debug)]
+pub struct Size {
+ /// The minimum size this window needs to be useful (width, height).
+ min_size: Option<(u32, u32)>,
+
+ /// The maximum size at which this window can be useful (width, height).
+ max_size: Option<(u32, u32)>,
+
+ /// The increments in which to resize this window (width, height)
+ resize_increments: Option<(u32, u32)>,
+
+ /// The ideal base size of this window (width, height)
+ base_size: Option<(u32, u32)>,
+
+ /// What side of the screen to gravitate this window towards.
+ win_gravity: Gravity,
+}
+
+impl Size {
+ const PROGRAM_MIN_SIZE: u32 = (1 << 4);
+ const PROGRAM_MAX_SIZE: u32 = (1 << 5);
+ const PROGRAM_RESIZE_INC: u32 = (1 << 6);
+ const PROGRAM_BASE_SIZE: u32 = (1 << 8);
+ const PROGRAM_WIN_GRAVITY: u32 = (1 << 9);
+
+ /// Get the size hints for the given window, if they exist and are valid.
+ pub fn get(conn: &Connection<'_>, window: Window) -> Option<Self> {
+ // https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/GetHints.c#L59
+ // https://github.com/mirror/libX11/blob/master/src/Xatomtype.h#L77
+ let hints = conn
+ .wait_for_reply(conn.send_request(&GetProperty {
+ window,
+ delete: false,
+ property: x::ATOM_WM_NORMAL_HINTS,
+ r#type: x::ATOM_WM_SIZE_HINTS,
+ long_offset: 0,
+ long_length: 18,
+ }))
+ .ok()?;
+
+ if hints.r#type() != x::ATOM_WM_SIZE_HINTS || hints.length() < 18 || hints.format() != 32 {
+ return None;
+ }
+
+ let &[flags, _, _, _, _, min_width, min_height, max_width, max_height, width_inc, height_inc, _, _, _, _, base_width, base_height, win_gravity] =
+ hints.value::<u32>()
+ else {
+ unreachable!()
+ };
+
+ Some(Self {
+ min_size: if (flags & Self::PROGRAM_MIN_SIZE) > 0 {
+ Some((min_width, min_height))
+ } else if (flags & Self::PROGRAM_BASE_SIZE) > 0 {
+ Some((base_width, base_height))
+ } else {
+ None
+ },
+ max_size: if (flags & Self::PROGRAM_MAX_SIZE) > 0 {
+ Some((max_width, max_height))
+ } else {
+ None
+ },
+ resize_increments: if (flags & Self::PROGRAM_RESIZE_INC) > 0 {
+ Some((width_inc, height_inc))
+ } else {
+ None
+ },
+ base_size: if (flags & Self::PROGRAM_BASE_SIZE) > 0 {
+ Some((base_width, base_height))
+ } else if (flags & Self::PROGRAM_MIN_SIZE) > 0 {
+ Some((min_width, min_height))
+ } else {
+ None
+ },
+ win_gravity: if (flags & Self::PROGRAM_WIN_GRAVITY) > 0 {
+ match win_gravity {
+ 2 => Gravity::North,
+ 3 => Gravity::NorthEast,
+ 4 => Gravity::West,
+ 5 => Gravity::Center,
+ 6 => Gravity::East,
+ 7 => Gravity::SouthWest,
+ 8 => Gravity::South,
+ 9 => Gravity::SouthEast,
+ _ => Gravity::NorthWest,
+ }
+ } else {
+ Gravity::NorthWest
+ },
+ })
+ }
+}
+
/// Gets the `WM_TRANSIENT_FOR` hint set on a window
pub fn transient_for(conn: &Connection, window: Window) -> Option<Window> {
let hints = conn