commit 5cd644c6f846c1440efd3dd43822e4dacb440768
parent 2d738c1955333bab37f8fc717ee2711b211ca600
Author: deurzen <m.deurzen@tum.de>
Date: Wed, 17 Mar 2021 20:18:29 +0100
implements initial zone cycling behavior
Diffstat:
5 files changed, 116 insertions(+), 32 deletions(-)
diff --git a/src/core/common.rs b/src/core/common.rs
@@ -33,10 +33,12 @@ pub const FREE_DECORATION: Decoration = Decoration {
}),
};
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StateChangeError {
EarlyStop,
LimitReached,
StateUnchanged,
+ InvalidCaller,
}
pub type Color = u32;
diff --git a/src/core/main.rs b/src/core/main.rs
@@ -183,6 +183,10 @@ fn init_bindings() -> (MouseBindings, KeyBindings) {
"1-S-semicolon" => do_internal!(rotate_clients, Direction::Forward),
"1-S-comma" => do_internal!(rotate_clients, Direction::Backward),
+ // zone order modifiers
+ "1-C-j" => do_internal!(cycle_zones, Direction::Forward),
+ "1-C-k" => do_internal!(cycle_zones, Direction::Backward),
+
// active workspace layout setters
"1-m" => do_internal!(set_layout, LayoutKind::Monocle),
"1-t" => do_internal!(set_layout, LayoutKind::Stack),
@@ -293,9 +297,9 @@ fn init_bindings() -> (MouseBindings, KeyBindings) {
}),
// external spawn commands
- "XF86AudioPlay", "1-2-p" => spawn_external!("playerctl play-pause"),
- "XF86AudioPrev", "1-2-k" => spawn_external!("playerctl previous"),
- "XF86AudioNext", "1-2-j" => spawn_external!("playerctl next"),
+ "XF86AudioPlay", "1-2-C-p" => spawn_external!("playerctl play-pause"),
+ "XF86AudioPrev", "1-2-C-k" => spawn_external!("playerctl previous"),
+ "XF86AudioNext", "1-2-C-j" => spawn_external!("playerctl next"),
"1-2-BackSpace" => spawn_external!("playerctl stop"),
"XF86AudioMute" => spawn_external!("amixer -D pulse sset Master toggle"),
"XF86AudioLowerVolume" => spawn_external!("amixer -D pulse sset Master 5%-"),
diff --git a/src/core/model.rs b/src/core/model.rs
@@ -137,16 +137,38 @@ impl<'a> Model<'a> {
.screen()
.placeable_region();
- let id = model.zone_manager.new_zone(
+ let root_id = model.zone_manager.new_zone(
None,
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, id));
+ .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(id).set_region(region);
+ model.zone_manager.zone_mut(root_id).set_region(region);
}
model.workspaces.activate_for(&Selector::AtIndex(0));
@@ -1306,6 +1328,18 @@ impl<'a> Model<'a> {
self.conn.flush();
}
+ pub fn cycle_zones(
+ &mut self,
+ dir: Direction,
+ ) {
+ let workspace = self.active_workspace();
+ let zone_manager = &self.zone_manager;
+
+ self.workspaces
+ .get_mut(workspace)
+ .and_then(|ws| ws.cycle_zones(dir, zone_manager));
+ }
+
pub fn cycle_focus(
&mut self,
dir: Direction,
@@ -1400,7 +1434,7 @@ impl<'a> Model<'a> {
client.set_free_region(&active_region);
});
- self.set_layout(LayoutKind::Float);
+ drop(self.set_layout(LayoutKind::Float));
self.apply_layout(workspace_index, false);
}
@@ -1698,7 +1732,7 @@ impl<'a> Model<'a> {
pub fn set_layout(
&mut self,
kind: LayoutKind,
- ) {
+ ) -> Result<(), StateChangeError> {
let workspace_index = self.active_workspace();
let workspace = self.workspace_mut(workspace_index);
@@ -1708,9 +1742,11 @@ impl<'a> Model<'a> {
kind, workspace_index
);
- self.zone_manager.set_kind(id, kind);
+ self.zone_manager.set_kind(id, kind)?;
self.apply_layout(workspace_index, true);
}
+
+ Ok(())
}
pub fn toggle_layout(&mut self) {
diff --git a/src/core/workspace.rs b/src/core/workspace.rs
@@ -383,6 +383,27 @@ impl Workspace {
}
}
+ pub fn cycle_zones(
+ &mut self,
+ dir: Direction,
+ zone_manager: &ZoneManager,
+ ) -> Option<(ZoneId, ZoneId)> {
+ if self.zones.len() < 2 {
+ return None;
+ }
+
+ let prev_active = *self.zones.active_element()?;
+ let mut now_active = *self.zones.cycle_active(dir)?;
+
+ loop {
+ if zone_manager.is_cycle(now_active) {
+ return Some((prev_active, now_active));
+ }
+
+ now_active = *self.zones.cycle_active(dir)?;
+ }
+ }
+
pub fn cycle_focus(
&mut self,
dir: Direction,
@@ -393,8 +414,8 @@ impl Workspace {
return None;
}
- let window = self.clients.active_element().unwrap();
- let id = client_map.get(window).unwrap().zone();
+ let prev_active = *self.clients.active_element()?;
+ let id = client_map.get(&prev_active).unwrap().zone();
let config = zone_manager.active_layoutconfig(id);
if let Some(config) = config {
@@ -403,7 +424,6 @@ impl Workspace {
}
}
- let prev_active = *self.clients.active_element()?;
let now_active = *self.clients.cycle_active(dir)?;
if prev_active != now_active {
diff --git a/src/core/zone.rs b/src/core/zone.rs
@@ -2,8 +2,10 @@ use crate::common::Decoration;
use crate::common::Frame;
use crate::common::Ident;
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;
@@ -705,13 +707,15 @@ impl Layout {
fn set_kind(
&mut self,
kind: LayoutKind,
- ) {
+ ) -> Result<LayoutKind, StateChangeError> {
if kind == self.kind {
- return;
+ return Err(StateChangeError::EarlyStop);
}
self.prev_kind = self.kind;
self.kind = kind;
+
+ Ok(self.prev_kind)
}
#[inline]
@@ -850,26 +854,24 @@ impl Zone {
fn set_kind(
&mut self,
kind: LayoutKind,
- ) {
+ ) -> Result<LayoutKind, StateChangeError> {
match self.content {
- ZoneContent::Layout(ref mut layout, _) => {
- layout.set_kind(kind);
- },
- _ => {},
+ ZoneContent::Layout(ref mut layout, _) => layout.set_kind(kind),
+ _ => Err(StateChangeError::InvalidCaller),
}
}
- pub fn prev_kind(&self) -> LayoutKind {
+ pub fn prev_kind(&self) -> Result<LayoutKind, StateChangeError> {
match &self.content {
- ZoneContent::Layout(layout, _) => layout.prev_kind,
- _ => panic!("attempting to obtain layout kind from non-layout"),
+ ZoneContent::Layout(layout, _) => Ok(layout.prev_kind),
+ _ => Err(StateChangeError::InvalidCaller),
}
}
- pub fn kind(&self) -> LayoutKind {
+ pub fn kind(&self) -> Result<LayoutKind, StateChangeError> {
match &self.content {
- ZoneContent::Layout(layout, _) => layout.kind,
- _ => panic!("attempting to obtain layout kind from non-layout"),
+ ZoneContent::Layout(layout, _) => Ok(layout.kind),
+ _ => Err(StateChangeError::InvalidCaller),
}
}
@@ -1004,30 +1006,32 @@ impl ZoneManager {
&mut self,
id: ZoneId,
kind: LayoutKind,
- ) {
+ ) -> Result<LayoutKind, StateChangeError> {
let persistent_data_copy = self.persistent_data_copy;
let cycle = self.nearest_cycle(id);
let cycle = self.zone_mut(cycle);
- cycle.set_kind(kind);
+ let prev_kind = cycle.set_kind(kind)?;
if persistent_data_copy {
let prev_data = *cycle.prev_data().unwrap();
let data = cycle.data_mut().unwrap();
*data = prev_data;
}
+
+ Ok(prev_kind)
}
pub fn set_prev_kind(
&mut self,
id: ZoneId,
- ) -> LayoutKind {
+ ) -> Result<LayoutKind, StateChangeError> {
let persistent_data_copy = self.persistent_data_copy;
let cycle = self.nearest_cycle(id);
let cycle = self.zone_mut(cycle);
- let prev_kind = cycle.prev_kind();
- cycle.set_kind(prev_kind);
+ let kind = cycle.prev_kind()?;
+ let prev_kind = cycle.set_kind(kind)?;
if persistent_data_copy {
let prev_data = *cycle.prev_data().unwrap();
@@ -1035,7 +1039,7 @@ impl ZoneManager {
*data = prev_data;
}
- prev_kind
+ Ok(prev_kind)
}
pub fn active_default_data(
@@ -1123,6 +1127,18 @@ impl ZoneManager {
zone.config()
}
+ pub fn is_cycle(
+ &self,
+ id: ZoneId,
+ ) -> bool {
+ let zone = self.zone_map.get(&id).unwrap();
+
+ match zone.content {
+ ZoneContent::Tab(_) | ZoneContent::Layout(..) => true,
+ _ => false,
+ }
+ }
+
pub fn nearest_cycle(
&self,
id: ZoneId,
@@ -1289,7 +1305,13 @@ impl ZoneManager {
});
placements.extend(
- self.arrange_subzones(id, region, decoration, method, to_ignore),
+ self.arrange_subzones(id, region, Decoration {
+ frame: None,
+ border: Some(Border {
+ width: 1,
+ colors: Default::default(),
+ }),
+ }, method, to_ignore),
);
placements