commit 7c99b99a80114faf46f4a93b5c3e6cd1099d8e3f
parent 5cd644c6f846c1440efd3dd43822e4dacb440768
Author: deurzen <m.deurzen@tum.de>
Date: Fri, 19 Mar 2021 02:40:02 +0100
adds initial zone creation and deletion bindings
Diffstat:
4 files changed, 313 insertions(+), 158 deletions(-)
diff --git a/src/core/main.rs b/src/core/main.rs
@@ -183,6 +183,11 @@ fn init_bindings() -> (MouseBindings, KeyBindings) {
"1-S-semicolon" => do_internal!(rotate_clients, Direction::Forward),
"1-S-comma" => do_internal!(rotate_clients, Direction::Backward),
+ // zone creators
+ "1-C-Return" => do_internal!(create_layout_zone),
+ "1-C-S-Return" => do_internal!(create_tab_zone),
+ "1-C-C" => do_internal!(delete_zone),
+
// zone order modifiers
"1-C-j" => do_internal!(cycle_zones, Direction::Forward),
"1-C-k" => do_internal!(cycle_zones, Direction::Backward),
diff --git a/src/core/model.rs b/src/core/model.rs
@@ -142,32 +142,10 @@ impl<'a> Model<'a> {
ZoneContent::Layout(Layout::new(), Cycle::new(Vec::new(), true)),
);
- let subcycle1_id = model.zone_manager.new_zone(
- Some(root_id),
- ZoneContent::Tab(Cycle::new(Vec::new(), true)),
- );
-
- let subcycle2_id = model.zone_manager.new_zone(
- Some(root_id),
- ZoneContent::Layout(Layout::new(), Cycle::new(Vec::new(), true)),
- );
-
model
.workspaces
.push_back(Workspace::new(workspace_name, i as u32, root_id));
- model
- .workspaces
- .get_mut(i)
- .unwrap()
- .add_zone(subcycle1_id, &InsertPos::Back);
-
- model
- .workspaces
- .get_mut(i)
- .unwrap()
- .add_zone(subcycle2_id, &InsertPos::Back);
-
model.zone_manager.zone_mut(root_id).set_region(region);
}
@@ -358,7 +336,7 @@ impl<'a> Model<'a> {
let placements =
workspace.arrange(&mut self.zone_manager, &self.client_map, region, |client| {
- !Self::is_applyable(client)
+ !Self::is_applyable(client) || client.is_iconified()
});
let (show, hide): (Vec<&Placement>, Vec<&Placement>) = placements
@@ -815,7 +793,6 @@ impl<'a> Model<'a> {
let current_workspace = self.workspaces.get_mut(workspace).unwrap();
current_workspace.add_client(window, &InsertPos::Back);
- current_workspace.add_zone(id, &InsertPos::AfterActive);
}
if let Some(parent) = parent {
@@ -966,6 +943,51 @@ impl<'a> Model<'a> {
}
}
+ pub fn create_layout_zone(&mut self) {
+ let workspace_index = self.active_workspace();
+ let workspace = self.workspace(workspace_index);
+
+ let cycle = workspace.active_zone().unwrap();
+ let cycle = self.zone_manager.nearest_cycle(cycle);
+ let id = self.zone_manager.new_zone(Some(cycle),
+ ZoneContent::Layout(Layout::new(), Cycle::new(Vec::new(), true)));
+
+ let workspace = self.workspace_mut(workspace_index);
+ workspace.add_zone(id, &InsertPos::Back);
+ self.apply_layout(workspace_index, true);
+ }
+
+ pub fn create_tab_zone(&mut self) {
+ let workspace_index = self.active_workspace();
+ let workspace = self.workspace(workspace_index);
+
+ let cycle = workspace.active_zone().unwrap();
+ let cycle = self.zone_manager.nearest_cycle(cycle);
+ let id = self.zone_manager.new_zone(Some(cycle),
+ ZoneContent::Tab(Cycle::new(Vec::new(), true)));
+
+ let workspace = self.workspace_mut(workspace_index);
+ workspace.add_zone(id, &InsertPos::Back);
+ self.apply_layout(workspace_index, true);
+ }
+
+ pub fn delete_zone(&mut self) {
+ let workspace_index = self.active_workspace();
+ let workspace = self.workspace(workspace_index);
+
+ let cycle = workspace.active_zone().unwrap();
+ let cycle = self.zone_manager.nearest_cycle(cycle);
+
+ if cycle == workspace.root_zone() {
+ return;
+ }
+
+ self.zone_manager.remove_zone(cycle);
+
+ let workspace = self.workspace_mut(workspace_index);
+ workspace.remove_zone(cycle);
+ }
+
fn is_applyable(client: &Client) -> bool {
!client.is_floating()
&& !client.is_disowned()
@@ -1034,7 +1056,6 @@ impl<'a> Model<'a> {
self.zone_manager.remove_zone(id);
self.workspaces.get_mut(workspace).map(|w| {
- w.remove_zone(id);
w.remove_client(window);
w.remove_icon(window);
});
diff --git a/src/core/workspace.rs b/src/core/workspace.rs
@@ -345,6 +345,7 @@ impl Workspace {
let (to_ignore_ids, to_ignore_clients): (Vec<_>, Vec<_>) = self
.clients
.iter()
+ .chain(self.icons.iter())
.map(|window| client_map.get(window).unwrap())
.filter(|&client| ignore_filter(client))
.map(|client| (client.zone(), client))
@@ -361,7 +362,13 @@ impl Workspace {
PlacementRegion::NewRegion(screen_region),
NO_DECORATION,
)
- } else {
+ } else if client.is_iconified() {
+ (
+ PlacementMethod::Tile,
+ PlacementRegion::NoRegion,
+ NO_DECORATION,
+ )
+ }else {
(
PlacementMethod::Free,
PlacementRegion::FreeRegion,
diff --git a/src/core/zone.rs b/src/core/zone.rs
@@ -1,3 +1,4 @@
+use crate::common::Border;
use crate::common::Decoration;
use crate::common::Frame;
use crate::common::Ident;
@@ -5,7 +6,6 @@ use crate::common::Identify;
use crate::common::StateChangeError;
use crate::common::FREE_DECORATION;
use crate::common::NO_DECORATION;
-use crate::common::Border;
use crate::cycle::Cycle;
use crate::cycle::InsertPos;
use crate::cycle::Selector;
@@ -155,19 +155,26 @@ impl Default for LayoutData {
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, EnumIter, EnumCount, ToString)]
pub enum LayoutKind {
/// Free layouts
- Float = b'F',
- BLFloat = b'L',
- SingleFloat = b'Z',
- BLSingleFloat = b'Y',
+ Float = b'f',
+ BLFloat = b'F',
+ SingleFloat = b'z',
+ BLSingleFloat = b'Z',
/// Tiled layouts
+ // Overlapping
Center = b';',
- Monocle = b'M',
- Paper = b'/',
- SStack = b'+',
- Stack = b'S',
- Horz = b'H',
- Vert = b'V',
+ Monocle = b'%',
+ // Non-overlapping
+ Paper = b'p',
+ SPaper = b'P',
+ Stack = b's',
+ SStack = b'S',
+ BStack = b'b',
+ BSStack = b'B',
+ Horz = b'h',
+ SHorz = b'H',
+ Vert = b'v',
+ SVert = b'V',
}
impl LayoutKind {
@@ -262,6 +269,27 @@ impl LayoutKind {
single: false,
wraps: false,
},
+ LayoutKind::SPaper => 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,
+ margin: true,
+ gap: false,
+ persistent: true,
+ single: false,
+ wraps: false,
+ },
LayoutKind::Stack => LayoutConfig {
method: PlacementMethod::Tile,
decoration: Decoration {
@@ -304,6 +332,48 @@ impl LayoutKind {
single: false,
wraps: true,
},
+ LayoutKind::BStack => 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,
+ margin: true,
+ gap: true,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
+ LayoutKind::BSStack => 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,
+ margin: true,
+ gap: false,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
LayoutKind::Horz => LayoutConfig {
method: PlacementMethod::Tile,
decoration: Decoration {
@@ -325,6 +395,27 @@ impl LayoutKind {
single: false,
wraps: true,
},
+ LayoutKind::SHorz => 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,
+ margin: true,
+ gap: false,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
LayoutKind::Vert => LayoutConfig {
method: PlacementMethod::Tile,
decoration: Decoration {
@@ -346,6 +437,27 @@ impl LayoutKind {
single: false,
wraps: true,
},
+ LayoutKind::SVert => 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,
+ margin: true,
+ gap: false,
+ persistent: false,
+ single: false,
+ wraps: true,
+ },
#[allow(unreachable_patterns)]
_ => unimplemented!("{:?} does not have an associated configuration", self),
@@ -365,18 +477,31 @@ impl LayoutKind {
},
LayoutKind::Monocle => Default::default(),
LayoutKind::Paper => Default::default(),
+ LayoutKind::SPaper => Default::default(),
+ LayoutKind::Stack => LayoutData {
+ main_count: 1u32,
+ main_factor: 0.50f32,
+ ..Default::default()
+ },
LayoutKind::SStack => LayoutData {
main_count: 1u32,
main_factor: 0.50f32,
..Default::default()
},
- LayoutKind::Stack => LayoutData {
+ LayoutKind::BStack => LayoutData {
+ main_count: 1u32,
+ main_factor: 0.50f32,
+ ..Default::default()
+ },
+ LayoutKind::BSStack => LayoutData {
main_count: 1u32,
main_factor: 0.50f32,
..Default::default()
},
LayoutKind::Horz => Default::default(),
+ LayoutKind::SHorz => Default::default(),
LayoutKind::Vert => Default::default(),
+ LayoutKind::SVert => Default::default(),
#[allow(unreachable_patterns)]
_ => unimplemented!("{:?} does not have associated default data", self),
@@ -421,7 +546,58 @@ impl LayoutKind {
.map(|b| (Disposition::Unchanged(config.decoration), b))
.collect()
},
- LayoutKind::Stack => |region, data, active_map| {
+ LayoutKind::Center => |region, data, active_map| {
+ let config = &LayoutKind::Center.config();
+ 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
+ .into_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::Monocle => |region, _, active_map| {
+ let config = &LayoutKind::Monocle.config();
+ let (pos, dim) = region.values();
+
+ active_map
+ .into_iter()
+ .map(|_| {
+ (
+ Disposition::Changed(
+ Region {
+ pos,
+ dim,
+ },
+ 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();
@@ -429,44 +605,40 @@ impl LayoutKind {
return vec![(Disposition::Changed(*region, NO_DECORATION), true)];
}
- let (n_main, n_stack) = Self::stack_split(n, data.main_count);
- 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 cw = (dim.w as f32
+ * if data.main_factor > MIN_W_RATIO {
+ data.main_factor
+ } else {
+ MIN_W_RATIO
+ }) as u32;
- let div = if data.main_count > 0 {
- (dim.w as f32 * data.main_factor) as i32
- } else {
- 0
- };
+ let w = ((dim.w - cw) as usize / (n - 1)) as i32;
+ let mut after_active = false;
- let config = &LayoutKind::Stack.config();
active_map
.into_iter()
.enumerate()
- .map(|(i, _)| {
- let i = i as u32;
-
- if i < data.main_count {
- let w = if n_stack == 0 { dim.w } else { div as u32 };
+ .map(|(i, active)| {
+ if active {
+ after_active = true;
(
Disposition::Changed(
- Region::new(pos.x, pos.y + (i * h_main) as i32, w, h_main),
+ Region::new(pos.x + i as i32 * w, pos.y, cw, dim.h),
config.decoration,
),
true,
)
} else {
- let sn = (i - data.main_count) as i32;
+ let mut x = pos.x + i as i32 * w;
+
+ if after_active {
+ x += cw as i32 - w;
+ }
(
Disposition::Changed(
- Region::new(
- pos.x + div,
- pos.y + sn * h_stack as i32,
- dim.w - div as u32,
- h_stack,
- ),
+ Region::new(x, pos.y, w as u32, dim.h),
config.decoration,
),
true,
@@ -475,15 +647,18 @@ impl LayoutKind {
})
.collect()
},
- LayoutKind::SStack => |region, data, active_map| {
+ LayoutKind::SPaper => |region, data, active_map| {
let mut region = region.clone();
Layout::adjust_for_gap_size(&mut region, data.gap_size, &MIN_ZONE_DIM);
+ (Self::Paper.func())(®ion, data, active_map)
+ },
+ LayoutKind::Stack => |region, data, active_map| {
let (pos, dim) = region.values();
let n = active_map.len();
if n == 1 {
- return vec![(Disposition::Changed(region, NO_DECORATION), true)];
+ return vec![(Disposition::Changed(*region, NO_DECORATION), true)];
}
let (n_main, n_stack) = Self::stack_split(n, data.main_count);
@@ -532,106 +707,39 @@ impl LayoutKind {
})
.collect()
},
- LayoutKind::Monocle => |region, _, active_map| {
- let config = &LayoutKind::Monocle.config();
- let (pos, dim) = region.values();
+ LayoutKind::SStack => |region, data, active_map| {
+ let mut region = region.clone();
+ Layout::adjust_for_gap_size(&mut region, data.gap_size, &MIN_ZONE_DIM);
- active_map
- .into_iter()
- .map(|_| {
- (
- Disposition::Changed(
- Region {
- pos,
- dim,
- },
- config.decoration,
- ),
- true,
- )
- })
- .collect()
+ (Self::Stack.func())(®ion, data, active_map)
},
- LayoutKind::Center => |region, data, active_map| {
- let config = &LayoutKind::Center.config();
- 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
- .into_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();
+ LayoutKind::BStack => |region, _data, active_map| {
+ let (_pos, _dim) = region.values();
let n = active_map.len();
if n == 1 {
return vec![(Disposition::Changed(*region, NO_DECORATION), 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
- .into_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;
- }
+ todo!()
+ },
+ LayoutKind::BSStack => |region, data, active_map| {
+ let mut region = region.clone();
+ Layout::adjust_for_gap_size(&mut region, data.gap_size, &MIN_ZONE_DIM);
- (
- Disposition::Changed(
- Region::new(x, pos.y, w as u32, dim.h),
- config.decoration,
- ),
- true,
- )
- }
- })
- .collect()
+ (Self::BStack.func())(®ion, data, active_map)
+ },
+ LayoutKind::Horz => |_region, _data, _active_map| {
+ todo!()
+ },
+ LayoutKind::SHorz => |_region, _data, _active_map| {
+ todo!()
+ },
+ LayoutKind::Vert => |_region, _data, _active_map| {
+ todo!()
+ },
+ LayoutKind::SVert => |_region, _data, _active_map| {
+ todo!()
},
#[allow(unreachable_patterns)]
@@ -763,6 +871,16 @@ impl Layout {
}
}
+impl Default for Layout {
+ fn default() -> Self {
+ Self {
+ kind: LayoutKind::Stack,
+ prev_kind: LayoutKind::Stack,
+ data: HashMap::new(),
+ }
+ }
+}
+
trait Apply {
fn apply(
&self,
@@ -1304,15 +1422,19 @@ impl ZoneManager {
zone_changes.push((id, ZoneChange::Method(method)));
});
- placements.extend(
- self.arrange_subzones(id, region, Decoration {
+ placements.extend(self.arrange_subzones(
+ id,
+ region,
+ Decoration {
frame: None,
border: Some(Border {
width: 1,
colors: Default::default(),
}),
- }, method, to_ignore),
- );
+ },
+ method,
+ to_ignore,
+ ));
placements
},