refactor Client to better reflect different window types
This commit is contained in:
		
							parent
							
								
									449b4cccd8
								
							
						
					
					
						commit
						bae880c5e1
					
				|  | @ -1,6 +1,6 @@ | ||||||
| use log::{debug, error, warn}; | use log::{debug, error, warn}; | ||||||
| use num_traits::Zero; | use num_traits::Zero; | ||||||
| use std::{ptr::NonNull, rc::Rc}; | use std::{convert::TryFrom, ptr::NonNull, rc::Rc}; | ||||||
| 
 | 
 | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| 
 | 
 | ||||||
|  | @ -193,7 +193,7 @@ pub mod wmh { | ||||||
| pub mod ewmh { | pub mod ewmh { | ||||||
|     use std::{borrow::Borrow, ffi::CString, ops::Index, os::raw::c_long}; |     use std::{borrow::Borrow, ffi::CString, ops::Index, os::raw::c_long}; | ||||||
| 
 | 
 | ||||||
|     use strum::{EnumCount, EnumIter}; |     use strum::{EnumCount, EnumIter, FromRepr}; | ||||||
|     use x11::xlib::{Atom, XA_ATOM}; |     use x11::xlib::{Atom, XA_ATOM}; | ||||||
| 
 | 
 | ||||||
|     use super::{ |     use super::{ | ||||||
|  | @ -201,7 +201,9 @@ pub mod ewmh { | ||||||
|         Display, |         Display, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     #[derive(Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy)] |     #[derive(
 | ||||||
|  |         Debug, PartialEq, Eq, EnumIter, EnumCount, Clone, Copy, FromRepr, | ||||||
|  |     )] | ||||||
|     pub enum EWMHAtom { |     pub enum EWMHAtom { | ||||||
|         NetSupported, |         NetSupported, | ||||||
|         NetClientList, |         NetClientList, | ||||||
|  | @ -914,8 +916,6 @@ impl XLib { | ||||||
|                 ) == i32::from(Success) |                 ) == i32::from(Success) | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|         debug!("get_atom_property: {} {:?}", success, atom_out); |  | ||||||
| 
 |  | ||||||
|         success.then(|| atom_out).flatten() |         success.then(|| atom_out).flatten() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,13 +4,17 @@ use indexmap::IndexMap; | ||||||
| use log::error; | use log::error; | ||||||
| use num_traits::Zero; | use num_traits::Zero; | ||||||
| 
 | 
 | ||||||
|  | use crate::backends::structs::WindowType; | ||||||
| use crate::util::BuildIdentityHasher; | use crate::util::BuildIdentityHasher; | ||||||
| use crate::util::{Point, Size}; | use crate::util::{Point, Size}; | ||||||
| 
 | 
 | ||||||
| mod client { | mod client { | ||||||
|     use std::hash::{Hash, Hasher}; |     use std::hash::{Hash, Hasher}; | ||||||
| 
 | 
 | ||||||
|     use crate::util::{Point, Size}; |     use crate::{ | ||||||
|  |         backends::structs::WindowType, | ||||||
|  |         util::{Point, Size}, | ||||||
|  |     }; | ||||||
|     use x11::xlib::Window; |     use x11::xlib::Window; | ||||||
| 
 | 
 | ||||||
|     #[derive(Clone, Debug)] |     #[derive(Clone, Debug)] | ||||||
|  | @ -18,7 +22,8 @@ mod client { | ||||||
|         pub(crate) window: Window, |         pub(crate) window: Window, | ||||||
|         pub(crate) size: Size<i32>, |         pub(crate) size: Size<i32>, | ||||||
|         pub(crate) position: Point<i32>, |         pub(crate) position: Point<i32>, | ||||||
|         pub(crate) transient_for: Option<Window>, |         pub(crate) parent_window: Option<Window>, | ||||||
|  |         pub(crate) window_type: WindowType, | ||||||
|         pub(crate) fullscreen: bool, |         pub(crate) fullscreen: bool, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -28,8 +33,9 @@ mod client { | ||||||
|                 window: 0, |                 window: 0, | ||||||
|                 size: (100, 100).into(), |                 size: (100, 100).into(), | ||||||
|                 position: (0, 0).into(), |                 position: (0, 0).into(), | ||||||
|                 transient_for: None, |                 parent_window: None, | ||||||
|                 fullscreen: false, |                 fullscreen: false, | ||||||
|  |                 window_type: WindowType::Normal, | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -49,7 +55,7 @@ mod client { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pub fn new_transient( |         pub fn new_dialog( | ||||||
|             window: Window, |             window: Window, | ||||||
|             size: Size<i32>, |             size: Size<i32>, | ||||||
|             transient: Window, |             transient: Window, | ||||||
|  | @ -57,7 +63,7 @@ mod client { | ||||||
|             Self { |             Self { | ||||||
|                 window, |                 window, | ||||||
|                 size, |                 size, | ||||||
|                 transient_for: Some(transient), |                 parent_window: Some(transient), | ||||||
|                 ..Default::default() |                 ..Default::default() | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -69,6 +75,24 @@ mod client { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         pub fn with_window_type(self, window_type: WindowType) -> Self { | ||||||
|  |             Self { | ||||||
|  |                 window_type, | ||||||
|  |                 ..self | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         pub fn with_parent_window(self, parent_window: Option<Window>) -> Self { | ||||||
|  |             Self { | ||||||
|  |                 parent_window, | ||||||
|  |                 ..self | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         pub fn with_size(self, size: Size<i32>) -> Self { | ||||||
|  |             Self { size, ..self } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         /// toggles the clients fullscreen flag.
 |         /// toggles the clients fullscreen flag.
 | ||||||
|         /// returns `true` if the client is now fullscreen.
 |         /// returns `true` if the client is now fullscreen.
 | ||||||
|         pub fn toggle_fullscreen(&mut self) -> bool { |         pub fn toggle_fullscreen(&mut self) -> bool { | ||||||
|  | @ -90,8 +114,8 @@ mod client { | ||||||
|             self.fullscreen |             self.fullscreen | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         pub fn is_transient(&self) -> bool { |         pub fn has_parent_window(&self) -> bool { | ||||||
|             self.transient_for.is_some() |             self.parent_window.is_some() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -240,27 +264,42 @@ 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() |         match client.window_type { | ||||||
|             && self.contains(&client.transient_for.unwrap()) |             // idk how to handle docks and desktops, for now they float innit
 | ||||||
|  |             WindowType::Splash | ||||||
|  |             | WindowType::Dialog | ||||||
|  |             | WindowType::Utility | ||||||
|  |             | WindowType::Menu | ||||||
|  |             | WindowType::Toolbar | ||||||
|  |             | WindowType::Dock | ||||||
|  |             | WindowType::Desktop => { | ||||||
|  |                 if let Some(parent) = client | ||||||
|  |                     .parent_window | ||||||
|  |                     .and_then(|window| self.get(&window).into_option()) | ||||||
|                 { |                 { | ||||||
|             let transient = self.get(&client.transient_for.unwrap()).unwrap(); |  | ||||||
| 
 |  | ||||||
|                     client.position = { |                     client.position = { | ||||||
|                         ( |                         ( | ||||||
|                     transient.position.x |                             parent.position.x | ||||||
|                         + (transient.size.width - client.size.width) / 2, |                                 + (parent.size.width - client.size.width) / 2, | ||||||
|                     transient.position.y |                             parent.position.y | ||||||
|                         + (transient.size.height - client.size.height) / 2, |                                 + (parent.size.height - client.size.height) / 2, | ||||||
|                         ) |                         ) | ||||||
|                             .into() |                             .into() | ||||||
|                     }; |                     }; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 client.size = client.size.clamp( | ||||||
|  |                     self.screen_size | ||||||
|  |                         - Size::new(self.border_size * 2, self.border_size * 2), | ||||||
|  |                 ); | ||||||
| 
 | 
 | ||||||
|                 self.floating_clients.insert(key, client); |                 self.floating_clients.insert(key, client); | ||||||
|         } else { |             } | ||||||
|  |             WindowType::Normal => { | ||||||
|                 self.clients.insert(key, client); |                 self.clients.insert(key, client); | ||||||
| 
 |  | ||||||
|                 self.virtual_screens.get_mut_current().insert(&key); |                 self.virtual_screens.get_mut_current().insert(&key); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // adding a client changes the liling layout, rearrange
 |         // adding a client changes the liling layout, rearrange
 | ||||||
|         self.arrange_virtual_screen(); |         self.arrange_virtual_screen(); | ||||||
|  | @ -320,7 +359,15 @@ impl ClientState { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn iter_transient(&self) -> impl Iterator<Item = (&u64, &Client)> { |     pub fn iter_transient(&self) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|         self.iter_floating().filter(|&(_, c)| c.is_transient()) |         self.iter_floating().filter(|&(_, c)| c.has_parent_window()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn iter_by_window_type( | ||||||
|  |         &self, | ||||||
|  |         window_type: WindowType, | ||||||
|  |     ) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|  |         self.iter_floating() | ||||||
|  |             .filter(move |&(_, c)| c.window_type == window_type) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn iter_visible(&self) -> impl Iterator<Item = (&u64, &Client)> { |     pub fn iter_visible(&self) -> impl Iterator<Item = (&u64, &Client)> { | ||||||
|  | @ -357,7 +404,7 @@ impl ClientState { | ||||||
|     { |     { | ||||||
|         match self.get(key) { |         match self.get(key) { | ||||||
|             ClientEntry::Floating(c) => { |             ClientEntry::Floating(c) => { | ||||||
|                 if let Some(transient_for) = c.transient_for { |                 if let Some(transient_for) = c.parent_window { | ||||||
|                     self.is_client_visible(&transient_for) |                     self.is_client_visible(&transient_for) | ||||||
|                 } else { |                 } else { | ||||||
|                     true |                     true | ||||||
|  | @ -519,15 +566,15 @@ impl ClientState { | ||||||
|                 } |                 } | ||||||
|                 (None, Some(floating_client)) => { |                 (None, Some(floating_client)) => { | ||||||
|                     // transient clients cannot be tiled
 |                     // transient clients cannot be tiled
 | ||||||
|                     match floating_client.is_transient() { |                     // only normal windows can be tiled
 | ||||||
|                         true => { |                     match floating_client.window_type { | ||||||
|                             self.floating_clients.insert(key, floating_client); |                         WindowType::Normal => { | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         false => { |  | ||||||
|                             self.clients.insert(key, floating_client); |                             self.clients.insert(key, floating_client); | ||||||
|                             self.virtual_screens.get_mut_current().insert(&key); |                             self.virtual_screens.get_mut_current().insert(&key); | ||||||
|                         } |                         } | ||||||
|  |                         _ => { | ||||||
|  |                             self.floating_clients.insert(key, floating_client); | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 _ => { |                 _ => { | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								src/state.rs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/state.rs
									
									
									
									
									
								
							|  | @ -4,6 +4,7 @@ use log::{error, info}; | ||||||
| 
 | 
 | ||||||
| use x11::xlib::{self, Window}; | use x11::xlib::{self, Window}; | ||||||
| 
 | 
 | ||||||
|  | use crate::backends::structs::WindowType; | ||||||
| use crate::backends::window_event::{ | use crate::backends::window_event::{ | ||||||
|     FullscreenEvent, FullscreenState, WindowNameEvent, |     FullscreenEvent, FullscreenState, WindowNameEvent, | ||||||
| }; | }; | ||||||
|  | @ -748,19 +749,16 @@ where | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn new_client(&mut self, window: Window) { |     fn new_client(&mut self, window: Window) { | ||||||
|         info!("new client: {:?}", window); |         let client = match self.backend.get_window_type(window) { | ||||||
|         let client = if let Some(transient_window) = |             WindowType::Normal => Client::new_default(window), | ||||||
|             self.backend.get_parent_window(window) |             window_type @ _ => Client::new_default(window) | ||||||
|         { |                 .with_window_type(window_type) | ||||||
|             Client::new_transient( |                 .with_size( | ||||||
|                 window, |  | ||||||
|                     self.backend |                     self.backend | ||||||
|                         .get_window_size(window) |                         .get_window_size(window) | ||||||
|                         .unwrap_or((100, 100).into()), |                         .unwrap_or((100, 100).into()), | ||||||
|                 transient_window, |  | ||||||
|                 ) |                 ) | ||||||
|         } else { |                 .with_parent_window(self.backend.get_parent_window(window)), | ||||||
|             Client::new_default(window) |  | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         self.backend.configure_window( |         self.backend.configure_window( | ||||||
|  | @ -770,6 +768,8 @@ where | ||||||
|             Some(self.clients.get_border()), |             Some(self.clients.get_border()), | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|  |         info!("new client: {:#?}", client); | ||||||
|  | 
 | ||||||
|         self.clients.insert(client).unwrap(); |         self.clients.insert(client).unwrap(); | ||||||
|         self.arrange_clients(); |         self.arrange_clients(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue