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 c807c214a39e1e3d41c1a1380f7edcca5e23cfff
parent 23a18b11182e285a1847701bdac1681f27f68f60
Author: deurzen <m.deurzen@tum.de>
Date:   Wed, 10 Mar 2021 00:45:48 +0100

sets up layout handling refactoring base

Diffstat:
Dsrc/core/layout.rs | 1215-------------------------------------------------------------------------------
Msrc/core/main.rs | 20+++++++++-----------
Msrc/core/model.rs | 163++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/core/workspace.rs | 180+++++++++----------------------------------------------------------------------
Msrc/core/zone.rs | 1-
5 files changed, 124 insertions(+), 1455 deletions(-)

diff --git a/src/core/layout.rs b/src/core/layout.rs @@ -1,1215 +0,0 @@ -use crate::client::Client; -use crate::common::Change; -use crate::common::Ident; -use crate::common::Identify; -use crate::common::Placement; -use crate::common::FREE_EXTENTS; -use crate::common::MIN_WINDOW_DIM; -use crate::util::Util; - -use winsys::common::Dim; -use winsys::common::Edge; -use winsys::common::Extents; -use winsys::common::Padding; -use winsys::common::Pos; -use winsys::common::Region; -use winsys::common::Window; - -use std::default::Default; - -pub type LayoutFn = - fn(&[&Client], Option<Window>, &Region, &LayoutData) -> Vec<Placement>; - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum LayoutMethod { - /// Does not inhibit free placement of clients - Free, - /// Arranges clients along a predefined layout - Tile, - /// Semi-adjustable tree-based layout - Tree, -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum LayoutKind { - Center, - Float, - Monocle, - Paper, - PaperCenter, - SStack, - SingleFloat, - Stack, -} - -pub struct LayoutFactory {} - -impl LayoutFactory { - pub fn create_layout(kind: LayoutKind) -> Layout { - match kind { - LayoutKind::Center => CenterLayout::build(), - LayoutKind::Float => FloatLayout::build(), - LayoutKind::Monocle => MonocleLayout::build(), - LayoutKind::Paper => PaperLayout::build(), - LayoutKind::PaperCenter => PaperCenterLayout::build(), - LayoutKind::SStack => SStackLayout::build(), - LayoutKind::SingleFloat => SingleFloatLayout::build(), - LayoutKind::Stack => StackLayout::build(), - } - } -} - -pub trait LayoutApply { - fn arrange( - &self, - clients: &[&Client], - focus: Option<Window>, - screen: &Region, - ) -> Vec<Placement>; -} - -#[derive(Clone)] -pub struct Layout { - pub kind: LayoutKind, - pub symbol: char, - pub name: String, - pub config: LayoutConfig, - data: LayoutData, - default_data: LayoutData, - logic: LayoutFn, -} - -impl Layout { - const MAX_MAIN_COUNT: u32 = 15; - const MAX_GAP_SIZE: u32 = 300; - const MAX_MARGIN: Padding = Padding { - left: 350, - right: 350, - top: 200, - bottom: 200, - }; - - pub fn new( - kind: LayoutKind, - symbol: char, - name: impl Into<String>, - config: LayoutConfig, - data: LayoutData, - logic: LayoutFn, - ) -> Self { - Self { - kind, - symbol, - name: name.into(), - config, - data, - default_data: data, - logic, - } - } - - pub fn change_gap_size( - &mut self, - change: Change, - delta: u32, - ) { - if let LayoutData::Tile(ref mut data) = self.data { - data.gap_size = Util::change_within_range( - 0, - Self::MAX_GAP_SIZE, - data.gap_size, - change, - delta, - ); - } - } - - pub fn reset_gap_size(&mut self) { - match self.data { - LayoutData::Tile(ref mut data) => { - if let LayoutData::Tile(default_data) = self.default_data { - data.gap_size = default_data.gap_size; - } - }, - LayoutData::Tree(ref mut data) => { - if let LayoutData::Tree(default_data) = self.default_data { - data.gap_size = default_data.gap_size; - } - }, - _ => {}, - }; - } - - pub fn main_count(&self) -> Option<u32> { - if let LayoutData::Tile(data) = self.data { - Some(data.main_count) - } else { - None - } - } - - pub fn change_main_count( - &mut self, - change: Change, - ) { - if let LayoutData::Tile(ref mut data) = self.data { - data.main_count = Util::change_within_range( - 0, - Self::MAX_MAIN_COUNT, - data.main_count, - change, - 1, - ); - } - } - - pub fn change_main_factor( - &mut self, - change: Change, - delta: f32, - ) { - if let LayoutData::Tile(ref mut data) = self.data { - match change { - Change::Inc => data.main_factor += delta, - Change::Dec => data.main_factor -= delta, - } - - if data.main_factor < 0.05f32 { - data.main_factor = 0.05f32; - } else if data.main_factor > 0.95f32 { - data.main_factor = 0.95f32; - } - } - } - - pub fn change_margin( - &mut self, - edge: Edge, - change: Change, - delta: u32, - ) { - match self.data { - LayoutData::Tile(ref mut data) => { - if let LayoutData::Tile(default_data) = self.default_data { - if let Some(ref mut margin) = data.margin { - let default_margin = - if let Some(margin) = default_data.margin { - margin - } else { - Padding::default() - }; - - match edge { - Edge::Left => { - margin.left = Util::change_within_range( - default_margin.left, - Self::MAX_MARGIN.left, - margin.left, - change, - delta, - ); - }, - Edge::Right => { - margin.right = Util::change_within_range( - default_margin.right, - Self::MAX_MARGIN.right, - margin.right, - change, - delta, - ); - }, - Edge::Top => { - margin.top = Util::change_within_range( - default_margin.top, - Self::MAX_MARGIN.top, - margin.top, - change, - delta, - ); - }, - Edge::Bottom => { - margin.bottom = Util::change_within_range( - default_margin.bottom, - Self::MAX_MARGIN.bottom, - margin.bottom, - change, - delta, - ); - }, - } - } - } - }, - LayoutData::Tree(ref mut data) => { - if let LayoutData::Tree(default_data) = self.default_data { - if let Some(ref mut margin) = data.margin { - let default_margin = - if let Some(margin) = default_data.margin { - margin - } else { - Padding::default() - }; - - match edge { - Edge::Left => { - margin.left = Util::change_within_range( - default_margin.left, - Self::MAX_MARGIN.left, - margin.left, - change, - delta, - ); - }, - Edge::Right => { - margin.right = Util::change_within_range( - default_margin.right, - Self::MAX_MARGIN.right, - margin.right, - change, - delta, - ); - }, - Edge::Top => { - margin.top = Util::change_within_range( - default_margin.top, - Self::MAX_MARGIN.top, - margin.top, - change, - delta, - ); - }, - Edge::Bottom => { - margin.bottom = Util::change_within_range( - default_margin.bottom, - Self::MAX_MARGIN.bottom, - margin.bottom, - change, - delta, - ); - }, - } - } - } - }, - _ => {}, - }; - } - - pub fn reset_margin(&mut self) { - match self.data { - LayoutData::Tile(ref mut data) => { - if let LayoutData::Tile(default_data) = self.default_data { - data.margin = default_data.margin; - } - }, - LayoutData::Tree(ref mut data) => { - if let LayoutData::Tree(default_data) = self.default_data { - data.margin = default_data.margin; - } - }, - _ => {}, - }; - } - pub fn reset(&mut self) { - self.data = self.default_data; - } - - 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, - }, - } - } - - pub fn adjust_for_padding( - mut placement: Placement, - gap_size: u32, - ) -> Placement { - if let Some(ref mut region) = placement.region { - let padding = 2 * gap_size; - - region.pos.x += gap_size as i32; - region.pos.y += gap_size as i32; - - if region.dim.w >= padding + MIN_WINDOW_DIM.w { - region.dim.w -= padding; - } else { - region.dim.w = MIN_WINDOW_DIM.w; - } - - if region.dim.h >= padding + MIN_WINDOW_DIM.h { - region.dim.h -= padding; - } else { - region.dim.h = MIN_WINDOW_DIM.h; - } - } - - placement - } -} - -impl LayoutApply for Layout { - fn arrange( - &self, - clients: &[&Client], - focus: Option<Window>, - screen: &Region, - ) -> Vec<Placement> { - let screen = Layout::adjust_for_margin( - *screen, - &LayoutData::screen_margin(&self.data), - ); - - (self.logic)(clients, focus, &screen, &self.data) - .iter_mut() - .map(|p| { - Layout::adjust_for_padding( - *p, - if self.config.gap { - LayoutData::gap_size(&self.data) - } else { - 0 - }, - ) - }) - .collect() - } -} - -impl std::cmp::PartialEq<Self> for Layout { - fn eq( - &self, - other: &Self, - ) -> bool { - self.kind == other.kind - && self.symbol == other.symbol - && self.name == other.name - && self.config == other.config - && self.data == other.data - } -} - -impl Identify for Layout { - fn id(&self) -> Ident { - self.kind as Ident - } -} - -#[non_exhaustive] -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct LayoutConfig { - pub method: LayoutMethod, - pub mirrorable: bool, - pub gap: bool, - pub persistent: bool, - pub single: bool, - pub wraps: bool, -} - -impl Default for LayoutConfig { - fn default() -> Self { - Self { - method: LayoutMethod::Free, - mirrorable: false, - gap: false, - persistent: false, - single: false, - wraps: true, - } - } -} - -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum LayoutData { - Free(FreeData), - Tile(TileData), - Tree(TreeData), -} - -impl LayoutData { - fn screen_margin(data: &LayoutData) -> Extents { - let no_margin = Extents { - left: 0, - right: 0, - top: 0, - bottom: 0, - }; - - match data { - LayoutData::Free(_) => no_margin, - LayoutData::Tile(data) => { - if let Some(margin) = data.margin { - margin - } else { - no_margin - } - }, - LayoutData::Tree(data) => { - if let Some(margin) = data.margin { - margin - } else { - no_margin - } - }, - } - } - - fn gap_size(data: &LayoutData) -> u32 { - match data { - LayoutData::Free(_) => 0, - LayoutData::Tile(data) => data.gap_size, - LayoutData::Tree(data) => data.gap_size, - } - } -} - -#[non_exhaustive] -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct FreeData { - pub frame_extents: Option<Extents>, -} - -impl Default for FreeData { - fn default() -> Self { - Self { - frame_extents: Some(FREE_EXTENTS), - } - } -} - -#[non_exhaustive] -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct TileData { - pub main_count: u32, - pub gap_size: u32, - pub main_factor: f32, - pub mirrored: bool, - pub margin: Option<Padding>, - pub frame_extents: Option<Extents>, -} - -impl Default for TileData { - fn default() -> Self { - Self { - main_count: 1, - gap_size: 15, - main_factor: 0.5, - mirrored: false, - margin: Some(Padding { - left: 0, - right: 0, - top: 0, - bottom: 0, - }), - frame_extents: Some(Extents { - left: 0, - right: 0, - top: 3, - bottom: 0, - }), - } - } -} - -impl TileData { - pub fn stack_split<T>( - clients: &[T], - n_main: u32, - ) -> (u32, u32) { - let n = clients.len() as u32; - if n <= n_main { - (n, 0) - } else { - (n_main, n - n_main) - } - } -} - -#[non_exhaustive] -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct TreeData { - pub gap_size: u32, - pub mirrored: bool, - pub margin: Option<Padding>, - pub frame_extents: Option<Extents>, -} - -impl Default for TreeData { - fn default() -> Self { - Self { - gap_size: 15, - mirrored: false, - margin: Some(Padding { - left: 15, - right: 15, - top: 15, - bottom: 15, - }), - frame_extents: Some(Extents { - left: 0, - right: 0, - top: 3, - bottom: 0, - }), - } - } -} - -trait LayoutBuilder { - fn build() -> Layout; -} - -trait LayoutFunc { - fn func( - clients: &[&Client], - focus: Option<Window>, - screen: &Region, - data: &LayoutData, - ) -> Vec<Placement>; -} - -struct FloatLayout {} - -impl LayoutBuilder for FloatLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Free, - mirrorable: false, - gap: false, - persistent: false, - single: false, - wraps: true, - }; - - let data = FreeData::default(); - - Layout { - kind: LayoutKind::Float, - symbol: 'F', - name: "float".into(), - config, - data: LayoutData::Free(data), - default_data: LayoutData::Free(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for FloatLayout { - fn func( - clients: &[&Client], - _focus: Option<Window>, - _screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Free(data) = data { - clients - .iter() - .map(|c| { - Placement::new( - c.window(), - Some(*c.free_region()), - data.frame_extents, - ) - }) - .collect() - } else { - Vec::with_capacity(0) - } - } -} - -struct SingleFloatLayout {} - -impl LayoutBuilder for SingleFloatLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Free, - mirrorable: false, - gap: false, - persistent: true, - single: true, - wraps: true, - }; - - let data = FreeData::default(); - - Layout { - kind: LayoutKind::SingleFloat, - symbol: 'Z', - name: "singlefloat".into(), - config, - data: LayoutData::Free(data), - default_data: LayoutData::Free(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for SingleFloatLayout { - fn func( - clients: &[&Client], - focus: Option<Window>, - _screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Free(data) = data { - if let Some(focus) = focus { - clients - .iter() - .map(|c| { - let window = c.window(); - - if window == focus { - Placement::new( - window, - Some(*c.free_region()), - data.frame_extents, - ) - } else { - Placement::new(window, None, None) - } - }) - .collect() - } else { - Vec::with_capacity(0) - } - } else { - Vec::with_capacity(0) - } - } -} - -struct StackLayout {} - -impl LayoutBuilder for StackLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: true, - gap: true, - persistent: false, - single: false, - wraps: true, - }; - - let data = TileData::default(); - - Layout { - kind: LayoutKind::Stack, - symbol: 'S', - name: "stack".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for StackLayout { - fn func( - clients: &[&Client], - _focus: Option<Window>, - screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Tile(data) = data { - let n = clients.len(); - let (screen_pos, screen_dim) = screen.values(); - - if n == 1 { - return vec![Placement::new( - clients[0].window(), - Some(*screen), - None, - )]; - } - - let (n_main, n_stack) = - TileData::stack_split(&clients, data.main_count); - - let h_stack = if n_stack > 0 { - screen_dim.h / n_stack - } else { - 0 - }; - - let h_main = if n_main > 0 { screen_dim.h / n_main } else { 0 }; - - let split = if data.main_count > 0 { - (screen_dim.w as f32 * data.main_factor) as i32 - } else { - 0 - }; - - clients - .iter() - .enumerate() - .map(|(i, c)| { - let i = i as u32; - - if i < data.main_count { - let w = if n_stack == 0 { - screen_dim.w - } else { - split as u32 - }; - - Placement::new( - c.window(), - Some(Region::new( - screen_pos.x, - screen_pos.y + (i * h_main) as i32, - w, - h_main, - )), - data.frame_extents, - ) - } else { - let sn = (i - data.main_count) as i32; - - let region = Region::new( - screen_pos.x + split, - screen_pos.y + sn * h_stack as i32, - screen_dim.w - split as u32, - h_stack, - ); - - Placement::new( - c.window(), - Some(region), - data.frame_extents, - ) - } - }) - .collect() - } else { - Vec::with_capacity(0) - } - } -} - -struct SStackLayout {} - -impl LayoutBuilder for SStackLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: true, - gap: false, - persistent: false, - single: false, - wraps: true, - }; - - let data = TileData::default(); - - Layout { - kind: LayoutKind::SStack, - symbol: 'T', - name: "sstack".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: StackLayout::func, - } - } -} - -struct MonocleLayout {} - -impl LayoutBuilder for MonocleLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: false, - gap: false, - persistent: false, - single: false, - wraps: true, - }; - - let data = TileData { - main_count: 0, - gap_size: 0, - main_factor: 0f32, - mirrored: false, - frame_extents: None, - ..Default::default() - }; - - Layout { - kind: LayoutKind::Monocle, - symbol: 'M', - name: "monocle".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for MonocleLayout { - fn func( - clients: &[&Client], - _focus: Option<Window>, - screen: &Region, - _data: &LayoutData, - ) -> Vec<Placement> { - let (screen_pos, screen_dim) = screen.values(); - - clients - .iter() - .map(|c| { - Placement::new( - c.window(), - Some(Region::new( - screen_pos.x, - screen_pos.y, - screen_dim.w, - screen_dim.h, - )), - None, - ) - }) - .collect() - } -} - -struct CenterLayout {} - -impl LayoutBuilder for CenterLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: false, - gap: true, - persistent: false, - single: false, - wraps: true, - }; - - let data = TileData { - main_count: 5, - gap_size: 0, - main_factor: 0.40f32, - mirrored: false, - frame_extents: None, - ..Default::default() - }; - - Layout { - kind: LayoutKind::Center, - symbol: '|', - name: "center".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for CenterLayout { - fn func( - clients: &[&Client], - _focus: Option<Window>, - screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Tile(data) = data { - let (screen_pos, screen_dim) = screen.values(); - - clients - .iter() - .map(|c| { - let window = c.window(); - - let w_ratio: f32 = data.main_factor / 0.95; - let h_ratio: f32 = - ((Layout::MAX_MAIN_COUNT + 1) - data.main_count) as f32 - / (Layout::MAX_MAIN_COUNT + 1) as f32; - - Placement::new( - window, - Some( - Region::new( - screen_pos.x, - screen_pos.y, - screen_dim.w, - screen_dim.h, - ) - .from_absolute_inner_center(&Dim { - w: (screen_dim.w as f32 * w_ratio) as u32, - h: (screen_dim.h as f32 * h_ratio) as u32, - }), - ), - None, - ) - }) - .collect() - } else { - Vec::with_capacity(0) - } - } -} - -struct PaperLayout {} - -impl LayoutBuilder for PaperLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: true, - gap: false, - persistent: true, - single: false, - wraps: false, - }; - - let data = TileData::default(); - - Layout { - kind: LayoutKind::Paper, - symbol: ';', - name: "paper".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for PaperLayout { - fn func( - clients: &[&Client], - focus: Option<Window>, - screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Tile(data) = data { - let n = clients.len(); - - if n == 1 { - return vec![Placement::new( - clients[0].window(), - Some(*screen), - None, - )]; - } - - let (screen_pos, screen_dim) = screen.values(); - let min_w = 0.5; - - let cw = (screen_dim.w as f32 - * if data.main_factor > min_w { - data.main_factor - } else { - min_w - }) as u32; - - let step = ((screen_dim.w - cw) as usize / (n - 1)) as i32; - let focus = focus.unwrap(); - let mut after_focus = false; - - clients - .iter() - .enumerate() - .map(|(i, c)| { - let window = c.window(); - if window == focus { - after_focus = true; - - Placement::new( - window, - Some(Region::new( - screen_pos.x + i as i32 * step, - screen_pos.y, - cw, - screen_dim.h, - )), - data.frame_extents, - ) - } else { - let mut x = screen_pos.x + i as i32 * step; - - if after_focus { - x += cw as i32 - step - }; - - Placement::new( - window, - Some(Region::new( - x, - screen_pos.y, - step as u32, - screen_dim.h, - )), - data.frame_extents, - ) - } - }) - .collect() - } else { - Vec::with_capacity(0) - } - } -} - -struct PaperCenterLayout {} - -impl LayoutBuilder for PaperCenterLayout { - fn build() -> Layout { - let config = LayoutConfig { - method: LayoutMethod::Tile, - mirrorable: false, - gap: false, - persistent: true, - single: false, - wraps: false, - }; - - let data = TileData { - main_count: 0, - main_factor: 0.95f32, - gap_size: (Layout::MAX_GAP_SIZE as f32 / 2f32) as u32, - ..Default::default() - }; - - Layout { - kind: LayoutKind::PaperCenter, - symbol: ';', - name: "papercenter".into(), - config, - data: LayoutData::Tile(data), - default_data: LayoutData::Tile(data), - logic: Self::func, - } - } -} - -impl LayoutFunc for PaperCenterLayout { - fn func( - clients: &[&Client], - focus: Option<Window>, - screen: &Region, - data: &LayoutData, - ) -> Vec<Placement> { - if let LayoutData::Tile(data) = data { - let n = clients.len(); - - if n == 1 { - return vec![Placement::new( - clients[0].window(), - Some(*screen), - None, - )]; - } - - let min_w = 0.5; - let max_w = 0.95; - let w_ratio: f32 = data.main_factor / 0.95; - let h_ratio: f32 = ((Layout::MAX_MAIN_COUNT + 1) - data.main_count) - as f32 - / (Layout::MAX_MAIN_COUNT + 1) as f32; - - let screen = Region::new( - screen.pos.x, - screen.pos.y, - screen.dim.w, - screen.dim.h, - ) - .from_absolute_inner_center(&Dim { - w: (screen.dim.w as f32 * w_ratio) as u32, - h: (screen.dim.h as f32 * h_ratio) as u32, - }); - - let (screen_pos, screen_dim) = screen.values(); - - let cw = data.gap_size as f32 / Layout::MAX_GAP_SIZE as f32; - let cw = (screen_dim.w as f32 - * if cw > min_w { - if cw <= max_w { - data.gap_size as f32 / Layout::MAX_GAP_SIZE as f32 - } else { - max_w - } - } else { - min_w - }) as u32; - - let step = (screen_dim.w - cw) / (n - 1) as u32; - let focus = focus.unwrap(); - let mut after_focus = false; - - clients - .iter() - .enumerate() - .map(|(i, c)| { - let window = c.window(); - if window == focus { - after_focus = true; - - Placement::new( - window, - Some(Region::new( - screen_pos.x + i as i32 * step as i32, - screen_pos.y, - cw, - screen_dim.h, - )), - data.frame_extents, - ) - } else { - let mut x = screen_pos.x + (i as i32) * (step as i32); - - if after_focus { - x += cw as i32 - step as i32 - }; - - Placement::new( - window, - Some(Region::new( - x, - screen_pos.y, - step, - screen_dim.h, - )), - data.frame_extents, - ) - } - }) - .collect() - } else { - Vec::with_capacity(0) - } - } -} - -impl std::fmt::Debug for Layout { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - f.debug_struct("Layout") - .field("kind", &self.kind) - .field("symbol", &self.symbol) - .field("name", &self.name) - .field("config", &self.config) - .field("data", &self.data) - .field("logic", &stringify!(&self.logic)) - .finish() - } -} diff --git a/src/core/main.rs b/src/core/main.rs @@ -24,7 +24,6 @@ mod client; mod consume; mod cycle; mod jump; -mod layout; mod model; mod partition; mod rule; @@ -39,7 +38,6 @@ use common::Change; use common::Direction; use jump::JumpCriterium; use jump::MatchMethod; -use layout::LayoutKind; use model::Model; use workspace::ClientSelector; @@ -187,15 +185,15 @@ fn init_bindings() -> (MouseBindings, KeyBindings) { "1-S-comma" => do_internal!(rotate_clients, Direction::Backward), // active workspace layout setters - "1-m" => do_internal!(set_layout, LayoutKind::Monocle), - "1-t" => do_internal!(set_layout, LayoutKind::Stack), - "1-g" => do_internal!(set_layout, LayoutKind::Center), - "1-z" => do_internal!(set_layout, LayoutKind::SingleFloat), - "1-S-f" => do_internal!(set_layout, LayoutKind::Float), - "1-C-S-f" => do_internal!(apply_float_retain_region), - "1-S-t" => do_internal!(set_layout, LayoutKind::SStack), - "1-C-S-p" => do_internal!(set_layout, LayoutKind::Paper), - "1-space" => do_internal!(toggle_layout), + // "1-m" => do_internal!(set_layout, LayoutKind::Monocle), + // "1-t" => do_internal!(set_layout, LayoutKind::Stack), + // "1-g" => do_internal!(set_layout, LayoutKind::Center), + // "1-z" => do_internal!(set_layout, LayoutKind::SingleFloat), + // "1-S-f" => do_internal!(set_layout, LayoutKind::Float), + // "1-C-S-f" => do_internal!(apply_float_retain_region), + // "1-S-t" => do_internal!(set_layout, LayoutKind::SStack), + // "1-C-S-p" => do_internal!(set_layout, LayoutKind::Paper), + // "1-space" => do_internal!(toggle_layout), // active workspace layout-data modifiers "1-plus" => do_internal!(change_gap_size, Change::Inc), diff --git a/src/core/model.rs b/src/core/model.rs @@ -18,8 +18,6 @@ use crate::cycle::InsertPos; use crate::cycle::Selector; use crate::jump::JumpCriterium; use crate::jump::MatchMethod; -use crate::layout::LayoutKind; -use crate::layout::LayoutMethod; use crate::partition::Partition; use crate::rule::Rules; use crate::stack::StackLayer; @@ -320,19 +318,22 @@ impl<'a> Model<'a> { None => return, }; - let layout_config = workspace.layout_config(); + // TODO: zone change let region = self.active_screen().placeable_region(); for placement in workspace.arrange_with_filter(region, &self.client_map, |client| { - Self::is_applyable(client, layout_config.method) + // TODO: zone change + Self::is_applyable(client) }) { let frame = self.frame(placement.window).unwrap(); if placement.region.is_some() { - self.update_client_placement(&placement, layout_config.method); - self.place_client(placement.window, layout_config.method); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(placement.window); self.map_client(frame); } else { @@ -373,15 +374,18 @@ impl<'a> Model<'a> { }) }); - let (regular, free): (Vec<Window>, Vec<Window>) = - if workspace.layout_config().method == LayoutMethod::Free { - (Vec::new(), regular) - } else { - regular.iter().partition(|&window| { - self.client(*window) - .map_or(false, |client| !client.is_free()) - }) - }; + // TODO: zone change + // let (regular, free): (Vec<Window>, Vec<Window>) = + // if workspace.layout_config().method == LayoutMethod::Free { + // (Vec::new(), regular) + // } else { + // regular.iter().partition(|&window| { + // self.client(*window) + // .map_or(false, |client| !client.is_free()) + // }) + // }; + + let (regular, free): (Vec<Window>, Vec<Window>) = (Vec::new(), regular); let above = self.stack.layer_windows(StackLayer::Above); let notification = self.stack.layer_windows(StackLayer::Notification); @@ -919,12 +923,14 @@ impl<'a> Model<'a> { fn is_applyable( client: &Client, - method: LayoutMethod, + // TODO: zone change + // method: LayoutMethod, ) -> bool { - method == LayoutMethod::Free - || !client.is_floating() - && !client.is_disowned() - && client.is_managed() + // TODO: zone change + // method == LayoutMethod::Free + !client.is_floating() + && !client.is_disowned() + && client.is_managed() } fn is_free( @@ -934,14 +940,15 @@ impl<'a> Model<'a> { (!client.is_fullscreen() || client.is_in_window()) && (client.is_floating() || client.is_disowned() - || !client.is_managed() - || self - .workspaces - .get(client.workspace()) - .unwrap() - .layout_config() - .method - == LayoutMethod::Free) + || !client.is_managed()) + // TODO: zone change + // || self + // .workspaces + // .get(client.workspace()) + // .unwrap() + // .layout_config() + // .method + // == LayoutMethod::Free) } fn is_focusable( @@ -1033,24 +1040,28 @@ impl<'a> Model<'a> { fn update_client_placement( &mut self, placement: &Placement, - method: LayoutMethod, + // method: LayoutMethod, ) { let client = self.client_mut(placement.window).unwrap(); client.set_frame_extents(placement.extents); - if let Some(region) = placement.region { - match method { - LayoutMethod::Free => client.set_free_region(&region), - LayoutMethod::Tile => client.set_tile_region(&region), - LayoutMethod::Tree => client.set_tree_region(&region), - }; - } + // LayoutMethod::Free => client.set_free_region(&region), + // LayoutMethod::Tile => client.set_tile_region(&region), + + // TODO: zone change + // if let Some(region) = placement.region { + // match method { + // LayoutMethod::Free => client.set_free_region(&region), + // LayoutMethod::Tile => client.set_tile_region(&region), + // LayoutMethod::Tree => client.set_tree_region(&region), + // }; + // } } fn place_client( &self, window: Window, - method: LayoutMethod, + // method: LayoutMethod, ) { let client = self.client(window).unwrap(); @@ -1059,11 +1070,12 @@ impl<'a> Model<'a> { self.conn.place_window(window, inner_region); - self.conn.place_window(frame, match method { - LayoutMethod::Free => &client.free_region(), - LayoutMethod::Tile => &client.tile_region(), - LayoutMethod::Tree => &client.tree_region(), - }); + // TODO: zone change + // self.conn.place_window(frame, match method { + // LayoutMethod::Free => &client.free_region(), + // LayoutMethod::Tile => &client.tile_region(), + // LayoutMethod::Tree => &client.tree_region(), + // }); self.refresh_client(window); self.conn.update_window_offset(window, frame); @@ -1337,7 +1349,8 @@ impl<'a> Model<'a> { }); let workspace = self.workspace_mut(workspace_index); - workspace.set_layout(LayoutKind::Float); + // TODO: zone change + // workspace.set_layout(LayoutKind::Float); self.apply_layout(workspace_index, false); } @@ -1607,17 +1620,20 @@ impl<'a> Model<'a> { pub fn set_layout( &mut self, - layout: LayoutKind, + // TODO: zone change + // layout: LayoutKind, ) { let workspace_index = self.active_workspace(); let workspace = self.workspace_mut(workspace_index); - info!( - "activating layout {:?} on workspace {}", - layout, workspace_index - ); + // TODO: zone change + // info!( + // "activating layout {:?} on workspace {}", + // layout, workspace_index + // ); - workspace.set_layout(layout); + // TODO: zone change + // workspace.set_layout(layout); self.apply_layout(workspace_index, true); } @@ -1772,9 +1788,10 @@ impl<'a> Model<'a> { let workspace = self.workspace_mut(client_workspace_index); workspace.focus_client(window); - if workspace.layout_config().persistent { - self.apply_layout(client_workspace_index, false); - } + // TODO: zone change + // if workspace.layout_config().persistent { + // self.apply_layout(client_workspace_index, false); + // } if self.conn.get_focused_window() != window { self.conn.focus_window(window); @@ -2248,8 +2265,10 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; - self.update_client_placement(&placement, LayoutMethod::Free); - self.place_client(window, LayoutMethod::Free); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(window); } } } @@ -2293,8 +2312,10 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; - self.update_client_placement(&placement, LayoutMethod::Free); - self.place_client(window, LayoutMethod::Free); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(window); } } } @@ -2358,8 +2379,10 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; - self.update_client_placement(&placement, LayoutMethod::Free); - self.place_client(placement.window, LayoutMethod::Free); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(placement.window); } } } @@ -2457,9 +2480,10 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; - self.update_client_placement(&placement, LayoutMethod::Free); - - self.place_client(window, LayoutMethod::Free); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(window); } } } @@ -2512,12 +2536,13 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; + // TODO: zone change self.update_client_placement( &placement, - LayoutMethod::Free, ); - self.place_client(placement.window, LayoutMethod::Free); + // TODO: zone change + self.place_client(placement.window); } } } @@ -2623,9 +2648,10 @@ impl<'a> Model<'a> { extents: Some(frame_extents), }; - self.update_client_placement(&placement, LayoutMethod::Free); - - self.place_client(placement.window, LayoutMethod::Free); + // TODO: zone change + self.update_client_placement(&placement); + // TODO: zone change + self.place_client(placement.window); } } } @@ -3176,11 +3202,12 @@ impl<'a> Model<'a> { extents: *client.frame_extents(), }; + // TODO: zone change self.update_client_placement( &placement, - LayoutMethod::Free, ); - self.place_client(placement.window, LayoutMethod::Free); + // TODO: zone change + self.place_client(placement.window); } } } else { diff --git a/src/core/workspace.rs b/src/core/workspace.rs @@ -5,15 +5,9 @@ use crate::common::Ident; use crate::common::Identify; use crate::common::Index; use crate::common::Placement; -use crate::common::FREE_EXTENTS; use crate::cycle::Cycle; use crate::cycle::InsertPos; use crate::cycle::Selector; -use crate::layout::Layout; -use crate::layout::LayoutApply; -use crate::layout::LayoutConfig; -use crate::layout::LayoutFactory; -use crate::layout::LayoutKind; use winsys::common::Edge; use winsys::common::Grip; @@ -138,8 +132,6 @@ pub struct Workspace { name: String, clients: Cycle<Window>, icons: Cycle<Window>, - layouts: Cycle<Layout>, - previous_layout: LayoutKind, } impl Workspace { @@ -152,20 +144,6 @@ impl Workspace { name: name.into(), clients: Cycle::new(Vec::new(), true), icons: Cycle::new(Vec::new(), true), - layouts: Cycle::new( - vec![ - LayoutFactory::create_layout(LayoutKind::Center), - LayoutFactory::create_layout(LayoutKind::Monocle), - LayoutFactory::create_layout(LayoutKind::Paper), - LayoutFactory::create_layout(LayoutKind::PaperCenter), - LayoutFactory::create_layout(LayoutKind::SStack), - LayoutFactory::create_layout(LayoutKind::SingleFloat), - LayoutFactory::create_layout(LayoutKind::Stack), - LayoutFactory::create_layout(LayoutKind::Float), - ], - false, - ), - previous_layout: LayoutKind::Float, } } @@ -226,18 +204,8 @@ impl Workspace { let sel = match sel { ClientSelector::AtActive => Selector::AtActive, ClientSelector::AtMaster => { - if let Some(layout) = self.layouts.active_element() { - if let Some(main_count) = layout.main_count() { - Selector::AtIndex(std::cmp::min( - main_count as usize, - self.clients.len(), - )) - } else { - return None; - } - } else { - return None; - } + // TODO: zone change + return None; }, ClientSelector::AtIndex(index) => Selector::AtIndex(*index), ClientSelector::AtIdent(window) => { @@ -310,128 +278,29 @@ impl Workspace { F: Fn(&Client) -> bool, { if !self.clients.is_empty() { - let layout = self.layouts.active_element().unwrap(); - let (fullscreen, non_fullscreen): (Vec<&Client>, Vec<&Client>) = - self.clients - .iter() - .map(|window| client_map.get(window).unwrap()) - .partition(|client| { - client.is_fullscreen() && !client.is_in_window() - }); - let (tiled, floating): (Vec<&Client>, Vec<&Client>) = - non_fullscreen.iter().partition(|client| filter(client)); - - let mut placements = if tiled.is_empty() { - Vec::with_capacity(floating.len()) - } else { - layout.arrange(&tiled, self.focused_client(), &screen_region) - }; - - placements.append( - &mut fullscreen - .iter() - .map(|client| Placement { - window: client.window(), - region: if !client.is_focused() - && self.layout_config().persistent - && self.layout_config().single - { - None - } else { - Some(screen_region) - }, - extents: None, - }) - .collect(), - ); - - placements.append( - &mut floating - .iter() - .map(|client| Placement { - window: client.window(), - region: if !client.is_focused() - && self.layout_config().persistent - && self.layout_config().single - { - None - } else { - Some(*client.free_region()) - }, - extents: Some(FREE_EXTENTS), - }) - .collect(), - ); - - placements + // TODO: zone change + Vec::with_capacity(0) } else { - vec![] - } - } - - pub fn arrange( - &self, - screen_region: Region, - client_map: &HashMap<Window, Client>, - ) -> Vec<Placement> { - if !self.clients.is_empty() { - let layout = self.layouts.active_element().unwrap(); - let clients: Vec<&Client> = self - .clients - .iter() - .map(|window| client_map.get(window).unwrap()) - .collect(); - - layout.arrange(&clients, self.focused_client(), &screen_region) - } else { - vec![] + Vec::with_capacity(0) } } pub fn set_layout( &mut self, - kind: LayoutKind, - ) -> Option<&Layout> { - let layout = self.layouts.active_element().unwrap(); - - if layout.kind == kind { - return None; - } - - self.previous_layout = layout.kind; - - let layout = - self.layouts.activate_for(&Selector::AtIdent(kind as Ident)); - - layout + // kind: LayoutKind, + ) { + // TODO: zone change } - pub fn toggle_layout(&mut self) -> Option<&Layout> { - self.set_layout(self.previous_layout) + pub fn toggle_layout(&mut self) { + // TODO: zone change } pub fn cycle_layout( &mut self, dir: Direction, - ) -> char { - self.layouts.cycle_active(dir); - self.layout_symbol() - } - - pub fn layout_kind(&self) -> LayoutKind { - self.layouts.active_element().unwrap().kind - } - - pub fn layout_symbol(&self) -> char { - self.layouts.active_element().unwrap().symbol - } - - pub fn layout_name(&self) -> &str { - &self.layouts.active_element().unwrap().name - } - - pub fn layout_config(&self) -> LayoutConfig { - self.layouts.active_element().unwrap().config + ) { + // TODO: zone change } pub fn cycle_focus( @@ -442,9 +311,7 @@ impl Workspace { return None; } - if !self.layout_config().wraps && self.clients.next_will_wrap(dir) { - return None; - } + // TODO: zone change let prev_active = *self.clients.active_element()?; let now_active = *self.clients.cycle_active(dir)?; @@ -485,8 +352,7 @@ impl Workspace { } pub fn reset_layout(&mut self) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.reset(); + // TODO: zone change } pub fn change_gap_size( @@ -494,21 +360,18 @@ impl Workspace { change: Change, delta: u32, ) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.change_gap_size(change, delta); + // TODO: zone change } pub fn reset_gap_size(&mut self) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.reset_gap_size(); + // TODO: zone change } pub fn change_main_count( &mut self, change: Change, ) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.change_main_count(change); + // TODO: zone change } pub fn change_main_factor( @@ -516,8 +379,7 @@ impl Workspace { change: Change, delta: f32, ) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.change_main_factor(change, delta); + // TODO: zone change } pub fn change_margin( @@ -526,13 +388,11 @@ impl Workspace { change: Change, delta: u32, ) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.change_margin(edge, change, delta); + // TODO: zone change } pub fn reset_margin(&mut self) { - let layout = self.layouts.active_element_mut().unwrap(); - layout.reset_margin(); + // TODO: zone change } pub fn focused_icon(&self) -> Option<Window> { diff --git a/src/core/zone.rs b/src/core/zone.rs @@ -1,4 +1,3 @@ -use crate::client::Client; use crate::common::Ident; use crate::common::Identify; use crate::cycle::Cycle;