aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--niri-config/src/lib.rs11
-rw-r--r--niri-ipc/src/lib.rs16
-rw-r--r--src/input/mod.rs10
-rw-r--r--src/layout/mod.rs33
-rw-r--r--src/layout/scrolling.rs19
-rw-r--r--src/layout/workspace.rs12
6 files changed, 97 insertions, 4 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 2437fe66..069bb015 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -1241,6 +1241,12 @@ pub enum Action {
MoveColumnToMonitorRight,
MoveColumnToMonitorDown,
MoveColumnToMonitorUp,
+ SetWindowWidth(#[knuffel(argument, str)] SizeChange),
+ #[knuffel(skip)]
+ SetWindowWidthById {
+ id: u64,
+ change: SizeChange,
+ },
SetWindowHeight(#[knuffel(argument, str)] SizeChange),
#[knuffel(skip)]
SetWindowHeightById {
@@ -1373,6 +1379,11 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::MoveColumnToMonitorRight {} => Self::MoveColumnToMonitorRight,
niri_ipc::Action::MoveColumnToMonitorDown {} => Self::MoveColumnToMonitorDown,
niri_ipc::Action::MoveColumnToMonitorUp {} => Self::MoveColumnToMonitorUp,
+ niri_ipc::Action::SetWindowWidth { id: None, change } => Self::SetWindowWidth(change),
+ niri_ipc::Action::SetWindowWidth {
+ id: Some(id),
+ change,
+ } => Self::SetWindowWidthById { id, change },
niri_ipc::Action::SetWindowHeight { id: None, change } => Self::SetWindowHeight(change),
niri_ipc::Action::SetWindowHeight {
id: Some(id),
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index 6bbc00f2..bf66d3a8 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -362,6 +362,22 @@ pub enum Action {
MoveColumnToMonitorDown {},
/// Move the focused column to the monitor above.
MoveColumnToMonitorUp {},
+ /// Change the width of a window.
+ #[cfg_attr(
+ feature = "clap",
+ clap(about = "Change the width of the focused window")
+ )]
+ SetWindowWidth {
+ /// Id of the window whose width to set.
+ ///
+ /// If `None`, uses the focused window.
+ #[cfg_attr(feature = "clap", arg(long))]
+ id: Option<u64>,
+
+ /// How to change the width.
+ #[cfg_attr(feature = "clap", arg())]
+ change: SizeChange,
+ },
/// Change the height of a window.
#[cfg_attr(
feature = "clap",
diff --git a/src/input/mod.rs b/src/input/mod.rs
index 4e264b06..6e116d9e 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -1237,6 +1237,16 @@ impl State {
Action::SetColumnWidth(change) => {
self.niri.layout.set_column_width(change);
}
+ Action::SetWindowWidth(change) => {
+ self.niri.layout.set_window_width(None, change);
+ }
+ Action::SetWindowWidthById { id, change } => {
+ 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.set_window_width(Some(&window), change);
+ }
+ }
Action::SetWindowHeight(change) => {
self.niri.layout.set_window_height(None, change);
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 2b12c7bb..acdf1301 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -2592,6 +2592,29 @@ impl<W: LayoutElement> Layout<W> {
monitor.set_column_width(change);
}
+ pub fn set_window_width(&mut self, window: Option<&W::Id>, change: SizeChange) {
+ if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move {
+ if window.is_none() || window == Some(move_.tile.window().id()) {
+ return;
+ }
+ }
+
+ 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;
+ };
+ workspace.set_window_width(window, change);
+ }
+
pub fn set_window_height(&mut self, window: Option<&W::Id>, change: SizeChange) {
if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move {
if window.is_none() || window == Some(move_.tile.window().id()) {
@@ -4319,6 +4342,12 @@ mod tests {
},
MaximizeColumn,
SetColumnWidth(#[proptest(strategy = "arbitrary_size_change()")] SizeChange),
+ SetWindowWidth {
+ #[proptest(strategy = "proptest::option::of(1..=5usize)")]
+ id: Option<usize>,
+ #[proptest(strategy = "arbitrary_size_change()")]
+ change: SizeChange,
+ },
SetWindowHeight {
#[proptest(strategy = "proptest::option::of(1..=5usize)")]
id: Option<usize>,
@@ -4829,6 +4858,10 @@ mod tests {
}
Op::MaximizeColumn => layout.toggle_full_width(),
Op::SetColumnWidth(change) => layout.set_column_width(change),
+ Op::SetWindowWidth { id, change } => {
+ let id = id.filter(|id| layout.has_window(id));
+ layout.set_window_width(id.as_ref(), change);
+ }
Op::SetWindowHeight { id, change } => {
let id = id.filter(|id| layout.has_window(id));
layout.set_window_height(id.as_ref(), change);
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index 5d1b8234..c0de770a 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -1996,13 +1996,26 @@ impl<W: LayoutElement> ScrollingSpace<W> {
cancel_resize_for_column(&mut self.interactive_resize, col);
}
- pub fn set_column_width(&mut self, change: SizeChange) {
+ pub fn set_window_width(&mut self, window: Option<&W::Id>, change: SizeChange) {
if self.columns.is_empty() {
return;
}
- let col = &mut self.columns[self.active_column_idx];
- col.set_column_width(change, 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.set_column_width(change, tile_idx, true);
cancel_resize_for_column(&mut self.interactive_resize, col);
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 92900ff3..cd1a6261 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -998,7 +998,17 @@ impl<W: LayoutElement> Workspace<W> {
if self.floating_is_active.get() {
self.floating.set_window_width(None, change, true);
} else {
- self.scrolling.set_column_width(change);
+ self.scrolling.set_window_width(None, change);
+ }
+ }
+
+ pub fn set_window_width(&mut self, window: Option<&W::Id>, change: SizeChange) {
+ if window.map_or(self.floating_is_active.get(), |id| {
+ self.floating.has_window(id)
+ }) {
+ self.floating.set_window_width(window, change, true);
+ } else {
+ self.scrolling.set_window_width(window, change);
}
}