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:
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(®ion),
- LayoutMethod::Tile => client.set_tile_region(®ion),
- LayoutMethod::Tree => client.set_tree_region(®ion),
- };
- }
+ // LayoutMethod::Free => client.set_free_region(®ion),
+ // LayoutMethod::Tile => client.set_tile_region(®ion),
+
+ // TODO: zone change
+ // if let Some(region) = placement.region {
+ // match method {
+ // LayoutMethod::Free => client.set_free_region(®ion),
+ // LayoutMethod::Tile => client.set_tile_region(®ion),
+ // LayoutMethod::Tree => client.set_tree_region(®ion),
+ // };
+ // }
}
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;