wzrd

An ICCCM & EWMH compliant X11 reparenting, dynamic window manager, written in Rust
git clone git://git.deurzen.net/wzrd
Log | Files | Refs | LICENSE

commit 5405ebc2e12856ed1fef241aad3c076a8ba76e43
parent 1b8584dd1843e49379ebff746b082fb3c168e968
Author: deurzen <m.deurzen@tum.de>
Date:   Mon, 15 Mar 2021 07:07:05 +0100

implements margin and gap_size layout adjustment

Diffstat:
Msrc/core/model.rs | 34+++++++++++++++++++++-------------
Msrc/core/workspace.rs | 4++--
Msrc/core/zone.rs | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 86 insertions(+), 38 deletions(-)

diff --git a/src/core/model.rs b/src/core/model.rs @@ -163,11 +163,15 @@ impl<'a> Model<'a> { .collect::<Vec<&(winsys::input::MouseEventKey, winsys::input::MouseShortcut)>>(), ); - model.conn.top_level_windows().into_iter().for_each(|window| { - if model.conn.must_manage_window(window) { - model.manage(window, false); - } - }); + model + .conn + .top_level_windows() + .into_iter() + .for_each(|window| { + if model.conn.must_manage_window(window) { + model.manage(window, false); + } + }); if cfg!(not(debug_assertions)) { let nonblocking = concat!("$HOME/.config/", WM_NAME!(), "/nonblocking_autostart &"); @@ -395,14 +399,15 @@ impl<'a> Model<'a> { }) }); - let (free, regular): (Vec<Window>, Vec<Window>) = regular.into_iter().partition(|&window| { - self.client(window).map_or(true, |client| { - let id = client.zone(); - let zone = self.zone_manager.zone(id); + let (free, regular): (Vec<Window>, Vec<Window>) = + regular.into_iter().partition(|&window| { + self.client(window).map_or(true, |client| { + let id = client.zone(); + let zone = self.zone_manager.zone(id); - zone.method() == PlacementMethod::Free || client.is_free() - }) - }); + zone.method() == PlacementMethod::Free || client.is_free() + }) + }); let above = self.stack.layer_windows(StackLayer::Above); let notification = self.stack.layer_windows(StackLayer::Notification); @@ -482,7 +487,10 @@ impl<'a> Model<'a> { let mut client_list: Vec<&Client> = self.client_map.values().collect::<Vec<&Client>>(); client_list.sort_by_key(|&a| a.managed_since()); - let client_list: Vec<Window> = client_list.into_iter().map(|client| client.window()).collect(); + let client_list: Vec<Window> = client_list + .into_iter() + .map(|client| client.window()) + .collect(); self.conn.update_client_list(&client_list); let stack_windows: Vec<Window> = stack diff --git a/src/core/workspace.rs b/src/core/workspace.rs @@ -456,8 +456,8 @@ impl Workspace { if let Some(&id) = self.zones.active_element() { if let Some(data) = zone_manager.active_data_mut(id) { data.gap_size = match change { - Change::Inc => std::cmp::min(data.main_count + delta, MAX_GAP_SIZE), - Change::Dec => std::cmp::max(data.main_count as i32 - delta as i32, 0) as u32, + Change::Inc => std::cmp::min(data.gap_size + delta, MAX_GAP_SIZE), + Change::Dec => std::cmp::max(data.gap_size as i32 - delta as i32, 0) as u32, }; } } diff --git a/src/core/zone.rs b/src/core/zone.rs @@ -611,12 +611,38 @@ impl Layout { self.prev_kind = self.kind; self.kind = kind; } + + fn adjust_for_margin( + region: Region, + extents: &Extents, + ) -> Region { + Region { + pos: Pos { + x: region.pos.x + extents.left as i32, + y: region.pos.y + extents.top as i32, + }, + dim: Dim { + w: region.dim.w - extents.left - extents.right, + h: region.dim.h - extents.top - extents.bottom, + }, + } + } + + fn adjust_for_gap_size( + region: &mut Region, + gap_size: u32, + ) { + region.pos.x += gap_size as i32; + region.pos.y += gap_size as i32; + region.dim.w -= 2 * gap_size; + region.dim.h -= 2 * gap_size; + } } trait Apply { fn apply( &self, - region: &Region, + region: Region, active_map: Vec<bool>, ) -> (PlacementMethod, Vec<(Disposition, bool)>); } @@ -624,12 +650,33 @@ trait Apply { impl Apply for Layout { fn apply( &self, - region: &Region, + region: Region, active_map: Vec<bool>, ) -> (PlacementMethod, Vec<(Disposition, bool)>) { + let method = self.kind.config().method; + let data = self.get_data(); + + let region = if method == PlacementMethod::Free { + region + } else { + Self::adjust_for_margin(region, &data.margin) + }; + ( - self.kind.config().method, - (self.kind.func())(region, &self.data.get(&self.kind).unwrap(), active_map), + method, + (self.kind.func())(&region, &data, active_map) + .into_iter() + .map(|(mut disposition, is_visible)| { + match disposition { + Disposition::Unchanged => {}, + Disposition::Changed(ref mut region, _) => { + Self::adjust_for_gap_size(region, data.gap_size); + }, + } + + (disposition, is_visible) + }) + .collect(), ) } } @@ -902,21 +949,16 @@ impl ZoneManager { pub fn next_cycle( &self, - id: ZoneId, + mut id: ZoneId, ) -> Option<ZoneId> { - let mut next = self.parent_id(id); - - while next.is_some() { - let next_id = next.unwrap(); + while let Some(next_id) = self.parent_id(id) { let zone = self.zone_map.get(&next_id).unwrap(); match zone.content { ZoneContent::Tab(_) | ZoneContent::Layout(..) => { - return next; - }, - _ => { - next = self.parent_id(next_id); + return Some(next_id); }, + _ => id = next_id, } } @@ -1063,7 +1105,7 @@ impl ZoneManager { .collect(); let (method, application) = layout.apply( - &region, + region, zones.iter().map(|id| Some(id) == active_element).collect(), ); @@ -1096,15 +1138,13 @@ impl ZoneManager { }, ); - subplacements.into_iter().for_each(|(id, region, decoration)| { - placements.extend(self.arrange_subzones( - id, - region, - decoration, - method, - to_ignore, - )); - }); + subplacements + .into_iter() + .for_each(|(id, region, decoration)| { + placements.extend( + self.arrange_subzones(id, region, decoration, method, to_ignore), + ); + }); placements },