@@ -0,0 +1,55 @@ |
| | 1 | +use std::sync::Arc; |
| | 2 | + |
| | 3 | +use x11rb::protocol::xproto::{Atom, AtomEnum, ConnectionExt, Window}; |
| | 4 | +use x11rb::rust_connection::RustConnection; |
| | 5 | + |
| | 6 | +/// Get the WM_CLASS property of a window |
| | 7 | +/// Returns (instance, class) if available |
| | 8 | +pub fn get_wm_class(conn: &Arc<RustConnection>, window: Window) -> Option<(String, String)> { |
| | 9 | + if window == 0 { |
| | 10 | + return None; |
| | 11 | + } |
| | 12 | + |
| | 13 | + let wm_class_atom: Atom = AtomEnum::WM_CLASS.into(); |
| | 14 | + let string_atom: Atom = AtomEnum::STRING.into(); |
| | 15 | + |
| | 16 | + let reply = conn |
| | 17 | + .get_property(false, window, wm_class_atom, string_atom, 0, 1024) |
| | 18 | + .ok()? |
| | 19 | + .reply() |
| | 20 | + .ok()?; |
| | 21 | + |
| | 22 | + if reply.value.is_empty() { |
| | 23 | + return None; |
| | 24 | + } |
| | 25 | + |
| | 26 | + // WM_CLASS contains two null-terminated strings: instance and class |
| | 27 | + let value = &reply.value; |
| | 28 | + let mut parts = value.split(|&b| b == 0).filter(|s| !s.is_empty()); |
| | 29 | + |
| | 30 | + let instance = parts |
| | 31 | + .next() |
| | 32 | + .map(|s| String::from_utf8_lossy(s).into_owned()) |
| | 33 | + .unwrap_or_default(); |
| | 34 | + |
| | 35 | + let class = parts |
| | 36 | + .next() |
| | 37 | + .map(|s| String::from_utf8_lossy(s).into_owned()) |
| | 38 | + .unwrap_or_default(); |
| | 39 | + |
| | 40 | + if class.is_empty() && instance.is_empty() { |
| | 41 | + None |
| | 42 | + } else { |
| | 43 | + Some((instance, class)) |
| | 44 | + } |
| | 45 | +} |
| | 46 | + |
| | 47 | +/// Get the window class name (the second part of WM_CLASS) |
| | 48 | +pub fn get_window_class(conn: &Arc<RustConnection>, window: Window) -> Option<String> { |
| | 49 | + get_wm_class(conn, window).map(|(_, class)| class) |
| | 50 | +} |
| | 51 | + |
| | 52 | +/// Get the window instance name (the first part of WM_CLASS) |
| | 53 | +pub fn get_window_instance(conn: &Arc<RustConnection>, window: Window) -> Option<String> { |
| | 54 | + get_wm_class(conn, window).map(|(instance, _)| instance) |
| | 55 | +} |