diff --git a/resources/default-config.kdl b/resources/default-config.kdl index c383e6a98..602f0e975 100644 --- a/resources/default-config.kdl +++ b/resources/default-config.kdl @@ -107,6 +107,11 @@ preset-column-widths { // fixed 1920 } +// You can change the default width of the new windows. +default-column-width { proportion 0.5; } +// If you leave the brackets empty, the windows themselves will decide their initial width. +// default-column-width {} + // Set gaps around windows in logical pixels. gaps 16 diff --git a/src/config.rs b/src/config.rs index 51607efba..9509419e6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,6 +24,8 @@ pub struct Config { pub cursor: Cursor, #[knuffel(child, unwrap(children), default)] pub preset_column_widths: Vec, + #[knuffel(child)] + pub default_column_width: Option, #[knuffel(child, unwrap(argument), default = 16)] pub gaps: u16, #[knuffel( @@ -207,6 +209,9 @@ pub enum PresetWidth { Fixed(#[knuffel(argument)] i32), } +#[derive(knuffel::Decode, Debug, Clone, PartialEq)] +pub struct DefaultColumnWidth(#[knuffel(children)] pub Vec); + #[derive(knuffel::Decode, Debug, Default, PartialEq)] pub struct Binds(#[knuffel(children)] pub Vec); @@ -545,6 +550,8 @@ mod tests { fixed 1280 } + default-column-width { proportion 0.25; } + gaps 8 screenshot-path "~/Screenshots/screenshot.png" @@ -622,6 +629,7 @@ mod tests { PresetWidth::Fixed(960), PresetWidth::Fixed(1280), ], + default_column_width: Some(DefaultColumnWidth(vec![PresetWidth::Proportion(0.25)])), gaps: 8, screenshot_path: Some(String::from("~/Screenshots/screenshot.png")), binds: Binds(vec![ diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index dfc656482..7e01b5dec 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -18,7 +18,6 @@ use smithay::wayland::shm::{ShmHandler, ShmState}; use smithay::{delegate_compositor, delegate_shm}; use super::xdg_shell; -use crate::layout::ColumnWidth; use crate::niri::{ClientState, State}; impl CompositorHandler for State { @@ -99,12 +98,7 @@ impl CompositorHandler for State { let window = entry.remove(); window.on_commit(); - if let Some(output) = self - .niri - .layout - .add_window(window, true, ColumnWidth::default()) - .cloned() - { + if let Some(output) = self.niri.layout.add_window(window, true, None).cloned() { self.niri.queue_redraw(output); } return; diff --git a/src/layout.rs b/src/layout.rs index 663a5fc32..96b52fb04 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -208,6 +208,8 @@ struct Options { focus_ring: config::FocusRing, /// Column widths that `toggle_width()` switches between. preset_widths: Vec, + /// Initial width for new windows. + default_width: Option, } impl Default for Options { @@ -220,6 +222,7 @@ impl Default for Options { ColumnWidth::Proportion(0.5), ColumnWidth::Proportion(2. / 3.), ], + default_width: None, } } } @@ -238,10 +241,19 @@ impl Options { .collect() }; + // Missing default_column_width maps to Some(ColumnWidth::Proportion(0.5)), + // while present, but empty, maps to None. + let default_width = config + .default_column_width + .as_ref() + .map(|w| w.0.first().copied().map(ColumnWidth::from)) + .unwrap_or(Some(ColumnWidth::Proportion(0.5))); + Self { gaps: config.gaps.into(), focus_ring: config.focus_ring, preset_widths, + default_width, } } } @@ -457,12 +469,6 @@ impl ColumnWidth { } } -impl Default for ColumnWidth { - fn default() -> Self { - Self::Proportion(0.5) - } -} - impl Layout { pub fn new(config: &Config) -> Self { Self { @@ -631,7 +637,16 @@ impl Layout { /// Adds a new window to the layout. /// /// Returns an output that the window was added to, if there were any outputs. - pub fn add_window(&mut self, window: W, activate: bool, width: ColumnWidth) -> Option<&Output> { + pub fn add_window( + &mut self, + window: W, + activate: bool, + width: Option, + ) -> Option<&Output> { + let width = width + .or(self.options.default_width) + .unwrap_or_else(|| ColumnWidth::Fixed(window.geometry().size.w)); + match &mut self.monitor_set { MonitorSet::Normal { monitors, @@ -1992,9 +2007,14 @@ impl Workspace { } pub fn configure_new_window(&self, window: &Window) { - let width = ColumnWidth::default().resolve(&self.options, self.working_area.size.w); + let width = if let Some(width) = self.options.default_width { + max(1, width.resolve(&self.options, self.working_area.size.w)) + } else { + 0 + }; + let height = self.working_area.size.h - self.options.gaps * 2; - let size = Size::from((max(width, 1), max(height, 1))); + let size = Size::from((width, max(height, 1))); let bounds = self.toplevel_bounds(); @@ -2332,10 +2352,11 @@ impl Workspace { return; } + let width = source_column.width; let window = source_column.windows[source_column.active_window_idx].clone(); self.remove_window(&window); - self.add_window(window, true, ColumnWidth::default()); + self.add_window(window, true, width); } fn view_pos(&self) -> i32 { @@ -2749,7 +2770,9 @@ impl Column { let width = match self.width { ColumnWidth::Proportion(x) if x == 1. => { // FIXME: would be good to restore to previous width here. - ColumnWidth::default() + self.options + .default_width + .unwrap_or(ColumnWidth::Proportion(0.5)) } _ => ColumnWidth::Proportion(1.), }; @@ -3111,7 +3134,7 @@ mod tests { } let win = TestWindow::new(id, bbox); - layout.add_window(win, activate, ColumnWidth::default()); + layout.add_window(win, activate, None); } Op::CloseWindow(id) => { let dummy = TestWindow::new(id, Rectangle::default());