summaryrefslogtreecommitdiff
path: root/src/clients.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/clients.rs')
-rw-r--r--src/clients.rs104
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(())
+ }
+}