commit 3dadec096115d65484b82aa8cab329c4da17f108
parent 336efce7af5f2193a74d36d88e8c4249a3ca48ed
Author: deurzen <m.deurzen@tum.de>
Date: Fri, 12 Mar 2021 22:25:20 +0100
adds layout changing functionality
Diffstat:
4 files changed, 303 insertions(+), 55 deletions(-)
diff --git a/src/core/main.rs b/src/core/main.rs
@@ -40,6 +40,7 @@ use jump::JumpCriterium;
use jump::MatchMethod;
use model::Model;
use workspace::ClientSelector;
+use zone::LayoutKind;
pub fn main() -> Result<()> {
#[cfg(debug_assertions)]
@@ -185,15 +186,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
@@ -27,9 +27,10 @@ use crate::workspace::Workspace;
use crate::zone::Decoration;
use crate::zone::Frame;
use crate::zone::Layout;
-use crate::zone::PlacementMethod;
+use crate::zone::LayoutKind;
use crate::zone::Placement;
use crate::zone::PlacementKind;
+use crate::zone::PlacementMethod;
use crate::zone::ZoneContent;
use crate::zone::ZoneId;
use crate::zone::ZoneManager;
@@ -350,8 +351,8 @@ impl<'a> Model<'a> {
// TODO: zone change
let region = self.active_screen().placeable_region();
- let placements =
- workspace.arrange(&mut self.zone_manager, region);
+ let placements = workspace.arrange(&mut self.zone_manager, region);
+
let (show, hide): (Vec<&Placement>, Vec<&Placement>) = placements
.iter()
.partition(|&placement| placement.region.is_some());
@@ -1673,19 +1674,23 @@ impl<'a> Model<'a> {
pub fn set_layout(
&mut self,
// TODO: zone change
- // layout: LayoutKind,
+ kind: LayoutKind,
) {
let workspace_index = self.active_workspace();
let workspace = self.workspace_mut(workspace_index);
- // TODO: zone change
- // info!(
- // "activating layout {:?} on workspace {}",
- // layout, workspace_index
- // );
+ if let Some(id) = workspace.active_zone() {
+ let cycle = self.zone_manager.nearest_cycle(id);
+ let cycle = self.zone_manager.get_zone_mut(cycle);
+
+ cycle.set_kind(kind);
+ }
+
+ info!(
+ "activating layout {:?} on workspace {}",
+ kind, workspace_index
+ );
- // TODO: zone change
- // workspace.set_layout(layout);
self.apply_layout(workspace_index, true);
}
diff --git a/src/core/workspace.rs b/src/core/workspace.rs
@@ -7,8 +7,8 @@ use crate::common::Index;
use crate::cycle::Cycle;
use crate::cycle::InsertPos;
use crate::cycle::Selector;
-use crate::zone::PlacementMethod;
use crate::zone::Placement;
+use crate::zone::PlacementMethod;
use crate::zone::ZoneId;
use crate::zone::ZoneManager;
diff --git a/src/core/zone.rs b/src/core/zone.rs
@@ -23,6 +23,15 @@ use std::vec::Vec;
pub type ZoneId = u32;
type Color = u32;
+const MAX_MAIN_COUNT: u32 = 15;
+const MAX_GAP_SIZE: u32 = 300;
+const MAX_MARGIN: Padding = Padding {
+ left: 700,
+ right: 700,
+ top: 400,
+ bottom: 400,
+};
+
static INSTANCE_COUNT: atomic::AtomicU32 = atomic::AtomicU32::new(1);
fn next_id() -> ZoneId {
INSTANCE_COUNT.fetch_add(1, atomic::Ordering::Relaxed) as ZoneId
@@ -197,13 +206,88 @@ impl LayoutKind {
fn config(&self) -> LayoutConfig {
match *self {
- // TODO
- LayoutKind::Float => LayoutConfig::default(),
- LayoutKind::SingleFloat => LayoutConfig::default(),
- LayoutKind::Center => LayoutConfig::default(),
- LayoutKind::Monocle => LayoutConfig::default(),
- LayoutKind::Paper => LayoutConfig::default(),
- LayoutKind::SStack => LayoutConfig::default(),
+ LayoutKind::Float => LayoutConfig {
+ method: PlacementMethod::Free,
+ decoration: Default::default(),
+ root_only: true,
+ gap: false,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
+ LayoutKind::SingleFloat => LayoutConfig {
+ method: PlacementMethod::Free,
+ decoration: Default::default(),
+ root_only: true,
+ gap: false,
+ persistent: true,
+ single: true,
+ wraps: true,
+ },
+ LayoutKind::Center => LayoutConfig {
+ method: PlacementMethod::Tile,
+ decoration: Decoration {
+ frame: None,
+ border: None,
+ },
+ root_only: false,
+ gap: true,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
+ LayoutKind::Monocle => LayoutConfig {
+ method: PlacementMethod::Tile,
+ decoration: Decoration {
+ frame: None,
+ border: None,
+ },
+ root_only: false,
+ gap: true,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
+ LayoutKind::Paper => LayoutConfig {
+ method: PlacementMethod::Tile,
+ decoration: Decoration {
+ frame: Some(Frame {
+ extents: Extents {
+ left: 1,
+ right: 1,
+ top: 0,
+ bottom: 0,
+ },
+ colors: Default::default(),
+ }),
+ border: None,
+ },
+ root_only: false,
+ gap: true,
+ persistent: true,
+ single: false,
+ wraps: false,
+ },
+ LayoutKind::SStack => LayoutConfig {
+ method: PlacementMethod::Tile,
+ decoration: Decoration {
+ frame: Some(Frame {
+ extents: Extents {
+ left: 0,
+ right: 0,
+ top: 3,
+ bottom: 0,
+ },
+ colors: Default::default(),
+ }),
+ border: None,
+ },
+ root_only: false,
+ gap: false,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
LayoutKind::Stack => LayoutConfig {
method: PlacementMethod::Tile,
decoration: Decoration {
@@ -219,6 +303,7 @@ impl LayoutKind {
border: None,
},
root_only: false,
+ gap: true,
persistent: false,
single: false,
wraps: true,
@@ -232,6 +317,31 @@ impl LayoutKind {
}
}
+ fn default_data(&self) -> LayoutData {
+ match *self {
+ // TODO
+ LayoutKind::Float => LayoutData::default(),
+ LayoutKind::SingleFloat => LayoutData::default(),
+ LayoutKind::Center => LayoutData {
+ margin: None,
+ gap_size: 0,
+
+ main_count: 5u32,
+ main_factor: 0.40f32,
+ },
+ LayoutKind::Monocle => LayoutData::default(),
+ LayoutKind::Paper => LayoutData::default(),
+ LayoutKind::SStack => LayoutData::default(),
+ LayoutKind::Stack => LayoutData::default(),
+
+ #[allow(unreachable_patterns)]
+ _ => unimplemented!(
+ "{:?} does not have associated default data",
+ self
+ ),
+ }
+ }
+
fn func(&self) -> LayoutFn {
match *self {
// TODO
@@ -245,8 +355,8 @@ impl LayoutKind {
.collect()
},
LayoutKind::Stack => |region, data, active_map| {
- let n = active_map.len();
let (pos, dim) = region.values();
+ let n = active_map.len();
if n == 1 {
return vec![(
@@ -262,7 +372,7 @@ impl LayoutKind {
let h_stack = if n_stack > 0 { dim.h / n_stack } else { 0 };
let h_main = if n_main > 0 { dim.h / n_main } else { 0 };
- let split = if data.main_count > 0 {
+ let div = if data.main_count > 0 {
(dim.w as f32 * data.main_factor) as i32
} else {
0
@@ -277,7 +387,7 @@ impl LayoutKind {
if i < data.main_count {
let w =
- if n_stack == 0 { dim.w } else { split as u32 };
+ if n_stack == 0 { dim.w } else { div as u32 };
(
Disposition::Changed(
@@ -297,9 +407,9 @@ impl LayoutKind {
(
Disposition::Changed(
Region::new(
- pos.x + split,
+ pos.x + div,
pos.y + sn * h_stack as i32,
- dim.w - split as u32,
+ dim.w - div as u32,
h_stack,
),
config.decoration,
@@ -310,6 +420,126 @@ impl LayoutKind {
})
.collect()
},
+ LayoutKind::Monocle => |region, data, active_map| {
+ let config = &LayoutKind::Monocle.config();
+ let (pos, dim) = region.values();
+
+ active_map
+ .iter()
+ .map(|_| {
+ (
+ Disposition::Changed(
+ Region {
+ pos,
+ dim,
+ },
+ config.decoration,
+ ),
+ true,
+ )
+ })
+ .collect()
+ },
+ LayoutKind::Center => |region, data, active_map| {
+ let config = &LayoutKind::Center.config();
+ let default_data = &LayoutKind::Center.default_data();
+ let (pos, dim) = region.values();
+
+ let h_comp = MAX_MAIN_COUNT + 1;
+ let w_ratio: f32 = data.main_factor / 0.95;
+ let h_ratio: f32 =
+ (h_comp - data.main_count) as f32 / h_comp as f32;
+
+ active_map
+ .iter()
+ .map(|_| {
+ (
+ Disposition::Changed(
+ Region {
+ pos,
+ dim,
+ }
+ .from_absolute_inner_center(&Dim {
+ w: (dim.w as f32 * w_ratio) as u32,
+ h: (dim.h as f32 * h_ratio) as u32,
+ }),
+ config.decoration,
+ ),
+ true,
+ )
+ })
+ .collect()
+ },
+ LayoutKind::Paper => |region, data, active_map| {
+ const min_w_ratio: f32 = 0.5;
+
+ let config = &LayoutKind::Paper.config();
+ let (pos, dim) = region.values();
+ let n = active_map.len();
+
+ if n == 1 {
+ return vec![(
+ Disposition::Changed(*region, Decoration {
+ border: None,
+ frame: None,
+ }),
+ true,
+ )];
+ }
+
+
+ let cw = (dim.w as f32
+ * if data.main_factor > min_w_ratio {
+ data.main_factor
+ } else {
+ min_w_ratio
+ }) as u32;
+
+ let w = ((dim.w - cw) as usize / (n - 1)) as i32;
+ let mut after_active = false;
+
+ active_map
+ .iter()
+ .enumerate()
+ .map(|(i, &active)| {
+ if active {
+ after_active = true;
+
+ (
+ Disposition::Changed(
+ Region::new(
+ pos.x + i as i32 * w,
+ pos.y,
+ cw,
+ dim.h,
+ ),
+ config.decoration,
+ ),
+ true,
+ )
+ } else {
+ let mut x = pos.x + i as i32 * w;
+
+ if after_active {
+ x += cw as i32 - w;
+ }
+
+ (
+ Disposition::Changed(
+ Region::new(
+ x,
+ pos.y,
+ w as u32,
+ dim.h,
+ ),
+ config.decoration,
+ ),
+ true,
+ )
+ }
+ })
+ .collect()
+ },
#[allow(unreachable_patterns)]
_ => unimplemented!(
@@ -326,6 +556,7 @@ struct LayoutConfig {
method: PlacementMethod,
decoration: Decoration,
root_only: bool,
+ gap: bool,
persistent: bool,
single: bool,
wraps: bool,
@@ -337,6 +568,7 @@ impl Default for LayoutConfig {
method: PlacementMethod::Free,
decoration: Default::default(),
root_only: true,
+ gap: false,
persistent: false,
single: false,
wraps: true,
@@ -372,44 +604,42 @@ pub struct Layout {
kind: LayoutKind,
prev_kind: LayoutKind,
data: HashMap<LayoutKind, LayoutData>,
- default_data: HashMap<LayoutKind, LayoutData>,
}
impl Layout {
pub fn new() -> Self {
+ let kind = LayoutKind::Stack;
let mut data = HashMap::with_capacity(LayoutKind::COUNT);
- let mut default_data = HashMap::with_capacity(LayoutKind::COUNT);
for kind in LayoutKind::iter() {
- data.insert(kind, Default::default());
- default_data.insert(kind, Default::default());
+ data.insert(kind, kind.default_data());
}
Self {
- kind: LayoutKind::Stack,
- prev_kind: LayoutKind::Float,
+ kind,
+ prev_kind: kind,
data,
- default_data,
}
}
pub fn with_kind(kind: LayoutKind) -> Self {
let mut data = HashMap::with_capacity(LayoutKind::COUNT);
- let mut default_data = HashMap::with_capacity(LayoutKind::COUNT);
for kind in LayoutKind::iter() {
- data.insert(kind, Default::default());
- default_data.insert(kind, Default::default());
+ data.insert(kind, kind.default_data());
}
Self {
kind,
prev_kind: kind,
data,
- default_data,
}
}
+ fn get_config(&self) -> LayoutConfig {
+ self.kind.config()
+ }
+
fn get_data(&self) -> &LayoutData {
self.data.get(&self.kind).unwrap()
}
@@ -418,8 +648,8 @@ impl Layout {
self.data.get_mut(&self.kind).unwrap()
}
- fn get_default_data(&self) -> &LayoutData {
- self.default_data.get(&self.kind).unwrap()
+ fn get_default_data(&self) -> LayoutData {
+ self.kind.default_data()
}
fn set_kind(
@@ -451,7 +681,7 @@ impl Apply for Layout {
region,
&self.data.get(&self.kind).unwrap(),
active_map,
- )
+ ),
)
}
}
@@ -498,6 +728,18 @@ impl Zone {
})
}
+ pub fn set_kind(
+ &mut self,
+ kind: LayoutKind,
+ ) {
+ match self.content {
+ ZoneContent::Layout(ref mut layout, _) => {
+ layout.kind = kind;
+ },
+ _ => {},
+ }
+ }
+
pub fn set_region(
&mut self,
region: Region,
@@ -707,9 +949,7 @@ impl ZoneManager {
let active_element = zones.active_element();
zones
.iter()
- .filter(|&id| {
- Some(id) != active_element
- })
+ .filter(|&id| Some(id) != active_element)
.for_each(|&id| {
zone_changes.push((id, ZoneChange::Visible(false)));
});
@@ -733,9 +973,12 @@ impl ZoneManager {
.collect::<Vec<(ZoneId, ZoneChange)>>(),
);
- placements.extend(
- self.arrange_subzones(id, region, decoration, PlacementMethod::Tile),
- );
+ placements.extend(self.arrange_subzones(
+ id,
+ region,
+ decoration,
+ PlacementMethod::Tile,
+ ));
placements
},
}
@@ -809,8 +1052,7 @@ impl ZoneManager {
zone_changes.iter().for_each(|(id, change)| {
let zone = self.zone_map.get_mut(id).unwrap();
- let kind =
- PlacementKind::from_zone_content(&zone.content);
+ let kind = PlacementKind::from_zone_content(&zone.content);
let region = zone.region;
let decoration = zone.decoration;