diff --git a/src/backends/mod.rs b/src/backends/mod.rs index 73f4ef0..5b1d5a6 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -4,3 +4,18 @@ pub mod window_event; pub mod xlib; pub use traits::*; + +pub mod structs { + + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] + pub enum WindowType { + Splash, + Dialog, + Normal, + Utility, + Menu, + Toolbar, + Dock, + Desktop, + } +} diff --git a/src/backends/traits.rs b/src/backends/traits.rs index 0d6104b..7928a57 100644 --- a/src/backends/traits.rs +++ b/src/backends/traits.rs @@ -1,4 +1,7 @@ -use super::window_event::{self, KeyOrMouseBind}; +use super::{ + structs::WindowType, + window_event::{self, KeyOrMouseBind}, +}; use crate::util::{Point, Size}; pub trait WindowServerBackend { @@ -32,6 +35,7 @@ pub trait WindowServerBackend { fn screen_size(&self) -> Size; fn get_window_size(&self, window: Self::Window) -> Option>; fn get_window_name(&self, window: Self::Window) -> Option; + fn get_window_type(&self, window: Self::Window) -> WindowType; fn grab_cursor(&self); fn ungrab_cursor(&self); diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 92ca57d..b559a41 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -22,6 +22,7 @@ use self::{ use super::{ keycodes::VirtualKeyCode, + structs::WindowType, window_event::{ ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, FullscreenEvent, FullscreenState, KeyEvent, KeyOrMouseBind, KeyState, MapEvent, @@ -291,6 +292,14 @@ pub mod ewmh { .map(|atoms| Self { inner: atoms }) } + pub fn reverse_lookup(&self, atom: Atom) -> Option { + self.inner + .iter() + .position(|a| *a == atom) + .map(|position| EWMHAtom::from_repr(position)) + .flatten() + } + pub fn set_supported_atoms>(&self, con: C) { let supported_atoms = [ self[EWMHAtom::NetActiveWindow], @@ -1505,6 +1514,44 @@ impl WindowServerBackend for XLib { .get_text_property(window, self.atoms[ICCCMAtom::WmName]) }) } + + fn get_window_type( + &self, + window: Self::Window, + ) -> super::structs::WindowType { + match self + .get_atom_property( + window, + self.ewmh_atoms[EWMHAtom::NetWmWindowType], + ) + .and_then(|atom| self.ewmh_atoms.reverse_lookup(*atom)) + .and_then(|atom| WindowType::try_from(atom).ok()) + { + Some(window_type) => window_type, + None => match self.get_parent_window(window) { + Some(_) => WindowType::Dialog, + None => WindowType::Normal, + }, + } + } +} + +impl TryFrom for WindowType { + type Error = (); + + fn try_from(value: EWMHAtom) -> Result { + match value { + EWMHAtom::NetWmWindowTypeDesktop => Ok(Self::Desktop), + EWMHAtom::NetWmWindowTypeDock => Ok(Self::Dock), + EWMHAtom::NetWmWindowTypeUtility => Ok(Self::Utility), + EWMHAtom::NetWmWindowTypeMenu => Ok(Self::Menu), + EWMHAtom::NetWmWindowTypeToolbar => Ok(Self::Toolbar), + EWMHAtom::NetWmWindowTypeSplash => Ok(Self::Splash), + EWMHAtom::NetWmWindowTypeDialog => Ok(Self::Dialog), + EWMHAtom::NetWmWindowTypeNormal => Ok(Self::Normal), + _ => Err(()), + } + } } #[allow(dead_code)]