fixed some bugs related to floating window stacking
This commit is contained in:
		
							parent
							
								
									95d7740119
								
							
						
					
					
						commit
						134e727b25
					
				| 
						 | 
					@ -1,3 +1,2 @@
 | 
				
			||||||
imports_granularity = "Crate"
 | 
					#wrap_comments = true
 | 
				
			||||||
wrap_comments = true
 | 
					 | 
				
			||||||
max_width = 80
 | 
					max_width = 80
 | 
				
			||||||
							
								
								
									
										189
									
								
								src/clients.rs
									
									
									
									
									
								
							
							
						
						
									
										189
									
								
								src/clients.rs
									
									
									
									
									
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
#![allow(dead_code)]
 | 
					#![allow(dead_code)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::collections::HashMap;
 | 
					 | 
				
			||||||
use std::num::NonZeroI32;
 | 
					use std::num::NonZeroI32;
 | 
				
			||||||
 | 
					use std::{collections::HashMap, ops::Rem, usize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use log::{error, info};
 | 
					use log::{error, info};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,31 +113,6 @@ mod client {
 | 
				
			||||||
            self.to_owned()
 | 
					            self.to_owned()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
    impl Borrow<Window> for Client {
 | 
					 | 
				
			||||||
    fn borrow(&self) -> &Window {
 | 
					 | 
				
			||||||
    &self.window
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl ClientKey for Rc<Client> {
 | 
					 | 
				
			||||||
    fn key(&self) -> u64 {
 | 
					 | 
				
			||||||
    self.window
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    impl<'a> Borrow<dyn ClientKey + 'a> for Client {
 | 
					 | 
				
			||||||
    fn borrow(&self) -> &(dyn ClientKey + 'a) {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    impl<'a> Borrow<dyn ClientKey + 'a> for Rc<Client> {
 | 
					 | 
				
			||||||
    fn borrow(&self) -> &(dyn ClientKey + 'a) {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use client::*;
 | 
					pub use client::*;
 | 
				
			||||||
| 
						 | 
					@ -218,56 +193,15 @@ pub enum ClientEntry<T> {
 | 
				
			||||||
    Vacant,
 | 
					    Vacant,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T> Into<Option<T>> for ClientEntry<T> {
 | 
					 | 
				
			||||||
    fn into(self) -> Option<T> {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Self::Vacant => None,
 | 
					 | 
				
			||||||
            Self::Tiled(client) | Self::Floating(client) => Some(client),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T> ClientEntry<T> {
 | 
					 | 
				
			||||||
    pub fn into_option(self) -> Option<T> {
 | 
					 | 
				
			||||||
        self.into()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn unwrap(self) -> T {
 | 
					 | 
				
			||||||
        self.into_option().unwrap()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn is_vacant(&self) -> bool {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            ClientEntry::Vacant => true,
 | 
					 | 
				
			||||||
            _ => false,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn is_floating(&self) -> bool {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            ClientEntry::Floating(_) => true,
 | 
					 | 
				
			||||||
            _ => false,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn is_tiled(&self) -> bool {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            ClientEntry::Tiled(_) => true,
 | 
					 | 
				
			||||||
            _ => false,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn is_occupied(&self) -> bool {
 | 
					 | 
				
			||||||
        !self.is_vacant()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
pub struct ClientState {
 | 
					pub struct ClientState {
 | 
				
			||||||
    pub(self) clients: Clients,
 | 
					    pub(self) clients: Clients,
 | 
				
			||||||
    pub(self) floating_clients: Clients,
 | 
					    pub(self) floating_clients: Clients,
 | 
				
			||||||
    focused: Option<ClientRef>,
 | 
					    focused: Option<ClientRef>,
 | 
				
			||||||
    pub(self) virtual_screens: VecDeque<VirtualScreen>,
 | 
					    pub(self) virtual_screens: VecDeque<VirtualScreen>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gap: i32,
 | 
				
			||||||
 | 
					    screen_size: (i32, i32),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone)]
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
| 
						 | 
					@ -286,6 +220,8 @@ impl Default for ClientState {
 | 
				
			||||||
            floating_clients: Default::default(),
 | 
					            floating_clients: Default::default(),
 | 
				
			||||||
            focused: None,
 | 
					            focused: None,
 | 
				
			||||||
            virtual_screens: vss,
 | 
					            virtual_screens: vss,
 | 
				
			||||||
 | 
					            gap: 0,
 | 
				
			||||||
 | 
					            screen_size: (1, 1),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -295,13 +231,24 @@ impl ClientState {
 | 
				
			||||||
        Self::default()
 | 
					        Self::default()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn with_virtualscreens(num: usize) -> Self {
 | 
					    pub fn with_gap(self, gap: i32) -> Self {
 | 
				
			||||||
 | 
					        Self { gap, ..self }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn with_screen_size(self, screen_size: (i32, i32)) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            screen_size,
 | 
				
			||||||
 | 
					            ..self
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn with_virtualscreens(self, num: usize) -> Self {
 | 
				
			||||||
        let mut vss = VecDeque::<VirtualScreen>::new();
 | 
					        let mut vss = VecDeque::<VirtualScreen>::new();
 | 
				
			||||||
        vss.resize_with(num, Default::default);
 | 
					        vss.resize_with(num, Default::default);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            virtual_screens: vss,
 | 
					            virtual_screens: vss,
 | 
				
			||||||
            ..Default::default()
 | 
					            ..self
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -333,6 +280,9 @@ impl ClientState {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.focus_client(&key);
 | 
					        self.focus_client(&key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // adding a client changes the liling layout, rearrange
 | 
				
			||||||
 | 
					        self.arrange_virtual_screen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO: eventually make this function return a `ClientEntry` instead of an `Option`.
 | 
					        // TODO: eventually make this function return a `ClientEntry` instead of an `Option`.
 | 
				
			||||||
        self.get(&key).into_option()
 | 
					        self.get(&key).into_option()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -351,6 +301,9 @@ impl ClientState {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.clients.remove(&key.key());
 | 
					        self.clients.remove(&key.key());
 | 
				
			||||||
        self.floating_clients.remove(&key.key());
 | 
					        self.floating_clients.remove(&key.key());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // removing a client changes the liling layout, rearrange
 | 
				
			||||||
 | 
					        self.arrange_virtual_screen();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn contains<K>(&self, key: &K) -> bool
 | 
					    pub fn contains<K>(&self, key: &K) -> bool
 | 
				
			||||||
| 
						 | 
					@ -460,12 +413,18 @@ impl ClientState {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn rotate_right(&mut self) {
 | 
					    pub fn rotate_right(&mut self, n: Option<usize>) {
 | 
				
			||||||
        self.virtual_screens.rotate_right(1);
 | 
					        self.virtual_screens
 | 
				
			||||||
 | 
					            .rotate_right(n.unwrap_or(1).rem(self.virtual_screens.len()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.arrange_virtual_screen();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn rotate_left(&mut self) {
 | 
					    pub fn rotate_left(&mut self, n: Option<usize>) {
 | 
				
			||||||
        self.virtual_screens.rotate_left(1);
 | 
					        self.virtual_screens
 | 
				
			||||||
 | 
					            .rotate_left(n.unwrap_or(1).rem(self.virtual_screens.len()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.arrange_virtual_screen();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -508,6 +467,7 @@ impl ClientState {
 | 
				
			||||||
                    true => {
 | 
					                    true => {
 | 
				
			||||||
                        self.floating_clients.insert(key, floating_client);
 | 
					                        self.floating_clients.insert(key, floating_client);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    false => {
 | 
					                    false => {
 | 
				
			||||||
                        self.clients.insert(key, floating_client);
 | 
					                        self.clients.insert(key, floating_client);
 | 
				
			||||||
                        if let Some(vs) = self.virtual_screens.front_mut() {
 | 
					                        if let Some(vs) = self.virtual_screens.front_mut() {
 | 
				
			||||||
| 
						 | 
					@ -520,14 +480,22 @@ impl ClientState {
 | 
				
			||||||
                error!("wtf? Client was present in tiled and floating list.")
 | 
					                error!("wtf? Client was present in tiled and floating list.")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // we added or removed a client from the tiling so the layout changed, rearrange
 | 
				
			||||||
 | 
					        self.arrange_virtual_screen();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn remove_from_virtual_screens<K>(&mut self, key: &K)
 | 
					    fn remove_from_virtual_screens<K>(&mut self, key: &K)
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        K: ClientKey,
 | 
					        K: ClientKey,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if let Some(vs) = self.get_mut_virtualscreen_for_client(key) {
 | 
					        if self.contains(key) {
 | 
				
			||||||
            vs.remove(key);
 | 
					            if let Some(vs) = self.get_mut_virtualscreen_for_client(key) {
 | 
				
			||||||
 | 
					                vs.remove(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // we removed a client so the layout changed, rearrange
 | 
				
			||||||
 | 
					                self.arrange_virtual_screen();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -578,7 +546,9 @@ impl ClientState {
 | 
				
			||||||
                    if focused == key.key() {
 | 
					                    if focused == key.key() {
 | 
				
			||||||
                        (ClientEntry::Vacant, ClientEntry::Vacant)
 | 
					                        (ClientEntry::Vacant, ClientEntry::Vacant)
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        // focus the new client and return reference to it and the previously focused client.
 | 
					                        // focus the new client and return reference to it
 | 
				
			||||||
 | 
					                        // and the previously focused client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        self.focused = Some(key.key());
 | 
					                        self.focused = Some(key.key());
 | 
				
			||||||
                        (self.get(key), self.get(&focused))
 | 
					                        (self.get(key), self.get(&focused))
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -599,7 +569,8 @@ impl ClientState {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
    sets `self.focused` to `None` and returns a reference to the previously focused Client if any.
 | 
					    sets `self.focused` to `None` and returns a reference to
 | 
				
			||||||
 | 
					    the previously focused Client if any.
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    pub fn unfocus(&mut self) -> ClientEntry<&Client> {
 | 
					    pub fn unfocus(&mut self) -> ClientEntry<&Client> {
 | 
				
			||||||
        match self.focused {
 | 
					        match self.focused {
 | 
				
			||||||
| 
						 | 
					@ -627,6 +598,8 @@ impl ClientState {
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if let Some(vs) = self.get_mut_virtualscreen_for_client(key) {
 | 
					        if let Some(vs) = self.get_mut_virtualscreen_for_client(key) {
 | 
				
			||||||
            vs.switch_stack_for_client(key);
 | 
					            vs.switch_stack_for_client(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.arrange_virtual_screen();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -635,13 +608,9 @@ 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(
 | 
					    pub fn arrange_virtual_screen(&mut self) {
 | 
				
			||||||
        &mut self,
 | 
					        let gap = self.gap;
 | 
				
			||||||
        width: i32,
 | 
					        let (width, height) = self.screen_size;
 | 
				
			||||||
        height: i32,
 | 
					 | 
				
			||||||
        gap: Option<i32>,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        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
 | 
				
			||||||
        if let Some(vs) = self.virtual_screens.front_mut() {
 | 
					        if let Some(vs) = self.virtual_screens.front_mut() {
 | 
				
			||||||
| 
						 | 
					@ -692,7 +661,7 @@ impl ClientState {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info!("{:#?}", self);
 | 
					        //info!("{:#?}", self);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Should have xlib send those changes back to the x server after this function
 | 
					    // Should have xlib send those changes back to the x server after this function
 | 
				
			||||||
| 
						 | 
					@ -777,3 +746,47 @@ impl VirtualScreen {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> Into<Option<T>> for ClientEntry<T> {
 | 
				
			||||||
 | 
					    fn into(self) -> Option<T> {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::Vacant => None,
 | 
				
			||||||
 | 
					            Self::Tiled(client) | Self::Floating(client) => Some(client),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> ClientEntry<T> {
 | 
				
			||||||
 | 
					    pub fn into_option(self) -> Option<T> {
 | 
				
			||||||
 | 
					        self.into()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn unwrap(self) -> T {
 | 
				
			||||||
 | 
					        self.into_option().unwrap()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn is_vacant(&self) -> bool {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ClientEntry::Vacant => true,
 | 
				
			||||||
 | 
					            _ => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn is_floating(&self) -> bool {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ClientEntry::Floating(_) => true,
 | 
				
			||||||
 | 
					            _ => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn is_tiled(&self) -> bool {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            ClientEntry::Tiled(_) => true,
 | 
				
			||||||
 | 
					            _ => false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn is_occupied(&self) -> bool {
 | 
				
			||||||
 | 
					        !self.is_vacant()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log_prologue();
 | 
					    log_prologue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state::WindowManager::new(WMConfig::default()).init().run();
 | 
					    state::WindowManager::new(WMConfig::default()).run();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn log_prologue() {
 | 
					fn log_prologue() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										71
									
								
								src/state.rs
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								src/state.rs
									
									
									
									
									
								
							| 
						 | 
					@ -13,7 +13,7 @@ use xlib::{
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    clients::{Client, ClientKey, ClientState},
 | 
					    clients::{Client, ClientEntry, ClientKey, ClientState},
 | 
				
			||||||
    xlib::KeyOrButton,
 | 
					    xlib::KeyOrButton,
 | 
				
			||||||
    xlib::XLib,
 | 
					    xlib::XLib,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -40,8 +40,8 @@ pub struct WindowManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, Copy)]
 | 
					#[derive(Debug, Clone, Copy)]
 | 
				
			||||||
pub enum Direction {
 | 
					pub enum Direction {
 | 
				
			||||||
    Left,
 | 
					    Left(Option<usize>),
 | 
				
			||||||
    Right,
 | 
					    Right(Option<usize>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum MoveResizeInfo {
 | 
					enum MoveResizeInfo {
 | 
				
			||||||
| 
						 | 
					@ -70,10 +70,13 @@ struct KeyBinding {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl WindowManager {
 | 
					impl WindowManager {
 | 
				
			||||||
    pub fn new(config: WMConfig) -> Self {
 | 
					    pub fn new(config: WMConfig) -> Self {
 | 
				
			||||||
        let clients =
 | 
					 | 
				
			||||||
            ClientState::with_virtualscreens(config.num_virtualscreens);
 | 
					 | 
				
			||||||
        let xlib = XLib::new();
 | 
					        let xlib = XLib::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let clients = ClientState::new()
 | 
				
			||||||
 | 
					            .with_virtualscreens(config.num_virtualscreens)
 | 
				
			||||||
 | 
					            .with_gap(config.gap.unwrap_or(1))
 | 
				
			||||||
 | 
					            .with_screen_size(xlib.dimensions());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            clients,
 | 
					            clients,
 | 
				
			||||||
            move_resize_window: MoveResizeInfo::None,
 | 
					            move_resize_window: MoveResizeInfo::None,
 | 
				
			||||||
| 
						 | 
					@ -82,9 +85,10 @@ impl WindowManager {
 | 
				
			||||||
            last_rotation: None,
 | 
					            last_rotation: None,
 | 
				
			||||||
            config,
 | 
					            config,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        .init()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn init(mut self) -> Self {
 | 
					    fn init(mut self) -> Self {
 | 
				
			||||||
        self.xlib.add_global_keybind(KeyOrButton::button(
 | 
					        self.xlib.add_global_keybind(KeyOrButton::button(
 | 
				
			||||||
            1,
 | 
					            1,
 | 
				
			||||||
            self.config.mod_key,
 | 
					            self.config.mod_key,
 | 
				
			||||||
| 
						 | 
					@ -152,12 +156,12 @@ impl WindowManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_keybind(KeyBinding::new(
 | 
					        self.add_keybind(KeyBinding::new(
 | 
				
			||||||
            self.xlib.make_key("Left", self.config.mod_key),
 | 
					            self.xlib.make_key("Left", self.config.mod_key),
 | 
				
			||||||
            |wm, _| wm.rotate_virtual_screen(Direction::Left),
 | 
					            |wm, _| wm.rotate_virtual_screen(Direction::Left(None)),
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_keybind(KeyBinding::new(
 | 
					        self.add_keybind(KeyBinding::new(
 | 
				
			||||||
            self.xlib.make_key("Right", self.config.mod_key),
 | 
					            self.xlib.make_key("Right", self.config.mod_key),
 | 
				
			||||||
            |wm, _| wm.rotate_virtual_screen(Direction::Right),
 | 
					            |wm, _| wm.rotate_virtual_screen(Direction::Right(None)),
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_keybind(KeyBinding::new(
 | 
					        self.add_keybind(KeyBinding::new(
 | 
				
			||||||
| 
						 | 
					@ -177,12 +181,12 @@ impl WindowManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_keybind(KeyBinding::new(
 | 
					        self.add_keybind(KeyBinding::new(
 | 
				
			||||||
            self.xlib.make_key("J", self.config.mod_key | ShiftMask),
 | 
					            self.xlib.make_key("J", self.config.mod_key | ShiftMask),
 | 
				
			||||||
            |wm, _| wm.rotate_virtual_screen(Direction::Left),
 | 
					            |wm, _| wm.rotate_virtual_screen(Direction::Left(None)),
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.add_keybind(KeyBinding::new(
 | 
					        self.add_keybind(KeyBinding::new(
 | 
				
			||||||
            self.xlib.make_key("K", self.config.mod_key | ShiftMask),
 | 
					            self.xlib.make_key("K", self.config.mod_key | ShiftMask),
 | 
				
			||||||
            |wm, _| wm.rotate_virtual_screen(Direction::Right),
 | 
					            |wm, _| wm.rotate_virtual_screen(Direction::Right(None)),
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.xlib.init();
 | 
					        self.xlib.init();
 | 
				
			||||||
| 
						 | 
					@ -262,8 +266,8 @@ impl WindowManager {
 | 
				
			||||||
        self.last_rotation = Some(dir);
 | 
					        self.last_rotation = Some(dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match dir {
 | 
					        match dir {
 | 
				
			||||||
            Direction::Left => self.clients.rotate_left(),
 | 
					            Direction::Left(n) => self.clients.rotate_left(n),
 | 
				
			||||||
            Direction::Right => self.clients.rotate_right(),
 | 
					            Direction::Right(n) => self.clients.rotate_right(n),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.arrange_clients();
 | 
					        self.arrange_clients();
 | 
				
			||||||
| 
						 | 
					@ -273,7 +277,7 @@ impl WindowManager {
 | 
				
			||||||
            self.clients.iter_visible().next().map(|(k, _)| k).cloned();
 | 
					            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, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,7 +290,7 @@ impl WindowManager {
 | 
				
			||||||
            .cloned();
 | 
					            .cloned();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(k) = k {
 | 
					        if let Some(k) = k {
 | 
				
			||||||
            self.focus_client(&k);
 | 
					            self.focus_client(&k, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -299,7 +303,7 @@ impl WindowManager {
 | 
				
			||||||
            .cloned();
 | 
					            .cloned();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(k) = k {
 | 
					        if let Some(k) = k {
 | 
				
			||||||
            self.focus_client(&k);
 | 
					            self.focus_client(&k, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,10 +324,6 @@ impl WindowManager {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn arrange_clients(&mut self) {
 | 
					    fn arrange_clients(&mut self) {
 | 
				
			||||||
        let (width, height) = self.xlib.dimensions();
 | 
					 | 
				
			||||||
        self.clients
 | 
					 | 
				
			||||||
            .arrange_virtual_screen(width, height, self.config.gap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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));
 | 
				
			||||||
| 
						 | 
					@ -333,7 +333,7 @@ impl WindowManager {
 | 
				
			||||||
        self.raise_floating_clients();
 | 
					        self.raise_floating_clients();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn focus_client<K>(&mut self, key: &K)
 | 
					    fn focus_client<K>(&mut self, key: &K, try_raise: bool)
 | 
				
			||||||
    where
 | 
					    where
 | 
				
			||||||
        K: ClientKey,
 | 
					        K: ClientKey,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -343,12 +343,19 @@ impl WindowManager {
 | 
				
			||||||
            self.xlib.unfocus_client(old);
 | 
					            self.xlib.unfocus_client(old);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(new) = new.into_option() {
 | 
					        match new {
 | 
				
			||||||
            self.xlib.focus_client(new);
 | 
					            ClientEntry::Floating(new) => {
 | 
				
			||||||
            self.xlib.raise_client(new);
 | 
					                self.xlib.focus_client(new);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.raise_floating_clients();
 | 
					                if try_raise {
 | 
				
			||||||
 | 
					                    self.xlib.raise_client(new);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ClientEntry::Tiled(new) => {
 | 
				
			||||||
 | 
					                self.xlib.focus_client(new);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            _ => {}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn new_client(&mut self, window: Window) {
 | 
					    fn new_client(&mut self, window: Window) {
 | 
				
			||||||
| 
						 | 
					@ -368,7 +375,7 @@ impl WindowManager {
 | 
				
			||||||
        self.clients.insert(client).unwrap();
 | 
					        self.clients.insert(client).unwrap();
 | 
				
			||||||
        self.xlib.map_window(window);
 | 
					        self.xlib.map_window(window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.focus_client(&window);
 | 
					        self.focus_client(&window, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.arrange_clients();
 | 
					        self.arrange_clients();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -377,15 +384,12 @@ impl WindowManager {
 | 
				
			||||||
        let event: &XMapRequestEvent = event.as_ref();
 | 
					        let event: &XMapRequestEvent = event.as_ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if !self.clients.contains(&event.window) {
 | 
					        if !self.clients.contains(&event.window) {
 | 
				
			||||||
            info!("MapRequest: new client: {:?}", event.window);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.new_client(event.window);
 | 
					            self.new_client(event.window);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn unmap_notify(&mut self, event: &XEvent) {
 | 
					    fn unmap_notify(&mut self, event: &XEvent) {
 | 
				
			||||||
        let event: &XUnmapEvent = event.as_ref();
 | 
					        let event: &XUnmapEvent = event.as_ref();
 | 
				
			||||||
        info!("unmap_notify: {:?}", event.window);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.clients.remove(&event.window);
 | 
					        self.clients.remove(&event.window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -394,7 +398,6 @@ impl WindowManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn destroy_notify(&mut self, event: &XEvent) {
 | 
					    fn destroy_notify(&mut self, event: &XEvent) {
 | 
				
			||||||
        let event: &XDestroyWindowEvent = event.as_ref();
 | 
					        let event: &XDestroyWindowEvent = event.as_ref();
 | 
				
			||||||
        info!("destroy_notify: {:?}", event.window);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.clients.remove(&event.window);
 | 
					        self.clients.remove(&event.window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -413,7 +416,7 @@ impl WindowManager {
 | 
				
			||||||
    fn enter_notify(&mut self, event: &XEvent) {
 | 
					    fn enter_notify(&mut self, event: &XEvent) {
 | 
				
			||||||
        let event: &XCrossingEvent = event.as_ref();
 | 
					        let event: &XCrossingEvent = event.as_ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.focus_client(&event.window);
 | 
					        self.focus_client(&event.window, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// ensure event.subwindow refers to a valid client.
 | 
					    /// ensure event.subwindow refers to a valid client.
 | 
				
			||||||
| 
						 | 
					@ -514,7 +517,7 @@ impl WindowManager {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn button_press(&mut self, event: &XButtonPressedEvent) {
 | 
					    fn button_press(&mut self, event: &XButtonPressedEvent) {
 | 
				
			||||||
        self.focus_client(&event.subwindow);
 | 
					        self.focus_client(&event.subwindow, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match event.button {
 | 
					        match event.button {
 | 
				
			||||||
            1 | 3 => match self.move_resize_window {
 | 
					            1 | 3 => match self.move_resize_window {
 | 
				
			||||||
| 
						 | 
					@ -587,8 +590,8 @@ impl std::ops::Not for Direction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn not(self) -> Self::Output {
 | 
					    fn not(self) -> Self::Output {
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Direction::Left => Direction::Right,
 | 
					            Direction::Left(n) => Direction::Right(n),
 | 
				
			||||||
            Direction::Right => Direction::Left,
 | 
					            Direction::Right(n) => Direction::Left(n),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,12 +216,10 @@ impl XLib {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.send_event(client, self.atoms.take_focus);
 | 
					        self.send_event(client, self.atoms.take_focus);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.raise_client(client);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn unfocus_client(&self, client: &Client) {
 | 
					    pub fn unfocus_client(&self, client: &Client) {
 | 
				
			||||||
        info!("unfocusing client: {:?}", client);
 | 
					        //info!("unfocusing client: {:?}", client);
 | 
				
			||||||
        unsafe {
 | 
					        unsafe {
 | 
				
			||||||
            xlib::XSetInputFocus(
 | 
					            xlib::XSetInputFocus(
 | 
				
			||||||
                self.dpy(),
 | 
					                self.dpy(),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								xinitrc
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								xinitrc
									
									
									
									
									
								
							| 
						 | 
					@ -4,4 +4,4 @@
 | 
				
			||||||
/usr/bin/xsetroot -solid darkslategrey
 | 
					/usr/bin/xsetroot -solid darkslategrey
 | 
				
			||||||
/usr/bin/feh --bg-fill "/mnt/storage/rust/wm/starship.jpg"
 | 
					/usr/bin/feh --bg-fill "/mnt/storage/rust/wm/starship.jpg"
 | 
				
			||||||
export RUST_BACKTRACE=1
 | 
					export RUST_BACKTRACE=1
 | 
				
			||||||
exec /mnt/storage/rust/wm/target/debug/wm >& /home/user/.local/portlights.log
 | 
					exec /mnt/storage/rust/wm/target/release/wm >& /home/user/.local/portlights.log
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue