diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-01-15 10:31:44 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-01-15 10:31:44 +0400 |
| commit | cc4acdf24a0864e061e7ea54d6b3589402f2082d (patch) | |
| tree | 193905d10622fca3b6838bb97015e4c7d4677706 /src/layout | |
| parent | 2506d43bb9b78adbfa291604616363089b4dcc21 (diff) | |
| download | niri-cc4acdf24a0864e061e7ea54d6b3589402f2082d.tar.gz niri-cc4acdf24a0864e061e7ea54d6b3589402f2082d.tar.bz2 niri-cc4acdf24a0864e061e7ea54d6b3589402f2082d.zip | |
Add move-column-to-workspace* binds
As opposed to move-window-to-workspace*
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/mod.rs | 37 | ||||
| -rw-r--r-- | src/layout/monitor.rs | 77 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 73 |
3 files changed, 186 insertions, 1 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index fbbd1292..5933b217 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -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, diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index a5c4d6dd..11eef73a 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -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)); } diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 3259785d..7405ecec 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -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 |
