use xcb::{ xinerama::{self, ScreenInfo}, Extension, }; use crate::{Error, Result, WM}; #[derive(Debug, Default)] pub struct ClientList(Vec); impl ClientList { /// Set the new amount of screens, moving clients away if necessary pub fn truncate_screens(&mut self, new_size: usize) { // hack: double borrow stuff let mut moved_clients = vec![]; for old in self.0.drain(new_size - self.0.len()..self.0.len()) { moved_clients.extend(old.clients.into_iter()); } self.0[0].clients.extend(moved_clients.into_iter()); } pub fn set_screen_info(&mut self, i: usize, info: ScreenInfo) { while i >= self.0.len() { self.0.push(MonitorInfo::default()) } self.0[i].screen_info = info; } pub fn len(&self) -> usize { self.0.len() } } #[derive(Debug)] pub struct MonitorInfo { clients: Vec, screen_info: ScreenInfo, } impl Default for MonitorInfo { fn default() -> Self { Self { clients: vec![], screen_info: ScreenInfo { x_org: 0, y_org: 0, width: 0, height: 0, }, } } } #[derive(Debug)] pub struct Client {} impl WM<'_> { /// Update the client list's recorded monitors and monitor sizes pub(crate) fn update_geometry(&mut self) -> Result<()> { if self .conn .active_extensions() .any(|e| e == Extension::Xinerama) { let reply = self .conn .wait_for_reply(self.conn.send_request(&xinerama::QueryScreens {}))?; // Monitor removed, move its clients away if reply.screen_info().len() > self.clients.len() { self.clients.truncate_screens(reply.screen_info().len()); } // Update screen info & add new client lists if needed for (i, monitor) in reply.screen_info().iter().enumerate() { self.clients.set_screen_info(i, monitor.clone()); } } else { // Only one screen if self.clients.len() > 1 { self.clients.truncate_screens(1); } // TODO: it looks like this won't actually update when the screen size changes? let setup = self.conn.get_setup(); let screen = setup .roots() .nth(self.screen_num as usize) .ok_or(Error::NoSuchScreen)?; self.clients.set_screen_info( 0, ScreenInfo { x_org: 0, y_org: 0, width: screen.width_in_pixels(), height: screen.height_in_pixels(), }, ); } Ok(()) } }