diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index 520a0417..cf55ecf1 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -1159,6 +1159,8 @@ pub enum Action { ResetWindowHeightById(u64), SwitchPresetColumnWidth, SwitchPresetWindowHeight, + #[knuffel(skip)] + SwitchPresetWindowHeightById(u64), MaximizeColumn, SetColumnWidth(#[knuffel(argument, str)] SizeChange), SwitchLayout(#[knuffel(argument, str)] LayoutSwitchTarget), @@ -1270,7 +1272,12 @@ impl From for Action { niri_ipc::Action::ResetWindowHeight { id: None } => Self::ResetWindowHeight, niri_ipc::Action::ResetWindowHeight { id: Some(id) } => Self::ResetWindowHeightById(id), niri_ipc::Action::SwitchPresetColumnWidth {} => Self::SwitchPresetColumnWidth, - niri_ipc::Action::SwitchPresetWindowHeight {} => Self::SwitchPresetWindowHeight, + niri_ipc::Action::SwitchPresetWindowHeight { id: None } => { + Self::SwitchPresetWindowHeight + } + niri_ipc::Action::SwitchPresetWindowHeight { id: Some(id) } => { + Self::SwitchPresetWindowHeightById(id) + } niri_ipc::Action::MaximizeColumn {} => Self::MaximizeColumn, niri_ipc::Action::SetColumnWidth { change } => Self::SetColumnWidth(change), niri_ipc::Action::SwitchLayout { layout } => Self::SwitchLayout(layout), diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 9d36ddea..13365522 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -351,7 +351,13 @@ pub enum Action { /// Switch between preset column widths. SwitchPresetColumnWidth {}, /// Switch between preset window heights. - SwitchPresetWindowHeight {}, + SwitchPresetWindowHeight { + /// Id of the window whose height to switch. + /// + /// If `None`, uses the focused window. + #[cfg_attr(feature = "clap", arg(long))] + id: Option, + }, /// Toggle the maximized state of the focused column. MaximizeColumn {}, /// Change the width of the focused column. diff --git a/src/input/mod.rs b/src/input/mod.rs index 6211535d..44832911 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1036,7 +1036,14 @@ impl State { self.niri.layout.toggle_width(); } Action::SwitchPresetWindowHeight => { - self.niri.layout.toggle_window_height(); + self.niri.layout.toggle_window_height(None); + } + Action::SwitchPresetWindowHeightById(id) => { + let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id); + let window = window.map(|(_, m)| m.window.clone()); + if let Some(window) = window { + self.niri.layout.toggle_window_height(Some(&window)); + } } Action::CenterColumn => { self.niri.layout.center_column(); diff --git a/src/layout/mod.rs b/src/layout/mod.rs index ea29311e..5ab81f03 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1951,11 +1951,21 @@ impl Layout { monitor.toggle_width(); } - pub fn toggle_window_height(&mut self) { - let Some(monitor) = self.active_monitor() else { + pub fn toggle_window_height(&mut self, window: Option<&W::Id>) { + let workspace = if let Some(window) = window { + Some( + self.workspaces_mut() + .find(|ws| ws.has_window(window)) + .unwrap(), + ) + } else { + self.active_workspace_mut() + }; + + let Some(workspace) = workspace else { return; }; - monitor.toggle_window_height(); + workspace.toggle_window_height(window); } pub fn toggle_full_width(&mut self) { @@ -3048,7 +3058,10 @@ mod tests { }, MoveColumnToOutput(#[proptest(strategy = "1..=5u8")] u8), SwitchPresetColumnWidth, - SwitchPresetWindowHeight, + SwitchPresetWindowHeight { + #[proptest(strategy = "proptest::option::of(1..=5usize)")] + id: Option, + }, MaximizeColumn, SetColumnWidth(#[proptest(strategy = "arbitrary_size_change()")] SizeChange), SetWindowHeight { @@ -3475,7 +3488,10 @@ mod tests { Op::MoveWorkspaceDown => layout.move_workspace_down(), Op::MoveWorkspaceUp => layout.move_workspace_up(), Op::SwitchPresetColumnWidth => layout.toggle_width(), - Op::SwitchPresetWindowHeight => layout.toggle_window_height(), + Op::SwitchPresetWindowHeight { id } => { + let id = id.filter(|id| layout.has_window(id)); + layout.toggle_window_height(id.as_ref()); + } Op::MaximizeColumn => layout.toggle_full_width(), Op::SetColumnWidth(change) => layout.set_column_width(change), Op::SetWindowHeight { id, change } => { @@ -4458,8 +4474,8 @@ mod tests { min_max_size: Default::default(), }, Op::ConsumeOrExpelWindowLeft, - Op::SwitchPresetWindowHeight, - Op::SwitchPresetWindowHeight, + Op::SwitchPresetWindowHeight { id: None }, + Op::SwitchPresetWindowHeight { id: None }, ]; for op in ops { op.apply(&mut layout); diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index b712d8e9..3227c9c4 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -740,10 +740,6 @@ impl Monitor { self.active_workspace().toggle_width(); } - pub fn toggle_window_height(&mut self) { - self.active_workspace().toggle_window_height(); - } - pub fn toggle_full_width(&mut self) { self.active_workspace().toggle_full_width(); } diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 5a0ce052..f6a659f8 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -2373,13 +2373,26 @@ impl Workspace { cancel_resize_for_column(&mut self.interactive_resize, col); } - pub fn toggle_window_height(&mut self) { + pub fn toggle_window_height(&mut self, window: Option<&W::Id>) { if self.columns.is_empty() { return; } - let col = &mut self.columns[self.active_column_idx]; - col.toggle_window_height(None, true); + let (col, tile_idx) = if let Some(window) = window { + self.columns + .iter_mut() + .find_map(|col| { + col.tiles + .iter() + .position(|tile| tile.window().id() == window) + .map(|tile_idx| (col, Some(tile_idx))) + }) + .unwrap() + } else { + (&mut self.columns[self.active_column_idx], None) + }; + + col.toggle_window_height(tile_idx, true); cancel_resize_for_column(&mut self.interactive_resize, col); }