Workspace back and forth (#253)

* implement workspace back and forth

* Make our own ID counter instead of SerialCounter, use a newtype

* Rename FocusWorkspaceBackAndForth to FocusWorkspacePrevious

* Add focus-workspace-previous to tests

* Don't special case in switch_workspace_previous

* Minor clean up

* Add switch_workspace_auto_back_and_forth to tests

* Skip animation on switch_workspace_previous

* Preserve previous_workspace_id on workspace movement

* Make Workspace::id private with a getter

Reduce the chance it gets overwritten.

* Add test for workspace ID uniqueness

* Update previous workspace ID upon moving workspace across monitors

---------

Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
FluxTape
2024-03-19 14:27:52 +00:00
committed by GitHub
parent c3327d36da
commit 23ac3d7323
9 changed files with 150 additions and 2 deletions
+36
View File
@@ -1165,6 +1165,20 @@ impl<W: LayoutElement> Layout<W> {
monitor.switch_workspace(idx);
}
pub fn switch_workspace_auto_back_and_forth(&mut self, idx: usize) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.switch_workspace_auto_back_and_forth(idx);
}
pub fn switch_workspace_previous(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.switch_workspace_previous();
}
pub fn consume_into_column(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
@@ -1221,8 +1235,12 @@ impl<W: LayoutElement> Layout<W> {
#[cfg(test)]
fn verify_invariants(&self) {
use std::collections::HashSet;
use crate::layout::monitor::WorkspaceSwitch;
let mut seen_workspace_id = HashSet::new();
let (monitors, &primary_idx, &active_monitor_idx) = match &self.monitor_set {
MonitorSet::Normal {
monitors,
@@ -1241,6 +1259,11 @@ impl<W: LayoutElement> Layout<W> {
"workspace options must be synchronized with layout"
);
assert!(
seen_workspace_id.insert(workspace.id()),
"workspace id must be unique"
);
workspace.verify_invariants();
}
@@ -1325,6 +1348,11 @@ impl<W: LayoutElement> Layout<W> {
"workspace options must be synchronized with layout"
);
assert!(
seen_workspace_id.insert(workspace.id()),
"workspace id must be unique"
);
workspace.verify_invariants();
}
}
@@ -1529,6 +1557,8 @@ impl<W: LayoutElement> Layout<W> {
.unwrap();
let target = &mut monitors[target_idx];
target.previous_workspace_id = Some(target.workspaces[target.active_workspace_idx].id());
// Insert the workspace after the currently active one. Unless the currently active one is
// the last empty workspace, then insert before.
let target_ws_idx = min(target.active_workspace_idx + 1, target.workspaces.len() - 1);
@@ -2017,6 +2047,8 @@ mod tests {
FocusWorkspaceDown,
FocusWorkspaceUp,
FocusWorkspace(#[proptest(strategy = "0..=4usize")] usize),
FocusWorkspaceAutoBackAndForth(#[proptest(strategy = "0..=4usize")] usize),
FocusWorkspacePrevious,
MoveWindowToWorkspaceDown,
MoveWindowToWorkspaceUp,
MoveWindowToWorkspace(#[proptest(strategy = "0..=4usize")] usize),
@@ -2219,6 +2251,10 @@ mod tests {
Op::FocusWorkspaceDown => layout.switch_workspace_down(),
Op::FocusWorkspaceUp => layout.switch_workspace_up(),
Op::FocusWorkspace(idx) => layout.switch_workspace(idx),
Op::FocusWorkspaceAutoBackAndForth(idx) => {
layout.switch_workspace_auto_back_and_forth(idx)
}
Op::FocusWorkspacePrevious => layout.switch_workspace_previous(),
Op::MoveWindowToWorkspaceDown => layout.move_to_workspace_down(),
Op::MoveWindowToWorkspaceUp => layout.move_to_workspace_up(),
Op::MoveWindowToWorkspace(idx) => layout.move_to_workspace(idx),