Add move-column-to-workspace* binds

As opposed to move-window-to-workspace*
This commit is contained in:
Ivan Molodetskikh
2024-01-15 10:31:44 +04:00
parent 2506d43bb9
commit cc4acdf24a
5 changed files with 205 additions and 1 deletions
+3
View File
@@ -408,6 +408,9 @@ pub enum Action {
MoveWindowToWorkspaceDown,
MoveWindowToWorkspaceUp,
MoveWindowToWorkspace(#[knuffel(argument)] u8),
MoveColumnToWorkspaceDown,
MoveColumnToWorkspaceUp,
MoveColumnToWorkspace(#[knuffel(argument)] u8),
MoveWorkspaceDown,
MoveWorkspaceUp,
FocusMonitorLeft,
+16
View File
@@ -458,6 +458,22 @@ impl State {
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveColumnToWorkspaceDown => {
self.niri.layout.move_column_to_workspace_down();
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveColumnToWorkspaceUp => {
self.niri.layout.move_column_to_workspace_up();
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::MoveColumnToWorkspace(idx) => {
let idx = idx.saturating_sub(1) as usize;
self.niri.layout.move_column_to_workspace(idx);
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::FocusWorkspaceDown => {
self.niri.layout.switch_workspace_down();
// FIXME: granular
+37
View File
@@ -897,6 +897,27 @@ impl<W: LayoutElement> Layout<W> {
monitor.move_to_workspace(idx);
}
pub fn move_column_to_workspace_up(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.move_column_to_workspace_up();
}
pub fn move_column_to_workspace_down(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.move_column_to_workspace_down();
}
pub fn move_column_to_workspace(&mut self, idx: usize) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.move_column_to_workspace(idx);
}
pub fn switch_workspace_up(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
@@ -1608,6 +1629,9 @@ mod tests {
MoveWindowToWorkspaceDown,
MoveWindowToWorkspaceUp,
MoveWindowToWorkspace(#[proptest(strategy = "0..=4usize")] usize),
MoveColumnToWorkspaceDown,
MoveColumnToWorkspaceUp,
MoveColumnToWorkspace(#[proptest(strategy = "0..=4usize")] usize),
MoveWorkspaceDown,
MoveWorkspaceUp,
MoveWindowToOutput(#[proptest(strategy = "1..=5u8")] u8),
@@ -1729,6 +1753,9 @@ mod tests {
Op::MoveWindowToWorkspaceDown => layout.move_to_workspace_down(),
Op::MoveWindowToWorkspaceUp => layout.move_to_workspace_up(),
Op::MoveWindowToWorkspace(idx) => layout.move_to_workspace(idx),
Op::MoveColumnToWorkspaceDown => layout.move_column_to_workspace_down(),
Op::MoveColumnToWorkspaceUp => layout.move_column_to_workspace_up(),
Op::MoveColumnToWorkspace(idx) => layout.move_column_to_workspace(idx),
Op::MoveWindowToOutput(id) => {
let name = format!("output{id}");
let Some(output) = layout.outputs().find(|o| o.name() == name).cloned() else {
@@ -1855,6 +1882,11 @@ mod tests {
Op::MoveWindowToWorkspace(1),
Op::MoveWindowToWorkspace(2),
Op::MoveWindowToWorkspace(3),
Op::MoveColumnToWorkspaceDown,
Op::MoveColumnToWorkspaceUp,
Op::MoveColumnToWorkspace(1),
Op::MoveColumnToWorkspace(2),
Op::MoveColumnToWorkspace(3),
Op::MoveWindowDown,
Op::MoveWindowDownOrToWorkspaceDown,
Op::MoveWindowUp,
@@ -1977,6 +2009,11 @@ mod tests {
Op::MoveWindowToWorkspace(1),
Op::MoveWindowToWorkspace(2),
Op::MoveWindowToWorkspace(3),
Op::MoveColumnToWorkspaceDown,
Op::MoveColumnToWorkspaceUp,
Op::MoveColumnToWorkspace(1),
Op::MoveColumnToWorkspace(2),
Op::MoveColumnToWorkspace(3),
Op::MoveWindowDown,
Op::MoveWindowDownOrToWorkspaceDown,
Op::MoveWindowUp,
+76 -1
View File
@@ -12,7 +12,7 @@ use smithay::output::Output;
use smithay::utils::{Logical, Point, Rectangle, Scale};
use super::workspace::{
compute_working_area, ColumnWidth, OutputId, Workspace, WorkspaceRenderElement,
compute_working_area, Column, ColumnWidth, OutputId, Workspace, WorkspaceRenderElement,
};
use super::{LayoutElement, Options};
use crate::animation::Animation;
@@ -127,6 +127,25 @@ impl<W: LayoutElement> Monitor<W> {
}
}
pub fn add_column(&mut self, workspace_idx: usize, column: Column<W>, activate: bool) {
let workspace = &mut self.workspaces[workspace_idx];
workspace.add_column(column, activate);
// After adding a new window, workspace becomes this output's own.
workspace.original_output = OutputId::new(&self.output);
if workspace_idx == self.workspaces.len() - 1 {
// Insert a new empty workspace.
let ws = Workspace::new(self.output.clone(), self.options.clone());
self.workspaces.push(ws);
}
if activate {
self.activate_workspace(workspace_idx);
}
}
fn clean_up_workspaces(&mut self) {
assert!(self.workspace_switch.is_none());
@@ -323,6 +342,62 @@ impl<W: LayoutElement> Monitor<W> {
self.clean_up_workspaces();
}
pub fn move_column_to_workspace_up(&mut self) {
let source_workspace_idx = self.active_workspace_idx;
let new_idx = source_workspace_idx.saturating_sub(1);
if new_idx == source_workspace_idx {
return;
}
let workspace = &mut self.workspaces[source_workspace_idx];
if workspace.columns.is_empty() {
return;
}
let column = workspace.remove_column_by_idx(workspace.active_column_idx);
self.add_column(new_idx, column, true);
}
pub fn move_column_to_workspace_down(&mut self) {
let source_workspace_idx = self.active_workspace_idx;
let new_idx = min(source_workspace_idx + 1, self.workspaces.len() - 1);
if new_idx == source_workspace_idx {
return;
}
let workspace = &mut self.workspaces[source_workspace_idx];
if workspace.columns.is_empty() {
return;
}
let column = workspace.remove_column_by_idx(workspace.active_column_idx);
self.add_column(new_idx, column, true);
}
pub fn move_column_to_workspace(&mut self, idx: usize) {
let source_workspace_idx = self.active_workspace_idx;
let new_idx = min(idx, self.workspaces.len() - 1);
if new_idx == source_workspace_idx {
return;
}
let workspace = &mut self.workspaces[source_workspace_idx];
if workspace.columns.is_empty() {
return;
}
let column = workspace.remove_column_by_idx(workspace.active_column_idx);
self.add_column(new_idx, column, true);
// Don't animate this action.
self.workspace_switch = None;
self.clean_up_workspaces();
}
pub fn switch_workspace_up(&mut self) {
self.activate_workspace(self.active_workspace_idx.saturating_sub(1));
}
+73
View File
@@ -574,6 +574,43 @@ impl<W: LayoutElement> Workspace<W> {
}
}
pub fn add_column(&mut self, mut column: Column<W>, activate: bool) {
for tile in &column.tiles {
self.enter_output_for_window(tile.window());
}
let was_empty = self.columns.is_empty();
let idx = if self.columns.is_empty() {
0
} else {
self.active_column_idx + 1
};
column.set_view_size(self.view_size, self.working_area);
let width = column.width();
self.columns.insert(idx, column);
if activate {
// If this is the first window on an empty workspace, skip the animation from whatever
// view_offset was left over.
if was_empty {
if self.options.center_focused_column == CenterFocusedColumn::Always {
self.view_offset =
-(self.working_area.size.w - width) / 2 - self.working_area.loc.x;
} else {
// Try to make the code produce a left-aligned offset, even in presence of left
// exclusive zones.
self.view_offset = self.compute_new_view_offset_for_column(self.column_x(0), 0);
}
self.view_offset_anim = None;
}
self.activate_column(idx);
self.activate_prev_column_on_removal = true;
}
}
pub fn remove_window_by_idx(&mut self, column_idx: usize, window_idx: usize) -> W {
let column = &mut self.columns[column_idx];
let window = column.tiles.remove(window_idx).into_window();
@@ -618,6 +655,42 @@ impl<W: LayoutElement> Workspace<W> {
window
}
pub fn remove_column_by_idx(&mut self, column_idx: usize) -> Column<W> {
let column = self.columns.remove(column_idx);
if let Some(output) = &self.output {
for tile in &column.tiles {
tile.window().output_leave(output);
}
}
if column_idx + 1 == self.active_column_idx {
// The previous column, that we were going to activate upon removal of the active
// column, has just been itself removed.
self.activate_prev_column_on_removal = false;
}
// FIXME: activate_column below computes current view position to compute the new view
// position, which can include the column we're removing here. This leads to unwanted
// view jumps.
if self.columns.is_empty() {
return column;
}
if self.active_column_idx > column_idx
|| (self.active_column_idx == column_idx && self.activate_prev_column_on_removal)
{
// A column to the left was removed; preserve the current position.
// FIXME: preserve activate_prev_column_on_removal.
// Or, the active column was removed, and we needed to activate the previous column.
self.activate_column(self.active_column_idx.saturating_sub(1));
} else {
self.activate_column(min(self.active_column_idx, self.columns.len() - 1));
}
column
}
pub fn remove_window(&mut self, window: &W) {
let column_idx = self
.columns