diff options
author | tcmal <me@aria.rip> | 2024-06-03 17:06:15 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-06-03 17:06:15 +0100 |
commit | dc8094726026c5b56b5600f95da8475561b1073d (patch) | |
tree | b850c5076151feb6d3610a4b66087423cd3882e6 /src/clients.rs |
initial commit: basic xorg initialisation
Diffstat (limited to 'src/clients.rs')
-rw-r--r-- | src/clients.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/clients.rs b/src/clients.rs new file mode 100644 index 0000000..70a44fa --- /dev/null +++ b/src/clients.rs @@ -0,0 +1,104 @@ +use xcb::{ + xinerama::{self, ScreenInfo}, + Extension, +}; + +use crate::{Error, Result, WM}; + +#[derive(Debug, Default)] +pub struct ClientList(Vec<MonitorInfo>); + +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<Client>, + 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(()) + } +} |