diff --git a/src/clients.rs b/src/clients.rs index d2a987f..6f425f7 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -1,7 +1,7 @@ use std::{borrow::Borrow, cell::RefCell, collections::HashMap, rc::Rc}; use std::{ hash::{Hash, Hasher}, - rc::Weak, + num::NonZeroI32, }; use x11::xlib::Window; @@ -89,343 +89,313 @@ mod tests { use super::*; #[test] - fn client_lists_test() {} + fn client_lists_test() { + let mut clients = ClientState::default(); + + clients.insert(Client { + window: 1, + size: (1, 1), + position: (1, 1), + floating: false, + }); + + clients.insert(Client { + window: 2, + size: (1, 1), + position: (1, 1), + floating: false, + }); + + clients.stack_unstacked(); + clients.refresh_virtual_screen(); + clients.arange_virtual_screen(600, 400); + + println!("{:#?}", clients); + + clients.remove(&1u64); + + clients.stack_unstacked(); + clients.refresh_virtual_screen(); + clients.arange_virtual_screen(600, 400); + + println!("{:#?}", clients); + + clients.virtual_screens.rotate_right(1); + + clients.insert(Client { + window: 3, + size: (1, 1), + position: (1, 1), + floating: false, + }); + + clients.stack_unstacked(); + clients.refresh_virtual_screen(); + clients.arange_virtual_screen(600, 400); + + println!("{:#?}", clients); + + clients.toggle_floating(&2u64); + + clients.virtual_screens.rotate_left(1); + + clients.stack_unstacked(); + clients.refresh_virtual_screen(); + clients.arange_virtual_screen(600, 400); + + println!("{:#?}", clients); + } } -mod no_refcell { - use std::{collections::VecDeque, iter::repeat}; +use std::{collections::VecDeque, iter::repeat}; - use super::*; +type Clients = HashMap; +type ClientRef = u64; +type ClientRefs = Vec; - type ClientsWrapped = Rc>; - type Clients = HashMap; - type ClientRef = u64; - type ClientRefs = Vec; +#[derive(Debug, Clone)] +struct ClientState { + clients: Clients, + virtual_screens: VecDeque, +} - struct ClientState { - clients: Clients, - virtual_screens: VecDeque, +#[derive(Debug, Clone)] +struct VirtualScreen { + master: ClientRefs, + aux: ClientRefs, + focused: Option, +} + +impl Default for ClientState { + fn default() -> Self { + let mut vss = VecDeque::::new(); + vss.resize_with(10, Default::default); + + Self { + clients: Default::default(), + virtual_screens: vss, + } + } +} + +impl ClientState { + fn insert(&mut self, client: Client) { + let key = client.key(); + + self.clients.insert(key, client); } - struct VirtualScreen { - master: ClientRefs, - aux: ClientRefs, - focused: Option, + fn remove(&mut self, key: &K) + where + K: ClientKey, + { + self.virtual_screens + .iter_mut() + .for_each(|vs| vs.remove(key)); + + self.clients.remove(&key.key()); } - impl ClientState { - fn insert(&mut self, client: Client) { - let key = client.key(); + fn get(&self, key: &K) -> Option<&Client> + where + K: ClientKey, + { + self.clients.get(&key.key()) + } - self.clients.insert(key, client); + fn get_mut(&mut self, key: &K) -> Option<&mut Client> + where + K: ClientKey, + { + self.clients.get_mut(&key.key()) + } + + fn toggle_floating(&mut self, key: &K) -> Option + where + K: ClientKey, + { + match self.get_mut(key) { + Some(client) => { + client.floating = !client.floating; + Some(client.floating) + } + None => None, } + } - fn get(&self, key: &K) -> Option<&Client> - where - K: ClientKey, - { - self.clients.get(&key.key()) - } + fn get_virtualscreen_for_client(&self, key: &K) -> Option<&VirtualScreen> + where + K: ClientKey, + { + self.virtual_screens + .iter() + .find_map(|vs| if vs.contains(key) { Some(vs) } else { None }) + } - fn get_mut(&mut self, key: &K) -> Option<&mut Client> - where - K: ClientKey, - { - self.clients.get_mut(&key.key()) - } - - fn toggle_floating(&mut self, key: &K) -> Option - where - K: ClientKey, - { - match self.get_mut(key) { - Some(client) => { - client.floating = !client.floating; - Some(client.floating) + fn get_mut_virtualscreen_for_client(&mut self, key: &K) -> Option<&mut VirtualScreen> + where + K: ClientKey, + { + self.virtual_screens.iter_mut().find_map( + |vs| { + if vs.contains(key) { + Some(vs) + } else { + None + } + }, + ) + } + + /// focuses client `key` on current virtual screen + fn focus_client(&mut self, key: &K) + where + K: ClientKey, + { + match self.virtual_screens.front_mut() { + Some(vs) => vs.focus(key), + None => {} + } + } + + fn stack_unstacked(&mut self) { + let unstacked = self + .clients + .iter() + .filter(|&(key, client)| { + !client.floating && self.get_virtualscreen_for_client(key).is_none() + }) + .map(|(key, _)| key) + .collect::>(); + + if let Some(vs) = self.virtual_screens.front_mut() { + vs.aux.extend(unstacked.into_iter()) + } + } + + fn switch_stack_for_client(&mut self, key: &K) + where + K: ClientKey, + { + if let Some(vs) = self.get_mut_virtualscreen_for_client(key) { + match vs.master.iter().position(|&key| key == key.key()) { + Some(index) => { + vs.aux.extend(vs.master.drain(index..=index)); + } + None => { + let index = vs.aux.iter().position(|&key| key == key.key()).unwrap(); + vs.master.extend(vs.aux.drain(index..=index)); } - None => None, } } + } - fn get_virtualscreen_for_client(&self, key: &K) -> Option<&VirtualScreen> - where - K: ClientKey, - { - self.virtual_screens.iter().find_map( - |vs| { - if vs.contains(key) { - Some(vs) - } else { - None - } - }, - ) - } + fn refresh_virtual_screen(&mut self) { + let clients = &self.clients; - fn get_mut_virtualscreen_for_client(&mut self, key: &K) -> Option<&mut VirtualScreen> - where - K: ClientKey, - { - self.virtual_screens.iter_mut().find_map( - |vs| { - if vs.contains(key) { - Some(vs) - } else { - None - } - }, - ) - } + if let Some(vs) = self.virtual_screens.front_mut() { + vs.master.retain(|key| match clients.get(key) { + Some(client) => !client.floating, + None => false, + }); + vs.aux.retain(|key| match clients.get(key) { + Some(client) => !client.floating, + None => false, + }); - /// focuses client `key` on current virtual screen - fn focus_client(&mut self, key: &K) - where - K: ClientKey, - { - match self.virtual_screens.front_mut() { - Some(vs) => vs.focus(key), - None => {} + // if master is empty but aux has at least one client, drain from aux to master + if vs.master.is_empty() && !vs.aux.is_empty() { + vs.master.extend(vs.aux.drain(..1)); } } + } - fn stack_unstacked(&mut self) { - let unstacked = self - .clients + /** + resizes and moves clients on the current virtual screen with `width` and `height` as + screen width and screen height + */ + fn arange_virtual_screen(&mut self, width: i32, height: i32) { + // should be fine to unwrap since we will always have at least 1 virtual screen + + if let Some(vs) = self.virtual_screens.front_mut() { + // if aux is empty -> width : width / 2 + let width = width / (1 + i32::from(!vs.aux.is_empty() && !vs.master.is_empty())); + + // make sure we dont devide by 0 + let master_height = height + / match NonZeroI32::new(vs.master.len() as i32) { + Some(i) => i.get(), + None => 1, + }; + + let aux_height = height + / match NonZeroI32::new(vs.aux.len() as i32) { + Some(i) => i.get(), + None => 1, + }; + + // chaining master and aux together with `Zip`s for height and x reduces duplicate code + for ((i, key), (height, x)) in vs + .master .iter() - .filter(|&(key, client)| { - !client.floating && self.get_virtualscreen_for_client(key).is_some() - }) - .map(|(key, _)| key) - .collect::>(); + .enumerate() + // add repeating height for each window and x pos for each window + .zip(repeat(master_height).zip(repeat(0i32))) + .chain( + vs.aux + .iter() + .enumerate() + .zip(repeat(aux_height).zip(repeat(width))), + ) + { + let size = (width, height); + let position = (x, height * i as i32); - match self.virtual_screens.front_mut() { - Some(vs) => vs.aux.extend(unstacked.into_iter()), - None => {} - } - } - - fn switch_stack_for_client(&mut self, key: &K) - where - K: ClientKey, - { - if let Some(vs) = self.get_mut_virtualscreen_for_client(key) { - match vs.master.iter().position(|&key| key == key.key()) { - Some(index) => { - vs.aux.extend(vs.master.drain(index..=index)); - } - None => { - let index = vs.aux.iter().position(|&key| key == key.key()).unwrap(); - vs.master.extend(vs.aux.drain(index..=index)); - } + if let Some(client) = self.clients.get_mut(key) { + *client = Client { + size, + position, + ..*client + }; } } } - - fn refresh_virtual_screen(&mut self) { - let clients = &self.clients; - - if let Some(vs) = self.virtual_screens.front_mut() { - vs.master.retain(|key| match clients.get(key) { - Some(client) => !client.floating, - None => false, - }); - vs.aux.retain(|key| match clients.get(key) { - Some(client) => !client.floating, - None => false, - }); - - // if master is empty but aux has at least one client, drain from aux to master - if vs.master.is_empty() && !vs.aux.is_empty() { - vs.master.extend(vs.aux.drain(..1)); - } - } - } - - /** - resizes and moves clients on the current virtual screen with `width` and `height` as - screen width and screen height - */ - fn arange_virtual_screen(&mut self, width: i32, height: i32) { - // should be fine to unwrap since we will always have at least 1 virtual screen - - if let Some(vs) = self.virtual_screens.front_mut() { - // if aux is empty -> width : width / 2 - let width = width / 1 + i32::from(!vs.aux.is_empty()); - - // chaining master and aux together with `Zip`s for height and x reduces duplicate code - for ((i, key), (height, x)) in vs - .master - .iter() - .enumerate() - // add repeating height for each window and x pos for each window - .zip(repeat(height / vs.master.len() as i32).zip(repeat(0i32))) - .chain( - vs.aux - .iter() - .enumerate() - .zip(repeat(height / vs.aux.len() as i32).zip(repeat(width))), - ) - { - let size = (width, height); - let position = (x, height * i as i32); - - if let Some(client) = self.clients.get_mut(key) { - *client = Client { - size, - position, - ..*client - }; - } - } - } - } - - // Should have xlib send those changes back to the x server after this function } - impl VirtualScreen { - fn contains(&self, key: &K) -> bool - where - K: ClientKey, - { - self.master.contains(&key.key()) || self.aux.contains(&key.key()) - } + // Should have xlib send those changes back to the x server after this function +} - fn focus(&mut self, key: &K) - where - K: ClientKey, - { - self.focused = Some(key.key()); +impl Default for VirtualScreen { + fn default() -> Self { + Self { + master: Default::default(), + aux: Default::default(), + focused: None, } } } -/* -mod refcell { - use std::collections::VecDeque; - - use super::*; - - type ClientsWrapped = Rc>; - type Clients = HashMap>, BuildIdentityHasher>; - type ClientRef = Weak>; - type ClientRefs = Vec; - - struct ClientState { - clients: Clients, - virtual_screens: VecDeque, +impl VirtualScreen { + fn contains(&self, key: &K) -> bool + where + K: ClientKey, + { + self.master.contains(&key.key()) || self.aux.contains(&key.key()) } - struct VirtualScreen { - master: ClientRefs, - aux: ClientRefs, - focused: Option, + fn remove(&mut self, key: &K) + where + K: ClientKey, + { + let key = key.key(); + self.master.retain(|k| *k != key); + self.aux.retain(|k| *k != key); } - impl ClientState { - fn insert(&mut self, client: Client) { - let key = client.key(); - - self.clients.insert(key, Rc::new(RefCell::new(client))); - } - - fn get(&self, key: &K) -> Option<&Rc>> - where - K: ClientKey, - { - self.clients.get(&key.key()) - } - - fn toggle_floating(&mut self, key: &K) -> Option - where - K: ClientKey, - { - match self.get(key) { - Some(client) => { - let client = client.borrow_mut(); - client.floating = !client.floating; - - Some(client.floating) - } - None => None, - } - } - - fn get_virtualscreen_for_client(&self, key: &K) -> Option<&VirtualScreen> - where - K: ClientKey, - { - self.virtual_screens.iter().find_map( - |vs| { - if vs.contains(key) { - Some(vs) - } else { - None - } - }, - ) - } - - fn get_mut_virtualscreen_for_client(&mut self, key: &K) -> Option<&mut VirtualScreen> - where - K: ClientKey, - { - self.virtual_screens.iter_mut().find_map( - |vs| { - if vs.contains(key) { - Some(vs) - } else { - None - } - }, - ) - } - - /// focuses client `key` on current virtual screen - fn focus_client(&mut self, key: &K) - where - K: ClientKey, - { - match self.virtual_screens.front_mut() { - Some(vs) => vs.focus(key), - None => {} - } - } - - fn stack_unstacked(&mut self) { - let unstacked = self - .clients - .iter() - .filter(|&(key, client)| { - !client.as_ref().borrow().floating - && self.get_virtualscreen_for_client(key).is_some() - }) - .map(|(key, _)| key) - .collect::>(); - - match self.virtual_screens.front_mut() { - Some(vs) => vs.aux.extend(unstacked.into_iter()), - None => {} - } - } - - fn arrange(&mut self) {} - } - - impl VirtualScreen { - fn contains(&self, key: &K) -> bool - where - K: ClientKey, - { - self.master.contains(&key.key()) || self.aux.contains(&key.key()) - } - - fn focus(&mut self, key: &K) - where - K: ClientKey, - { - self.focused = Some(key.key()); - } + fn focus(&mut self, key: &K) + where + K: ClientKey, + { + self.focused = Some(key.key()); } } -*/