use xcb::xinerama::ScreenInfo; use super::{Client, Tag}; /// Info stored for each monitor #[derive(Debug)] pub struct MonitorInfo { /// How clients should be filtered by tag pub focused_tag: TagFocus, /// The previously focused tag, for going back-and-forth pub last_focused_tag: TagFocus, /// The monitor's geometry pub screen_info: MonitorGeometry, } /// How clients are currently being filtered by tag #[derive(Debug, Clone, Copy)] pub enum TagFocus { /// Only show clients with the given tag Tag(Tag), /// Show all clients All, } impl TagFocus { /// Check if a client with the given tag should be displayed when using this filter pub const fn matches(&self, tag: Tag) -> bool { match self { Self::Tag(x) => *x == tag, Self::All => true, } } /// Get the tag that new clients should be assigned when using this filter pub const fn create_tag(&self) -> Tag { match self { Self::Tag(x) => *x, Self::All => 1, } } } impl MonitorInfo { pub fn iter_visible_tiling<'a>( &'a self, i: impl IntoIterator, ) -> impl Iterator { i.into_iter() .filter(|c| self.focused_tag.matches(c.tag)) .filter(|c| c.tiled()) } } impl Default for MonitorInfo { fn default() -> Self { Self { screen_info: MonitorGeometry { x_org: 0, y_org: 0, width: 0, height: 0, }, focused_tag: TagFocus::Tag(1), last_focused_tag: TagFocus::Tag(1), } } } /// Info on the monitor's geometry. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MonitorGeometry { pub x_org: i16, pub y_org: i16, pub width: u16, pub height: u16, } impl MonitorGeometry { #[allow(clippy::cast_possible_wrap)] pub(crate) fn contains(self, x: i16, y: i16) -> bool { (self.x_org..self.x_org + self.width as i16).contains(&x) && (self.y_org..self.y_org + self.height as i16).contains(&y) } } impl From for MonitorGeometry { fn from(value: ScreenInfo) -> Self { Self { x_org: value.x_org, y_org: value.y_org, width: value.width, height: value.height, } } }