From f6a871d1e7a21afaf530842c5ea58aedb618e314 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 18:15:45 +0100 Subject: [PATCH 1/5] changed `FullscreenEvent` to be `On, Off, Toggle` instead of a simple bool --- src/backends/window_event.rs | 27 ++++++++--- src/backends/xlib/mod.rs | 86 ++++++++++++++++++++++++++++++++++-- src/state.rs | 12 +++-- 3 files changed, 111 insertions(+), 14 deletions(-) diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index c99beba..507f0af 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -265,18 +265,31 @@ impl ConfigureEvent { } } +#[derive(Debug)] +pub enum FullscreenState { + On, + Off, + Toggle, +} + +impl From for FullscreenState { + fn from(value: bool) -> Self { + match value { + true => Self::On, + false => Self::Off, + } + } +} + #[derive(Debug)] pub struct FullscreenEvent { - window: Window, - new_fullscreen: bool, + pub window: Window, + pub state: FullscreenState, } impl FullscreenEvent { - pub fn new(window: Window, new_fullscreen: bool) -> Self { - Self { - window, - new_fullscreen, - } + pub fn new(window: Window, state: FullscreenState) -> Self { + Self { window, state } } } diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 87d4f85..22ee3de 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -1,5 +1,5 @@ use log::{error, warn}; -use std::{ffi::CString, rc::Rc}; +use std::{ffi::CString, mem::MaybeUninit, rc::Rc}; use thiserror::Error; @@ -17,9 +17,9 @@ use self::keysym::{ use super::{ keycodes::VirtualKeyCode, window_event::{ - ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, KeyEvent, - KeyOrMouseBind, KeyState, MapEvent, ModifierState, MotionEvent, Point, - UnmapEvent, WindowEvent, + ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, FullscreenEvent, + FullscreenState, KeyEvent, KeyOrMouseBind, KeyState, MapEvent, + ModifierState, MotionEvent, Point, UnmapEvent, WindowEvent, }, WindowServerBackend, }; @@ -285,6 +285,53 @@ impl XLib { )) }) } + xlib::PropertyNotify => { + let ev = unsafe { &event.property }; + + (ev.atom == self.atoms.net_wm_window_type) + .then(|| { + (self.get_atom_property( + ev.window, + self.atoms.net_wm_state, + ) == Some(self.atoms.net_wm_state_fullscreen)) + .then(|| { + XLibWindowEvent::FullscreenEvent( + FullscreenEvent::new( + ev.window, + FullscreenState::On, + ), + ) + }) + }) + .flatten() + } + xlib::ClientMessage => { + let ev = unsafe { &event.client_message }; + + (ev.message_type == self.atoms.net_wm_state) + .then(|| { + let data = ev.data.as_longs(); + (data[1] as u64 == self.atoms.net_wm_state_fullscreen + || data[2] as u64 + == self.atoms.net_wm_state_fullscreen) + .then(|| { + XLibWindowEvent::FullscreenEvent( + FullscreenEvent::new( + ev.window, + match data[0] /* as u64 */ { + 0 => FullscreenState::Off, + 1 => FullscreenState::On, + 2 => FullscreenState::Toggle, + _ => { + unreachable!() + } + }, + ), + ) + }) + }) + .flatten() + } _ => None, } } @@ -308,6 +355,37 @@ impl XLib { } } + fn get_atom_property( + &self, + window: xlib::Window, + atom: xlib::Atom, + ) -> Option { + let mut di = 0; + let mut dl0 = 0; + let mut dl1 = 0; + let mut da = 0; + + let mut atom_out = MaybeUninit::::zeroed(); + + unsafe { + (xlib::XGetWindowProperty( + self.dpy(), + window, + atom, + 0, + std::mem::size_of::() as i64, + 0, + xlib::XA_ATOM, + &mut da, + &mut di, + &mut dl0, + &mut dl1, + atom_out.as_mut_ptr() as *mut _, + ) != 0) + .then(|| atom_out.assume_init()) + } + } + fn check_for_protocol( &self, window: xlib::Window, diff --git a/src/state.rs b/src/state.rs index 6e545f3..4e1bdd0 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,9 +8,9 @@ use crate::{ backends::{ keycodes::{MouseButton, VirtualKeyCode}, window_event::{ - ButtonEvent, ConfigureEvent, KeyBind, KeyEvent, KeyState, MapEvent, - ModifierKey, ModifierState, MotionEvent, MouseBind, Point, - WindowEvent, + ButtonEvent, ConfigureEvent, FullscreenEvent, KeyBind, KeyEvent, + KeyState, MapEvent, ModifierKey, ModifierState, MotionEvent, + MouseBind, Point, WindowEvent, }, xlib::XLib, WindowServerBackend, @@ -464,6 +464,12 @@ where // None => self.xlib.configure_window(event), // } } + WindowEvent::FullscreenEvent(FullscreenEvent { + window, + state, + }) => { + info!("FullscreenEvent for window {}: {:?}", window, state); + } // i dont think i actually have to handle destroy notify events. // every window should be unmapped regardless From c9b926f5badc3bc638498c7395ee43c043f27610 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 20:21:21 +0100 Subject: [PATCH 2/5] moved `Point` to module `utils` and also added `Size` both types depend on `num-traits` --- Cargo.toml | 1 + src/backends/window_event.rs | 37 +--------- src/clients.rs | 6 +- src/util.rs | 133 +++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 30b0998..c7534c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,4 @@ bitflags = "1.3.2" derivative = "2.2.0" serde = { version = "1.0", features = ["derive"] } toml = "0.5" +num-traits = "0.2.14" diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index 507f0af..92d1e95 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -129,42 +129,7 @@ impl KeyEvent { } } -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] -pub struct Point -where - I: Copy + Clone + PartialEq + PartialOrd, -{ - pub x: I, - pub y: I, -} -impl From<(I, I)> for Point -where - I: Copy + Clone + PartialEq + PartialOrd, -{ - fn from(value: (I, I)) -> Self { - Self::from_tuple(value) - } -} - -impl Point -where - I: Copy + Clone + PartialEq + PartialOrd, -{ - pub fn new(x: I, y: I) -> Self { - Self { x, y } - } - - pub fn from_tuple(tuple: (I, I)) -> Self { - Self { - x: tuple.0, - y: tuple.1, - } - } - - pub fn as_tuple(&self) -> (I, I) { - (self.x, self.y) - } -} +pub use crate::util::Point; #[derive(Debug)] pub struct ButtonEvent { diff --git a/src/clients.rs b/src/clients.rs index e641d8a..a01f22e 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -2,10 +2,10 @@ use std::num::NonZeroI32; use std::{ops::Rem, usize}; use indexmap::IndexMap; -use log::{error, info}; +use log::error; -use crate::backends::window_event::Point; use crate::util::BuildIdentityHasher; +use crate::util::{Point, Size}; mod client { use std::hash::{Hash, Hasher}; @@ -538,7 +538,7 @@ impl ClientState { let (new, old) = self.focus_client_inner(key); if !(new.is_vacant() && old.is_vacant()) { - info!("Swapping focus: new({:?}) old({:?})", new, old); + //info!("Swapping focus: new({:?}) old({:?})", new, old); } (new, old) diff --git a/src/util.rs b/src/util.rs index 4389ed7..75f9d78 100644 --- a/src/util.rs +++ b/src/util.rs @@ -22,3 +22,136 @@ impl Hasher for IdentityHasher { } pub type BuildIdentityHasher = BuildHasherDefault; + +pub use point::Point; +pub use size::Size; + +mod size { + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + pub width: I, + pub height: I, + } + + impl Default for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn default() -> Self { + Self { + width: I::zero(), + height: I::zero(), + } + } + } + + impl From<(I, I)> for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn from(value: (I, I)) -> Self { + Self::from_tuple(value) + } + } + + impl From> for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn from(value: super::point::Point) -> Self { + Self::new(value.x, value.y) + } + } + + impl Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + pub fn new(width: I, height: I) -> Self { + Self { width, height } + } + + pub fn from_tuple(tuple: (I, I)) -> Self { + Self::new(tuple.0, tuple.1) + } + + pub fn as_tuple(&self) -> (I, I) { + (self.width, self.height) + } + + pub fn map(self, f: F) -> Self + where + F: FnOnce(I, I) -> Self, + { + f(self.width, self.height) + } + } +} + +mod point { + #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] + pub struct Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + pub x: I, + pub y: I, + } + + impl Default for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn default() -> Self { + Self { + x: I::zero(), + y: I::zero(), + } + } + } + + impl From<(I, I)> for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn from(value: (I, I)) -> Self { + Self::from_tuple(value) + } + } + + impl From> for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn from(value: super::size::Size) -> Self { + Self::new(value.width, value.height) + } + } + + impl Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + pub fn new(x: I, y: I) -> Self { + Self { x, y } + } + + pub fn from_tuple(tuple: (I, I)) -> Self { + Self::new(tuple.0, tuple.1) + } + + pub fn as_tuple(&self) -> (I, I) { + (self.x, self.y) + } + + pub fn map(self, f: F) -> T + where + F: FnOnce(I, I) -> T, + { + f(self.x, self.y) + } + } +} From 5dbfa6fbcfb29524ad91a68a176bc3db74569ddc Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 20:22:21 +0100 Subject: [PATCH 3/5] added fullscreen mechanics --- src/clients.rs | 173 ++++++++++++++++++++++++++++++++++++++----------- src/state.rs | 26 +++++++- 2 files changed, 159 insertions(+), 40 deletions(-) diff --git a/src/clients.rs b/src/clients.rs index a01f22e..e806c08 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -1,4 +1,3 @@ -use std::num::NonZeroI32; use std::{ops::Rem, usize}; use indexmap::IndexMap; @@ -20,6 +19,7 @@ mod client { pub(crate) size: Point, pub(crate) position: Point, pub(crate) transient_for: Option, + pub(crate) fullscreen: bool, } impl Default for Client { @@ -29,6 +29,7 @@ mod client { size: (100, 100).into(), position: (0, 0).into(), transient_for: None, + fullscreen: false, } } } @@ -44,7 +45,7 @@ mod client { window, size, position, - transient_for: None, + ..Self::default() } } @@ -68,6 +69,27 @@ mod client { } } + /// toggles the clients fullscreen flag. + /// returns `true` if the client is now fullscreen. + pub fn toggle_fullscreen(&mut self) -> bool { + self.fullscreen = !self.fullscreen; + + self.is_fullscreen() + } + + pub fn set_fullscreen(&mut self, fullscreen: bool) -> bool { + if self.fullscreen == fullscreen { + false + } else { + self.fullscreen = fullscreen; + true + } + } + + pub fn is_fullscreen(&self) -> bool { + self.fullscreen + } + pub fn is_transient(&self) -> bool { self.transient_for.is_some() } @@ -408,6 +430,43 @@ impl ClientState { self.arrange_virtual_screen(); } + pub fn set_fullscreen(&mut self, key: &K, fullscreen: bool) -> bool + where + K: ClientKey, + { + self.get(key) + .into_option() + .map(|client| client.is_fullscreen() != fullscreen) + .unwrap_or(false) + .then(|| self.toggle_fullscreen(key)) + .unwrap_or(false) + } + + pub fn toggle_fullscreen(&mut self, key: &K) -> bool + where + K: ClientKey, + { + if self.inner_toggle_fullscreen(key) { + self.arrange_virtual_screen(); + true + } else { + false + } + } + + fn inner_toggle_fullscreen(&mut self, key: &K) -> bool + where + K: ClientKey, + { + self.get_mut(key) + .into_option() + .map(|client| { + client.toggle_fullscreen(); + true + }) + .unwrap_or(false) + } + /** Sets a tiled client to floating and returns true, does nothing for a floating client and returns false. If this function returns `true` you have to call `arrange_clients` after. @@ -635,49 +694,87 @@ impl ClientState { let vs = self.virtual_screens.get_mut_current(); // if aux is empty -> width : width / 2 - let (master_width, aux_width) = { - let effective_width = width - gap * 2; + let vs_width = width - gap * 2; - let master_size = if vs.aux.is_empty() { + let master_position = Point::new(0, 0); + let master_window_size = { + let factor = if vs.aux.is_empty() { 1.0 } else { self.master_size / 2.0 }; - let master_width = (effective_width as f32 * master_size) as i32; - let aux_width = effective_width - master_width; + let width = (vs_width as f32 * factor) as i32; - (master_width, aux_width) + // make sure we dont devide by 0 + // height is max height / number of clients in the stack + let height = match vs.master.len() as i32 { + 0 => 1, + n => (height - gap * 2) / n, + }; + + Size::new(width, height) }; - // make sure we dont devide by 0 - // height is max height / number of clients in the stack - let master_height = (height - gap * 2) - / match NonZeroI32::new(vs.master.len() as i32) { - Some(i) => i.get(), - None => 1, + let aux_position = Point::new(master_window_size.width, 0); + let aux_window_size = { + let width = vs_width - master_window_size.width; + + // make sure we dont devide by 0 + // height is max height / number of clients in the stack + let height = match vs.aux.len() as i32 { + 0 => 1, + n => (height - gap * 2) / n, }; - // height is max height / number of clients in the stack - let aux_height = (height - gap * 2) - / match NonZeroI32::new(vs.aux.len() as i32) { - Some(i) => i.get(), - None => 1, - }; + Size::new(width, height) + }; + + fn calculate_window_dimensions( + screen_size: Size, + stack_size: Size, + stack_position: Point, + fullscreen: bool, + nth: i32, + gap: i32, + border: i32, + ) -> (Size, Point) { + if fullscreen { + let size = Size::new( + screen_size.width - border * 2, + screen_size.height - border * 2, + ); + let pos = Point::new(0, 0); + (size, pos) + } else { + let size = Size::new( + stack_size.width - gap * 2 - border * 2, + stack_size.height - gap * 2 - border * 2, + ); + let pos = Point::new( + stack_position.x + gap * 2, + stack_position.y + stack_size.height * nth + gap * 2, + ); + (size, pos) + } + } // Master for (i, key) in vs.master.iter().enumerate() { - let size = ( - master_width - gap * 2 - self.border_size * 2, - master_height - gap * 2 - self.border_size * 2, - ); - - let position = (gap * 2, master_height * i as i32 + gap * 2); - if let Some(client) = self.clients.get_mut(key) { + let (size, position) = calculate_window_dimensions( + self.screen_size.into(), + master_window_size, + master_position, + client.is_fullscreen(), + i as i32, + gap, + self.border_size, + ); + *client = Client { size: size.into(), - position: position.into(), + position, ..*client }; } @@ -685,18 +782,20 @@ impl ClientState { // Aux for (i, key) in vs.aux.iter().enumerate() { - let size = ( - aux_width - gap * 2 - self.border_size * 2, - aux_height - gap * 2 - self.border_size * 2, - ); - - let position = - (master_width + gap * 2, aux_height * i as i32 + gap * 2); - if let Some(client) = self.clients.get_mut(key) { + let (size, position) = calculate_window_dimensions( + self.screen_size.into(), + aux_window_size, + aux_position, + client.is_fullscreen(), + i as i32, + gap, + self.border_size, + ); + *client = Client { size: size.into(), - position: position.into(), + position, ..*client }; } diff --git a/src/state.rs b/src/state.rs index 4e1bdd0..993d0fb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,9 +8,9 @@ use crate::{ backends::{ keycodes::{MouseButton, VirtualKeyCode}, window_event::{ - ButtonEvent, ConfigureEvent, FullscreenEvent, KeyBind, KeyEvent, - KeyState, MapEvent, ModifierKey, ModifierState, MotionEvent, - MouseBind, Point, WindowEvent, + ButtonEvent, ConfigureEvent, FullscreenEvent, FullscreenState, + KeyBind, KeyEvent, KeyState, MapEvent, ModifierKey, ModifierState, + MotionEvent, MouseBind, Point, WindowEvent, }, xlib::XLib, WindowServerBackend, @@ -469,6 +469,20 @@ where state, }) => { info!("FullscreenEvent for window {}: {:?}", window, state); + + if match state { + FullscreenState::On => { + self.clients.set_fullscreen(&window, true) + } + FullscreenState::Off => { + self.clients.set_fullscreen(&window, false) + } + FullscreenState::Toggle => { + self.clients.toggle_fullscreen(&window) + } + } { + self.arrange_clients(); + } } // i dont think i actually have to handle destroy notify events. @@ -658,6 +672,12 @@ where self.clients .iter_transient() .for_each(|(_, c)| self.backend.raise_window(c.window)); + + //raise fullscreen windows + self.clients + .iter_current_screen() + .filter(|(_, c)| c.is_fullscreen()) + .for_each(|(_, c)| self.backend.raise_window(c.window)); } fn arrange_clients(&mut self) { From c3f3ad7203b892fc6ac5eea2bdeee5f73f76f7e9 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 20:43:02 +0100 Subject: [PATCH 4/5] rebase/corrected all cases of `Point` that were sizes --- src/backends/traits.rs | 14 +++--- src/backends/window_event.rs | 11 +++-- src/backends/xlib/mod.rs | 24 ++++++----- src/clients.rs | 17 ++++---- src/state.rs | 41 ++++-------------- src/util.rs | 82 ++++++++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 66 deletions(-) diff --git a/src/backends/traits.rs b/src/backends/traits.rs index 603a3b8..1698c69 100644 --- a/src/backends/traits.rs +++ b/src/backends/traits.rs @@ -1,7 +1,5 @@ -use super::{ - window_event, - window_event::{KeyOrMouseBind, Point}, -}; +use super::window_event::{self, KeyOrMouseBind}; +use crate::util::{Point, Size}; pub trait WindowServerBackend { type Window; @@ -26,13 +24,13 @@ pub trait WindowServerBackend { fn configure_window( &self, window: Self::Window, - new_size: Option>, + new_size: Option>, new_pos: Option>, new_border: Option, ); - fn screen_size(&self) -> Point; - fn get_window_size(&self, window: Self::Window) -> Option>; + fn screen_size(&self) -> Size; + fn get_window_size(&self, window: Self::Window) -> Option>; fn grab_cursor(&self); fn ungrab_cursor(&self); @@ -43,7 +41,7 @@ pub trait WindowServerBackend { fn set_active_window_border_color(&mut self, color_name: &str); fn set_inactive_window_border_color(&mut self, color_name: &str); - fn resize_window(&self, window: Self::Window, new_size: Point) { + fn resize_window(&self, window: Self::Window, new_size: Size) { self.configure_window(window, Some(new_size), None, None); } diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index 92d1e95..44ddb1e 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use super::keycodes::{KeyOrButton, MouseButton, VirtualKeyCode}; +use crate::util::{Point, Size}; use bitflags::bitflags; #[derive(Debug)] @@ -129,8 +130,6 @@ impl KeyEvent { } } -pub use crate::util::Point; - #[derive(Debug)] pub struct ButtonEvent { pub window: Window, @@ -200,11 +199,11 @@ impl DestroyEvent { pub struct CreateEvent { pub window: Window, pub position: Point, - pub size: Point, + pub size: Size, } impl CreateEvent { - pub fn new(window: Window, position: Point, size: Point) -> Self { + pub fn new(window: Window, position: Point, size: Size) -> Self { Self { window, position, @@ -217,11 +216,11 @@ impl CreateEvent { pub struct ConfigureEvent { pub window: Window, pub position: Point, - pub size: Point, + pub size: Size, } impl ConfigureEvent { - pub fn new(window: Window, position: Point, size: Point) -> Self { + pub fn new(window: Window, position: Point, size: Size) -> Self { Self { window, position, diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 22ee3de..4d222d1 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -1,4 +1,5 @@ use log::{error, warn}; +use num_traits::Zero; use std::{ffi::CString, mem::MaybeUninit, rc::Rc}; use thiserror::Error; @@ -19,10 +20,11 @@ use super::{ window_event::{ ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, FullscreenEvent, FullscreenState, KeyEvent, KeyOrMouseBind, KeyState, MapEvent, - ModifierState, MotionEvent, Point, UnmapEvent, WindowEvent, + ModifierState, MotionEvent, UnmapEvent, WindowEvent, }, WindowServerBackend, }; +use crate::util::{Point, Size}; pub mod color; pub mod keysym; @@ -804,8 +806,8 @@ impl WindowServerBackend for XLib { } fn hide_window(&self, window: Self::Window) { - let screen_size = self.screen_size(); - self.move_window(window, screen_size); + let screen_size = self.screen_size() + Size::new(100, 100); + self.move_window(window, screen_size.into()); } fn kill_window(&self, window: Self::Window) { @@ -831,17 +833,17 @@ impl WindowServerBackend for XLib { fn configure_window( &self, window: Self::Window, - new_size: Option>, - new_pos: Option>, + new_size: Option>, + new_pos: Option>, new_border: Option, ) { - let position = new_pos.unwrap_or(Point::new(0, 0)); - let size = new_size.unwrap_or(Point::new(0, 0)); + let position = new_pos.unwrap_or(Point::zero()); + let size = new_size.unwrap_or(Size::zero()); let mut wc = xlib::XWindowChanges { x: position.x, y: position.y, - width: size.x, - height: size.y, + width: size.width, + height: size.height, border_width: new_border.unwrap_or(0), sibling: 0, stack_mode: 0, @@ -867,7 +869,7 @@ impl WindowServerBackend for XLib { } } - fn screen_size(&self) -> Point { + fn screen_size(&self) -> Size { unsafe { let mut wa = std::mem::MaybeUninit::::zeroed(); @@ -880,7 +882,7 @@ impl WindowServerBackend for XLib { } } - fn get_window_size(&self, window: Self::Window) -> Option> { + fn get_window_size(&self, window: Self::Window) -> Option> { self.get_window_attributes(window) .map(|wa| (wa.width, wa.height).into()) } diff --git a/src/clients.rs b/src/clients.rs index e806c08..6676d57 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -9,14 +9,13 @@ use crate::util::{Point, Size}; mod client { use std::hash::{Hash, Hasher}; + use crate::util::{Point, Size}; use x11::xlib::Window; - use crate::backends::window_event::Point; - #[derive(Clone, Debug)] pub struct Client { pub(crate) window: Window, - pub(crate) size: Point, + pub(crate) size: Size, pub(crate) position: Point, pub(crate) transient_for: Option, pub(crate) fullscreen: bool, @@ -38,7 +37,7 @@ mod client { #[allow(dead_code)] pub fn new( window: Window, - size: Point, + size: Size, position: Point, ) -> Self { Self { @@ -51,7 +50,7 @@ mod client { pub fn new_transient( window: Window, - size: Point, + size: Size, transient: Window, ) -> Self { Self { @@ -165,7 +164,7 @@ pub struct ClientState { pub(self) virtual_screens: VirtualScreenStore, pub(self) gap: i32, - pub(self) screen_size: Point, + pub(self) screen_size: Size, pub(self) master_size: f32, border_size: i32, } @@ -214,7 +213,7 @@ impl ClientState { } } - pub fn with_screen_size(self, screen_size: Point) -> Self { + pub fn with_screen_size(self, screen_size: Size) -> Self { Self { screen_size, ..self @@ -248,9 +247,9 @@ impl ClientState { client.position = { ( transient.position.x - + (transient.size.x - client.size.x) / 2, + + (transient.size.width - client.size.width) / 2, transient.position.y - + (transient.size.y - client.size.y) / 2, + + (transient.size.height - client.size.height) / 2, ) .into() }; diff --git a/src/state.rs b/src/state.rs index 993d0fb..48c45c5 100644 --- a/src/state.rs +++ b/src/state.rs @@ -4,13 +4,13 @@ use log::{error, info}; use x11::xlib::{self, Window}; +use crate::util::{Point, Size}; use crate::{ backends::{ keycodes::{MouseButton, VirtualKeyCode}, window_event::{ - ButtonEvent, ConfigureEvent, FullscreenEvent, FullscreenState, - KeyBind, KeyEvent, KeyState, MapEvent, ModifierKey, ModifierState, - MotionEvent, MouseBind, Point, WindowEvent, + ButtonEvent, ConfigureEvent, KeyBind, KeyEvent, KeyState, MapEvent, + ModifierKey, ModifierState, MotionEvent, MouseBind, WindowEvent, }, xlib::XLib, WindowServerBackend, @@ -105,7 +105,7 @@ struct MoveInfoInner { struct ResizeInfoInner { window: Window, starting_cursor_pos: Point, - starting_window_size: Point, + starting_window_size: Size, } use derivative::*; @@ -464,26 +464,6 @@ where // None => self.xlib.configure_window(event), // } } - WindowEvent::FullscreenEvent(FullscreenEvent { - window, - state, - }) => { - info!("FullscreenEvent for window {}: {:?}", window, state); - - if match state { - FullscreenState::On => { - self.clients.set_fullscreen(&window, true) - } - FullscreenState::Off => { - self.clients.set_fullscreen(&window, false) - } - FullscreenState::Toggle => { - self.clients.toggle_fullscreen(&window) - } - } { - self.arrange_clients(); - } - } // i dont think i actually have to handle destroy notify events. // every window should be unmapped regardless @@ -782,12 +762,7 @@ where let client = self.clients.get(&window).unwrap(); - let corner_pos = { - ( - client.position.x + client.size.x, - client.position.y + client.size.y, - ) - }; + let corner_pos = client.position + client.size.into(); self.backend.move_cursor(None, corner_pos.into()); self.backend.grab_cursor(); @@ -846,8 +821,10 @@ where { let size = &mut client.size; - size.x = std::cmp::max(1, info.starting_window_size.x + x); - size.y = std::cmp::max(1, info.starting_window_size.y + y); + size.width = + std::cmp::max(1, info.starting_window_size.width + x); + size.height = + std::cmp::max(1, info.starting_window_size.height + y); self.backend.resize_window(client.window, client.size); } diff --git a/src/util.rs b/src/util.rs index 75f9d78..bfc5fc2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -36,6 +36,47 @@ mod size { pub height: I, } + impl std::ops::Add for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + width: self.width + rhs.width, + height: self.height + rhs.height, + } + } + } + + impl std::ops::Sub for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + width: self.width - rhs.width, + height: self.height - rhs.height, + } + } + } + + impl num_traits::Zero for Size + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn zero() -> Self { + Self::default() + } + + fn is_zero(&self) -> bool { + self.width == I::zero() && self.height == I::zero() + } + } + impl Default for Size where I: num_traits::PrimInt + num_traits::Zero, @@ -101,6 +142,47 @@ mod point { pub y: I, } + impl std::ops::Add for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } + } + + impl std::ops::Sub for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } + } + + impl num_traits::Zero for Point + where + I: num_traits::PrimInt + num_traits::Zero, + { + fn zero() -> Self { + Self::default() + } + + fn is_zero(&self) -> bool { + self.x == I::zero() && self.y == I::zero() + } + } + impl Default for Point where I: num_traits::PrimInt + num_traits::Zero, From b49bfed1f0df8be990cc68b21484215a46fcc432 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 2 Dec 2021 21:36:51 +0100 Subject: [PATCH 5/5] removed debug logging --- src/state.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/state.rs b/src/state.rs index 993d0fb..bd79771 100644 --- a/src/state.rs +++ b/src/state.rs @@ -468,8 +468,6 @@ where window, state, }) => { - info!("FullscreenEvent for window {}: {:?}", window, state); - if match state { FullscreenState::On => { self.clients.set_fullscreen(&window, true)