diff options
-rw-r--r-- | src/clients/hints.rs | 94 |
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 |