changed rustfmt to max 80 chars per line, added better ways to switch virtual screens
This commit is contained in:
		
							parent
							
								
									ef63004242
								
							
						
					
					
						commit
						5b37a86a58
					
				|  | @ -1,2 +1,3 @@ | ||||||
| imports_granularity = "Crate" | imports_granularity = "Crate" | ||||||
| wrap_comments = true | wrap_comments = true | ||||||
|  | max_width = 80 | ||||||
|  | @ -32,7 +32,11 @@ mod client { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     impl Client { |     impl Client { | ||||||
|         pub fn new(window: Window, size: (i32, i32), position: (i32, i32)) -> Self { |         pub fn new( | ||||||
|  |             window: Window, | ||||||
|  |             size: (i32, i32), | ||||||
|  |             position: (i32, i32), | ||||||
|  |         ) -> Self { | ||||||
|             Self { |             Self { | ||||||
|                 window, |                 window, | ||||||
|                 size, |                 size, | ||||||
|  | @ -41,7 +45,11 @@ mod client { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pub fn new_transient(window: Window, size: (i32, i32), transient: Window) -> Self { |         pub fn new_transient( | ||||||
|  |             window: Window, | ||||||
|  |             size: (i32, i32), | ||||||
|  |             transient: Window, | ||||||
|  |         ) -> Self { | ||||||
|             Self { |             Self { | ||||||
|                 window, |                 window, | ||||||
|                 size, |                 size, | ||||||
|  | @ -300,13 +308,17 @@ impl ClientState { | ||||||
|     pub fn insert(&mut self, mut client: Client) -> Option<&Client> { |     pub fn insert(&mut self, mut client: Client) -> Option<&Client> { | ||||||
|         let key = client.key(); |         let key = client.key(); | ||||||
| 
 | 
 | ||||||
|         if client.is_transient() && self.contains(&client.transient_for.unwrap()) { |         if client.is_transient() | ||||||
|  |             && self.contains(&client.transient_for.unwrap()) | ||||||
|  |         { | ||||||
|             let transient = self.get(&client.transient_for.unwrap()).unwrap(); |             let transient = self.get(&client.transient_for.unwrap()).unwrap(); | ||||||
| 
 | 
 | ||||||
|             client.position = { |             client.position = { | ||||||
|                 ( |                 ( | ||||||
|                     transient.position.0 + (transient.size.0 - client.size.0) / 2, |                     transient.position.0 | ||||||
|                     transient.position.1 + (transient.size.1 - client.size.1) / 2, |                         + (transient.size.0 - client.size.0) / 2, | ||||||
|  |                     transient.position.1 | ||||||
|  |                         + (transient.size.1 - client.size.1) / 2, | ||||||
|                 ) |                 ) | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|  | @ -347,7 +359,8 @@ impl ClientState { | ||||||
|     { |     { | ||||||
|         let key = key.key(); |         let key = key.key(); | ||||||
| 
 | 
 | ||||||
|         self.clients.contains_key(&key) || self.floating_clients.contains_key(&key) |         self.clients.contains_key(&key) | ||||||
|  |             || self.floating_clients.contains_key(&key) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn iter_floating(&self) -> impl Iterator<Item = (&u64, &Client)> { |     pub fn iter_floating(&self) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|  | @ -378,6 +391,18 @@ impl ClientState { | ||||||
|             .filter(move |&(k, _)| self.current_vs().contains(k)) |             .filter(move |&(k, _)| self.current_vs().contains(k)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn iter_master_stack(&self) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|  |         self.clients | ||||||
|  |             .iter() | ||||||
|  |             .filter(move |&(k, _)| self.current_vs().is_in_master(k)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn iter_aux_stack(&self) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|  |         self.clients | ||||||
|  |             .iter() | ||||||
|  |             .filter(move |&(k, _)| self.current_vs().is_in_aux(k)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Returns reference to the current `VirtualScreen`.
 |     /// Returns reference to the current `VirtualScreen`.
 | ||||||
|     fn current_vs(&self) -> &VirtualScreen { |     fn current_vs(&self) -> &VirtualScreen { | ||||||
|         // there is always at least one (1) virtual screen.
 |         // there is always at least one (1) virtual screen.
 | ||||||
|  | @ -510,31 +535,39 @@ impl ClientState { | ||||||
|     where |     where | ||||||
|         K: ClientKey, |         K: ClientKey, | ||||||
|     { |     { | ||||||
|         self.virtual_screens |         self.virtual_screens.iter().find_map(|vs| { | ||||||
|             .iter() |  | ||||||
|             .find_map(|vs| if vs.contains(key) { Some(vs) } else { None }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn get_mut_virtualscreen_for_client<K>(&mut self, key: &K) -> Option<&mut VirtualScreen> |  | ||||||
|     where |  | ||||||
|         K: ClientKey, |  | ||||||
|     { |  | ||||||
|         self.virtual_screens.iter_mut().find_map( |  | ||||||
|             |vs| { |  | ||||||
|             if vs.contains(key) { |             if vs.contains(key) { | ||||||
|                 Some(vs) |                 Some(vs) | ||||||
|             } else { |             } else { | ||||||
|                 None |                 None | ||||||
|             } |             } | ||||||
|             }, |         }) | ||||||
|         ) |     } | ||||||
|  | 
 | ||||||
|  |     fn get_mut_virtualscreen_for_client<K>( | ||||||
|  |         &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` if it contains `key` and returns a reference to the  newly and the previously |     focuses client `key` if it contains `key` and returns a reference to the  newly and the previously | ||||||
|     focused clients if any. |     focused clients if any. | ||||||
|     */ |     */ | ||||||
|     pub fn focus_client<K>(&mut self, key: &K) -> (ClientEntry<&Client>, ClientEntry<&Client>) |     pub fn focus_client<K>( | ||||||
|  |         &mut self, | ||||||
|  |         key: &K, | ||||||
|  |     ) -> (ClientEntry<&Client>, ClientEntry<&Client>) | ||||||
|     where |     where | ||||||
|         K: ClientKey, |         K: ClientKey, | ||||||
|     { |     { | ||||||
|  | @ -613,7 +646,12 @@ impl ClientState { | ||||||
|     screen width and screen height. |     screen width and screen height. | ||||||
|     Optionally adds a gap between windows `gap.unwrap_or(0)` pixels wide. |     Optionally adds a gap between windows `gap.unwrap_or(0)` pixels wide. | ||||||
|     */ |     */ | ||||||
|     pub fn arrange_virtual_screen(&mut self, width: i32, height: i32, gap: Option<i32>) { |     pub fn arrange_virtual_screen( | ||||||
|  |         &mut self, | ||||||
|  |         width: i32, | ||||||
|  |         height: i32, | ||||||
|  |         gap: Option<i32>, | ||||||
|  |     ) { | ||||||
|         let gap = gap.unwrap_or(0); |         let gap = gap.unwrap_or(0); | ||||||
| 
 | 
 | ||||||
|         // should be fine to unwrap since we will always have at least 1 virtual screen
 |         // should be fine to unwrap since we will always have at least 1 virtual screen
 | ||||||
|  | @ -687,6 +725,20 @@ impl VirtualScreen { | ||||||
|         self.master.contains(&key.key()) || self.aux.contains(&key.key()) |         self.master.contains(&key.key()) || self.aux.contains(&key.key()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn is_in_master<K>(&self, key: &K) -> bool | ||||||
|  |     where | ||||||
|  |         K: ClientKey, | ||||||
|  |     { | ||||||
|  |         self.master.contains(&key.key()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn is_in_aux<K>(&self, key: &K) -> bool | ||||||
|  |     where | ||||||
|  |         K: ClientKey, | ||||||
|  |     { | ||||||
|  |         self.aux.contains(&key.key()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn insert<K>(&mut self, key: &K) |     fn insert<K>(&mut self, key: &K) | ||||||
|     where |     where | ||||||
|         K: ClientKey, |         K: ClientKey, | ||||||
|  | @ -716,7 +768,8 @@ impl VirtualScreen { | ||||||
|                 self.aux.extend(self.master.drain(index..=index)); |                 self.aux.extend(self.master.drain(index..=index)); | ||||||
|             } |             } | ||||||
|             None => { |             None => { | ||||||
|                 let index = self.aux.iter().position(|&k| k == key.key()).unwrap(); |                 let index = | ||||||
|  |                     self.aux.iter().position(|&k| k == key.key()).unwrap(); | ||||||
|                 self.master.extend(self.aux.drain(index..=index)); |                 self.master.extend(self.aux.drain(index..=index)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ use log4rs::{ | ||||||
|     encode::pattern::PatternEncoder, |     encode::pattern::PatternEncoder, | ||||||
|     Config, |     Config, | ||||||
| }; | }; | ||||||
|  | use state::WMConfig; | ||||||
| 
 | 
 | ||||||
| mod clients; | mod clients; | ||||||
| mod state; | mod state; | ||||||
|  | @ -44,7 +45,7 @@ fn main() { | ||||||
| 
 | 
 | ||||||
|     log_prologue(); |     log_prologue(); | ||||||
| 
 | 
 | ||||||
|     state::WindowManager::new().init().run(); |     state::WindowManager::new(WMConfig::default()).init().run(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn log_prologue() { | fn log_prologue() { | ||||||
|  |  | ||||||
							
								
								
									
										167
									
								
								src/state.rs
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								src/state.rs
									
									
									
									
									
								
							|  | @ -2,10 +2,14 @@ use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| use log::{error, info}; | use log::{error, info}; | ||||||
| 
 | 
 | ||||||
| use x11::xlib::{self, ShiftMask, Window, XButtonEvent, XEvent, XKeyEvent, XMotionEvent}; | use x11::xlib::{ | ||||||
|  |     self, Mod4Mask, ShiftMask, Window, XButtonEvent, XEvent, XKeyEvent, | ||||||
|  |     XMotionEvent, | ||||||
|  | }; | ||||||
| use xlib::{ | use xlib::{ | ||||||
|     ButtonPressMask, ButtonReleaseMask, Mod1Mask, PointerMotionMask, XConfigureRequestEvent, |     ButtonPressMask, ButtonReleaseMask, PointerMotionMask, | ||||||
|     XCrossingEvent, XDestroyWindowEvent, XMapRequestEvent, XUnmapEvent, |     XConfigureRequestEvent, XCrossingEvent, XDestroyWindowEvent, | ||||||
|  |     XMapRequestEvent, XUnmapEvent, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|  | @ -14,15 +18,28 @@ use crate::{ | ||||||
|     xlib::XLib, |     xlib::XLib, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  | Contains static config data for the window manager, the sort of stuff you might want to | ||||||
|  | be able to configure in a config file. | ||||||
|  | */ | ||||||
|  | pub struct WMConfig { | ||||||
|  |     num_virtualscreens: usize, | ||||||
|  |     mod_key: u32, | ||||||
|  |     gap: Option<i32>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct WindowManager { | pub struct WindowManager { | ||||||
|     clients: ClientState, |     clients: ClientState, | ||||||
|     move_window: Option<MoveWindow>, |     move_window: Option<MoveWindow>, | ||||||
|     resize_window: Option<MoveWindow>, |     resize_window: Option<MoveWindow>, | ||||||
|     keybinds: Vec<KeyBinding>, |     keybinds: Vec<KeyBinding>, | ||||||
|     xlib: XLib, |     xlib: XLib, | ||||||
|  | 
 | ||||||
|  |     last_rotation: Option<Direction>, | ||||||
|  |     config: WMConfig, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone, Copy)] | ||||||
| pub enum Direction { | pub enum Direction { | ||||||
|     Left, |     Left, | ||||||
|     Right, |     Right, | ||||||
|  | @ -40,8 +57,9 @@ struct KeyBinding { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl WindowManager { | impl WindowManager { | ||||||
|     pub fn new() -> Self { |     pub fn new(config: WMConfig) -> Self { | ||||||
|         let clients = ClientState::with_virtualscreens(3); |         let clients = | ||||||
|  |             ClientState::with_virtualscreens(config.num_virtualscreens); | ||||||
|         let xlib = XLib::new(); |         let xlib = XLib::new(); | ||||||
| 
 | 
 | ||||||
|         Self { |         Self { | ||||||
|  | @ -50,28 +68,30 @@ impl WindowManager { | ||||||
|             resize_window: None, |             resize_window: None, | ||||||
|             keybinds: Vec::new(), |             keybinds: Vec::new(), | ||||||
|             xlib, |             xlib, | ||||||
|  |             last_rotation: None, | ||||||
|  |             config, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn init(mut self) -> Self { |     pub fn init(mut self) -> Self { | ||||||
|         self.xlib.add_global_keybind(KeyOrButton::button( |         self.xlib.add_global_keybind(KeyOrButton::button( | ||||||
|             1, |             1, | ||||||
|             Mod1Mask, |             self.config.mod_key, | ||||||
|             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, |             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | ||||||
|         )); |         )); | ||||||
|         self.xlib.add_global_keybind(KeyOrButton::button( |         self.xlib.add_global_keybind(KeyOrButton::button( | ||||||
|             2, |             2, | ||||||
|             Mod1Mask, |             self.config.mod_key, | ||||||
|             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, |             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | ||||||
|         )); |         )); | ||||||
|         self.xlib.add_global_keybind(KeyOrButton::button( |         self.xlib.add_global_keybind(KeyOrButton::button( | ||||||
|             3, |             3, | ||||||
|             Mod1Mask, |             self.config.mod_key, | ||||||
|             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, |             ButtonPressMask | ButtonReleaseMask | PointerMotionMask, | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("P", Mod1Mask), |             self.xlib.make_key("P", self.config.mod_key), | ||||||
|             |wm, _| { |             |wm, _| { | ||||||
|                 wm.spawn( |                 wm.spawn( | ||||||
|                     "dmenu_run", |                     "dmenu_run", | ||||||
|  | @ -94,37 +114,63 @@ impl WindowManager { | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("M", Mod1Mask), |             self.xlib.make_key("M", self.config.mod_key), | ||||||
|             Self::handle_switch_stack, |             Self::handle_switch_stack, | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("Q", Mod1Mask), |             self.xlib.make_key("Q", self.config.mod_key), | ||||||
|             Self::kill_client, |             Self::kill_client, | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("Q", Mod1Mask | ShiftMask), |             self.xlib.make_key("Q", self.config.mod_key | ShiftMask), | ||||||
|             |wm, _| wm.quit(), |             |wm, _| wm.quit(), | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("T", Mod1Mask), |             self.xlib.make_key("T", self.config.mod_key), | ||||||
|             |wm, _| wm.spawn("alacritty", &[]), |             |wm, _| wm.spawn("alacritty", &[]), | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("Return", Mod1Mask | ShiftMask), |             self.xlib | ||||||
|  |                 .make_key("Return", self.config.mod_key | ShiftMask), | ||||||
|             |wm, _| wm.spawn("alacritty", &[]), |             |wm, _| wm.spawn("alacritty", &[]), | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("Left", Mod1Mask), |             self.xlib.make_key("Left", self.config.mod_key), | ||||||
|             |wm, _| wm.rotate_virtual_screen(Direction::Left), |             |wm, _| wm.rotate_virtual_screen(Direction::Left), | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|         self.add_keybind(KeyBinding::new( |         self.add_keybind(KeyBinding::new( | ||||||
|             self.xlib.make_key("Right", Mod1Mask), |             self.xlib.make_key("Right", self.config.mod_key), | ||||||
|  |             |wm, _| wm.rotate_virtual_screen(Direction::Right), | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         self.add_keybind(KeyBinding::new( | ||||||
|  |             self.xlib.make_key("Tab", self.config.mod_key), | ||||||
|  |             |wm, _| wm.rotate_virtual_screen_back(), | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         self.add_keybind(KeyBinding::new( | ||||||
|  |             self.xlib.make_key("J", self.config.mod_key), | ||||||
|  |             |wm, _| wm.focus_master_stack(), | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         self.add_keybind(KeyBinding::new( | ||||||
|  |             self.xlib.make_key("K", self.config.mod_key), | ||||||
|  |             |wm, _| wm.focus_aux_stack(), | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         self.add_keybind(KeyBinding::new( | ||||||
|  |             self.xlib.make_key("J", self.config.mod_key | ShiftMask), | ||||||
|  |             |wm, _| wm.rotate_virtual_screen(Direction::Left), | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         self.add_keybind(KeyBinding::new( | ||||||
|  |             self.xlib.make_key("K", self.config.mod_key | ShiftMask), | ||||||
|             |wm, _| wm.rotate_virtual_screen(Direction::Right), |             |wm, _| wm.rotate_virtual_screen(Direction::Right), | ||||||
|         )); |         )); | ||||||
| 
 | 
 | ||||||
|  | @ -192,7 +238,9 @@ impl WindowManager { | ||||||
|             let event: &XButtonEvent = event.as_ref(); |             let event: &XButtonEvent = event.as_ref(); | ||||||
|             let clean_mask = self.xlib.get_clean_mask(); |             let clean_mask = self.xlib.get_clean_mask(); | ||||||
| 
 | 
 | ||||||
|             if event.button == 2 && event.state & clean_mask == Mod1Mask & clean_mask { |             if event.button == 2 | ||||||
|  |                 && event.state & clean_mask == self.config.mod_key & clean_mask | ||||||
|  |             { | ||||||
|                 if self.clients.contains(&event.subwindow) { |                 if self.clients.contains(&event.subwindow) { | ||||||
|                     info!("toggleing floating for {:?}", event.subwindow); |                     info!("toggleing floating for {:?}", event.subwindow); | ||||||
| 
 | 
 | ||||||
|  | @ -221,7 +269,8 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|                 if self.move_window.is_none() |                 if self.move_window.is_none() | ||||||
|                     && event.button == 1 |                     && event.button == 1 | ||||||
|                     && event.state & clean_mask == Mod1Mask & clean_mask |                     && event.state & clean_mask | ||||||
|  |                         == self.config.mod_key & clean_mask | ||||||
|                     && self.clients.contains(&event.subwindow) |                     && self.clients.contains(&event.subwindow) | ||||||
|                 { |                 { | ||||||
|                     // if client is tiled, set to floating
 |                     // if client is tiled, set to floating
 | ||||||
|  | @ -257,7 +306,9 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|                     move_window.cached_cursor_position = (event.x, event.y); |                     move_window.cached_cursor_position = (event.x, event.y); | ||||||
| 
 | 
 | ||||||
|                     if let Some(client) = self.clients.get_mut(&move_window.key).into_option() { |                     if let Some(client) = | ||||||
|  |                         self.clients.get_mut(&move_window.key).into_option() | ||||||
|  |                     { | ||||||
|                         let position = &mut client.position; |                         let position = &mut client.position; | ||||||
|                         position.0 += x; |                         position.0 += x; | ||||||
|                         position.1 += y; |                         position.1 += y; | ||||||
|  | @ -279,7 +330,8 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|                 if self.resize_window.is_none() |                 if self.resize_window.is_none() | ||||||
|                     && event.button == 3 |                     && event.button == 3 | ||||||
|                     && event.state & clean_mask == Mod1Mask & clean_mask |                     && event.state & clean_mask | ||||||
|  |                         == self.config.mod_key & clean_mask | ||||||
|                     && self.clients.contains(&event.subwindow) |                     && self.clients.contains(&event.subwindow) | ||||||
|                 { |                 { | ||||||
|                     // if client is tiled, set to floating
 |                     // if client is tiled, set to floating
 | ||||||
|  | @ -329,7 +381,9 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|                     resize_window.cached_cursor_position = (event.x, event.y); |                     resize_window.cached_cursor_position = (event.x, event.y); | ||||||
| 
 | 
 | ||||||
|                     if let Some(client) = self.clients.get_mut(&resize_window.key).into_option() { |                     if let Some(client) = | ||||||
|  |                         self.clients.get_mut(&resize_window.key).into_option() | ||||||
|  |                     { | ||||||
|                         let size = &mut client.size; |                         let size = &mut client.size; | ||||||
| 
 | 
 | ||||||
|                         size.0 = std::cmp::max(1, size.0 + x); |                         size.0 = std::cmp::max(1, size.0 + x); | ||||||
|  | @ -343,9 +397,17 @@ impl WindowManager { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn rotate_virtual_screen_back(&mut self) { | ||||||
|  |         if let Some(dir) = self.last_rotation { | ||||||
|  |             self.rotate_virtual_screen(!dir); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn rotate_virtual_screen(&mut self, dir: Direction) { |     fn rotate_virtual_screen(&mut self, dir: Direction) { | ||||||
|         info!("rotateing VS: {:?}", dir); |         info!("rotateing VS: {:?}", dir); | ||||||
| 
 | 
 | ||||||
|  |         self.last_rotation = Some(dir); | ||||||
|  | 
 | ||||||
|         match dir { |         match dir { | ||||||
|             Direction::Left => self.clients.rotate_left(), |             Direction::Left => self.clients.rotate_left(), | ||||||
|             Direction::Right => self.clients.rotate_right(), |             Direction::Right => self.clients.rotate_right(), | ||||||
|  | @ -354,13 +416,40 @@ impl WindowManager { | ||||||
|         self.arrange_clients(); |         self.arrange_clients(); | ||||||
| 
 | 
 | ||||||
|         // focus first client in all visible clients
 |         // focus first client in all visible clients
 | ||||||
|         let to_focus = self.clients.iter_visible().next().map(|(k, _)| k).cloned(); |         let to_focus = | ||||||
|  |             self.clients.iter_visible().next().map(|(k, _)| k).cloned(); | ||||||
| 
 | 
 | ||||||
|         if let Some(key) = to_focus { |         if let Some(key) = to_focus { | ||||||
|             self.focus_client(&key); |             self.focus_client(&key); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn focus_master_stack(&mut self) { | ||||||
|  |         let k = self | ||||||
|  |             .clients | ||||||
|  |             .iter_master_stack() | ||||||
|  |             .map(|(k, _)| k) | ||||||
|  |             .next() | ||||||
|  |             .cloned(); | ||||||
|  | 
 | ||||||
|  |         if let Some(k) = k { | ||||||
|  |             self.focus_client(&k); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn focus_aux_stack(&mut self) { | ||||||
|  |         let k = self | ||||||
|  |             .clients | ||||||
|  |             .iter_aux_stack() | ||||||
|  |             .map(|(k, _)| k) | ||||||
|  |             .next() | ||||||
|  |             .cloned(); | ||||||
|  | 
 | ||||||
|  |         if let Some(k) = k { | ||||||
|  |             self.focus_client(&k); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn hide_hidden_clients(&self) { |     fn hide_hidden_clients(&self) { | ||||||
|         self.clients |         self.clients | ||||||
|             .iter_hidden() |             .iter_hidden() | ||||||
|  | @ -379,14 +468,15 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|     fn arrange_clients(&mut self) { |     fn arrange_clients(&mut self) { | ||||||
|         let (width, height) = self.xlib.dimensions(); |         let (width, height) = self.xlib.dimensions(); | ||||||
|         self.clients.arrange_virtual_screen(width, height, Some(2)); |         self.clients | ||||||
| 
 |             .arrange_virtual_screen(width, height, self.config.gap); | ||||||
|         self.hide_hidden_clients(); |  | ||||||
| 
 | 
 | ||||||
|         self.clients |         self.clients | ||||||
|             .iter_visible() |             .iter_visible() | ||||||
|             .for_each(|(_, c)| self.xlib.move_resize_client(c)); |             .for_each(|(_, c)| self.xlib.move_resize_client(c)); | ||||||
| 
 | 
 | ||||||
|  |         self.hide_hidden_clients(); | ||||||
|  | 
 | ||||||
|         self.raise_floating_clients(); |         self.raise_floating_clients(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -410,7 +500,9 @@ impl WindowManager { | ||||||
| 
 | 
 | ||||||
|     fn new_client(&mut self, window: Window) { |     fn new_client(&mut self, window: Window) { | ||||||
|         info!("new client: {:?}", window); |         info!("new client: {:?}", window); | ||||||
|         let client = if let Some(transient_window) = self.xlib.get_transient_for_window(window) { |         let client = if let Some(transient_window) = | ||||||
|  |             self.xlib.get_transient_for_window(window) | ||||||
|  |         { | ||||||
|             Client::new_transient( |             Client::new_transient( | ||||||
|                 window, |                 window, | ||||||
|                 self.xlib.get_window_size(window).unwrap_or((100, 100)), |                 self.xlib.get_window_size(window).unwrap_or((100, 100)), | ||||||
|  | @ -502,3 +594,24 @@ impl KeyBinding { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | impl Default for WMConfig { | ||||||
|  |     fn default() -> Self { | ||||||
|  |         Self { | ||||||
|  |             num_virtualscreens: 5, | ||||||
|  |             mod_key: Mod4Mask, | ||||||
|  |             gap: Some(2), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl std::ops::Not for Direction { | ||||||
|  |     type Output = Self; | ||||||
|  | 
 | ||||||
|  |     fn not(self) -> Self::Output { | ||||||
|  |         match self { | ||||||
|  |             Direction::Left => Direction::Right, | ||||||
|  |             Direction::Right => Direction::Left, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										115
									
								
								src/xlib.rs
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								src/xlib.rs
									
									
									
									
									
								
							|  | @ -3,12 +3,14 @@ use std::ptr::{null, null_mut}; | ||||||
| use std::{ffi::CString, rc::Rc}; | use std::{ffi::CString, rc::Rc}; | ||||||
| 
 | 
 | ||||||
| use x11::xlib::{ | use x11::xlib::{ | ||||||
|     self, Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask, CurrentTime, |     self, Atom, ButtonPressMask, ButtonReleaseMask, CWEventMask, ControlMask, | ||||||
|     EnterWindowMask, FocusChangeMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, |     CurrentTime, EnterWindowMask, FocusChangeMask, LockMask, Mod1Mask, | ||||||
|     PointerMotionMask, PropertyChangeMask, ShiftMask, StructureNotifyMask, SubstructureNotifyMask, |     Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, PointerMotionMask, | ||||||
|     SubstructureRedirectMask, Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, |     PropertyChangeMask, ShiftMask, StructureNotifyMask, SubstructureNotifyMask, | ||||||
|     XEvent, XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow, XOpenDisplay, |     SubstructureRedirectMask, Window, XCloseDisplay, XConfigureRequestEvent, | ||||||
|     XRaiseWindow, XRootWindow, XSetErrorHandler, XSync, XUngrabPointer, XWarpPointer, |     XDefaultScreen, XEvent, XGetTransientForHint, XGrabPointer, XInternAtom, | ||||||
|  |     XKillClient, XMapWindow, XOpenDisplay, XRaiseWindow, XRootWindow, | ||||||
|  |     XSetErrorHandler, XSync, XUngrabPointer, XWarpPointer, | ||||||
| }; | }; | ||||||
| use xlib::GrabModeAsync; | use xlib::GrabModeAsync; | ||||||
| 
 | 
 | ||||||
|  | @ -76,7 +78,8 @@ impl XLib { | ||||||
|     pub fn init(&mut self) { |     pub fn init(&mut self) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut window_attributes = |             let mut window_attributes = | ||||||
|                 std::mem::MaybeUninit::<xlib::XSetWindowAttributes>::zeroed().assume_init(); |                 std::mem::MaybeUninit::<xlib::XSetWindowAttributes>::zeroed() | ||||||
|  |                     .assume_init(); | ||||||
| 
 | 
 | ||||||
|             window_attributes.event_mask = SubstructureRedirectMask |             window_attributes.event_mask = SubstructureRedirectMask | ||||||
|                 | StructureNotifyMask |                 | StructureNotifyMask | ||||||
|  | @ -92,7 +95,11 @@ impl XLib { | ||||||
|                 &mut window_attributes, |                 &mut window_attributes, | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             xlib::XSelectInput(self.dpy(), self.root, window_attributes.event_mask); |             xlib::XSelectInput( | ||||||
|  |                 self.dpy(), | ||||||
|  |                 self.root, | ||||||
|  |                 window_attributes.event_mask, | ||||||
|  |             ); | ||||||
| 
 | 
 | ||||||
|             XSetErrorHandler(Some(xlib_error_handler)); |             XSetErrorHandler(Some(xlib_error_handler)); | ||||||
|         } |         } | ||||||
|  | @ -123,9 +130,12 @@ impl XLib { | ||||||
| 
 | 
 | ||||||
|     pub fn squash_event(&self, event_type: i32) -> XEvent { |     pub fn squash_event(&self, event_type: i32) -> XEvent { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut event = std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init(); |             let mut event = | ||||||
|  |                 std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init(); | ||||||
| 
 | 
 | ||||||
|             while xlib::XCheckTypedEvent(self.dpy(), event_type, &mut event) != 0 {} |             while xlib::XCheckTypedEvent(self.dpy(), event_type, &mut event) | ||||||
|  |                 != 0 | ||||||
|  |             {} | ||||||
| 
 | 
 | ||||||
|             event |             event | ||||||
|         } |         } | ||||||
|  | @ -133,7 +143,8 @@ impl XLib { | ||||||
| 
 | 
 | ||||||
|     pub fn next_event(&self) -> XEvent { |     pub fn next_event(&self) -> XEvent { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut event = std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init(); |             let mut event = | ||||||
|  |                 std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init(); | ||||||
|             xlib::XNextEvent(self.dpy(), &mut event); |             xlib::XNextEvent(self.dpy(), &mut event); | ||||||
| 
 | 
 | ||||||
|             event |             event | ||||||
|  | @ -142,7 +153,8 @@ impl XLib { | ||||||
| 
 | 
 | ||||||
|     pub fn grab_key_or_button(&self, window: Window, key: &KeyOrButton) { |     pub fn grab_key_or_button(&self, window: Window, key: &KeyOrButton) { | ||||||
|         let numlock_mask = self.get_numlock_mask(); |         let numlock_mask = self.get_numlock_mask(); | ||||||
|         let modifiers = vec![0, LockMask, numlock_mask, LockMask | numlock_mask]; |         let modifiers = | ||||||
|  |             vec![0, LockMask, numlock_mask, LockMask | numlock_mask]; | ||||||
| 
 | 
 | ||||||
|         for modifier in modifiers.iter() { |         for modifier in modifiers.iter() { | ||||||
|             match key { |             match key { | ||||||
|  | @ -215,7 +227,11 @@ impl XLib { | ||||||
|                 xlib::CurrentTime, |                 xlib::CurrentTime, | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             xlib::XDeleteProperty(self.dpy(), self.root, self.atoms.active_window); |             xlib::XDeleteProperty( | ||||||
|  |                 self.dpy(), | ||||||
|  |                 self.root, | ||||||
|  |                 self.atoms.active_window, | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -237,7 +253,8 @@ impl XLib { | ||||||
|                 xlib::XConfigureWindow( |                 xlib::XConfigureWindow( | ||||||
|                     self.dpy(), |                     self.dpy(), | ||||||
|                     client.window, |                     client.window, | ||||||
|                     (xlib::CWY | xlib::CWX | xlib::CWHeight | xlib::CWWidth) as u32, |                     (xlib::CWY | xlib::CWX | xlib::CWHeight | xlib::CWWidth) | ||||||
|  |                         as u32, | ||||||
|                     &mut windowchanges, |                     &mut windowchanges, | ||||||
|                 ); |                 ); | ||||||
| 
 | 
 | ||||||
|  | @ -338,10 +355,14 @@ impl XLib { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_window_size(&self, window: Window) -> Option<(i32, i32)> { |     pub fn get_window_size(&self, window: Window) -> Option<(i32, i32)> { | ||||||
|         let mut wa = |         let mut wa = unsafe { | ||||||
|             unsafe { std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed().assume_init() }; |             std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed() | ||||||
|  |                 .assume_init() | ||||||
|  |         }; | ||||||
| 
 | 
 | ||||||
|         if unsafe { xlib::XGetWindowAttributes(self.dpy(), window, &mut wa) != 0 } { |         if unsafe { | ||||||
|  |             xlib::XGetWindowAttributes(self.dpy(), window, &mut wa) != 0 | ||||||
|  |         } { | ||||||
|             Some((wa.width, wa.height)) |             Some((wa.width, wa.height)) | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|  | @ -351,7 +372,9 @@ impl XLib { | ||||||
|     pub fn get_transient_for_window(&self, window: Window) -> Option<Window> { |     pub fn get_transient_for_window(&self, window: Window) -> Option<Window> { | ||||||
|         let mut transient_for: Window = 0; |         let mut transient_for: Window = 0; | ||||||
| 
 | 
 | ||||||
|         if unsafe { XGetTransientForHint(self.dpy(), window, &mut transient_for) != 0 } { |         if unsafe { | ||||||
|  |             XGetTransientForHint(self.dpy(), window, &mut transient_for) != 0 | ||||||
|  |         } { | ||||||
|             Some(transient_for) |             Some(transient_for) | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|  | @ -370,7 +393,12 @@ impl XLib { | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         unsafe { |         unsafe { | ||||||
|             xlib::XConfigureWindow(self.dpy(), event.window, event.value_mask as u32, &mut wc); |             xlib::XConfigureWindow( | ||||||
|  |                 self.dpy(), | ||||||
|  |                 event.window, | ||||||
|  |                 event.value_mask as u32, | ||||||
|  |                 &mut wc, | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -409,7 +437,10 @@ impl XLib { | ||||||
|             xlib::XSelectInput( |             xlib::XSelectInput( | ||||||
|                 self.dpy(), |                 self.dpy(), | ||||||
|                 window, |                 window, | ||||||
|                 EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask, |                 EnterWindowMask | ||||||
|  |                     | FocusChangeMask | ||||||
|  |                     | PropertyChangeMask | ||||||
|  |                     | StructureNotifyMask, | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -445,7 +476,8 @@ impl XLib { | ||||||
|                 self.dpy(), |                 self.dpy(), | ||||||
|                 self.root, |                 self.root, | ||||||
|                 0, |                 0, | ||||||
|                 (ButtonPressMask | ButtonReleaseMask | PointerMotionMask) as u32, |                 (ButtonPressMask | ButtonReleaseMask | PointerMotionMask) | ||||||
|  |                     as u32, | ||||||
|                 GrabModeAsync, |                 GrabModeAsync, | ||||||
|                 GrabModeAsync, |                 GrabModeAsync, | ||||||
|                 0, |                 0, | ||||||
|  | @ -463,7 +495,17 @@ impl XLib { | ||||||
| 
 | 
 | ||||||
|     pub fn move_cursor(&self, window: Window, position: (i32, i32)) { |     pub fn move_cursor(&self, window: Window, position: (i32, i32)) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             XWarpPointer(self.dpy(), 0, window, 0, 0, 0, 0, position.0, position.1); |             XWarpPointer( | ||||||
|  |                 self.dpy(), | ||||||
|  |                 0, | ||||||
|  |                 window, | ||||||
|  |                 0, | ||||||
|  |                 0, | ||||||
|  |                 0, | ||||||
|  |                 0, | ||||||
|  |                 position.0, | ||||||
|  |                 position.1, | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -472,7 +514,13 @@ impl XLib { | ||||||
|         let mut num_protos: i32 = 0; |         let mut num_protos: i32 = 0; | ||||||
| 
 | 
 | ||||||
|         unsafe { |         unsafe { | ||||||
|             if xlib::XGetWMProtocols(self.dpy(), client.window, &mut protos, &mut num_protos) != 0 { |             if xlib::XGetWMProtocols( | ||||||
|  |                 self.dpy(), | ||||||
|  |                 client.window, | ||||||
|  |                 &mut protos, | ||||||
|  |                 &mut num_protos, | ||||||
|  |             ) != 0 | ||||||
|  |             { | ||||||
|                 for i in 0..num_protos { |                 for i in 0..num_protos { | ||||||
|                     if *protos.offset(i as isize) == proto { |                     if *protos.offset(i as isize) == proto { | ||||||
|                         return true; |                         return true; | ||||||
|  | @ -503,7 +551,13 @@ impl XLib { | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             unsafe { |             unsafe { | ||||||
|                 xlib::XSendEvent(self.dpy(), client.window, 0, xlib::NoEventMask, &mut event); |                 xlib::XSendEvent( | ||||||
|  |                     self.dpy(), | ||||||
|  |                     client.window, | ||||||
|  |                     0, | ||||||
|  |                     xlib::NoEventMask, | ||||||
|  |                     &mut event, | ||||||
|  |                 ); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             true |             true | ||||||
|  | @ -543,7 +597,10 @@ impl XLib { | ||||||
|                     if *(*modmap) |                     if *(*modmap) | ||||||
|                         .modifiermap |                         .modifiermap | ||||||
|                         .offset((i * max_keypermod + j) as isize) |                         .offset((i * max_keypermod + j) as isize) | ||||||
|                         == xlib::XKeysymToKeycode(self.dpy(), x11::keysym::XK_Num_Lock as u64) |                         == xlib::XKeysymToKeycode( | ||||||
|  |                             self.dpy(), | ||||||
|  |                             x11::keysym::XK_Num_Lock as u64, | ||||||
|  |                         ) | ||||||
|                     { |                     { | ||||||
|                         return 1 << i; |                         return 1 << i; | ||||||
|                     } |                     } | ||||||
|  | @ -556,7 +613,13 @@ impl XLib { | ||||||
| 
 | 
 | ||||||
|     pub fn get_clean_mask(&self) -> u32 { |     pub fn get_clean_mask(&self) -> u32 { | ||||||
|         !(self.get_numlock_mask() | LockMask) |         !(self.get_numlock_mask() | LockMask) | ||||||
|             & (ShiftMask | ControlMask | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) |             & (ShiftMask | ||||||
|  |                 | ControlMask | ||||||
|  |                 | Mod1Mask | ||||||
|  |                 | Mod2Mask | ||||||
|  |                 | Mod3Mask | ||||||
|  |                 | Mod4Mask | ||||||
|  |                 | Mod5Mask) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue