diff options
| -rw-r--r-- | resources/default-config.kdl | 13 | ||||
| -rw-r--r-- | src/config.rs | 23 | ||||
| -rw-r--r-- | src/handlers/compositor.rs | 14 | ||||
| -rw-r--r-- | src/handlers/layer_shell.rs | 6 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 2 | ||||
| -rw-r--r-- | src/handlers/xdg_shell.rs | 25 | ||||
| -rw-r--r-- | src/input.rs | 74 | ||||
| -rw-r--r-- | src/layout.rs | 456 | ||||
| -rw-r--r-- | src/main.rs | 2 | ||||
| -rw-r--r-- | src/niri.rs | 47 |
10 files changed, 424 insertions, 238 deletions
diff --git a/resources/default-config.kdl b/resources/default-config.kdl index 11d225cb..926d0def 100644 --- a/resources/default-config.kdl +++ b/resources/default-config.kdl @@ -93,6 +93,19 @@ cursor { // If the client will specifically ask for CSD, the request will be honored. // prefer-no-csd +// You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between. +preset-column-widths { + // Proportion sets the width as a fraction of the output width, taking gaps into account. + // For example, you can perfectly fit four windows sized "proportion 0.25" on an output. + // The default preset widths are 1/3, 1/2 and 2/3 of the output. + proportion 0.333 + proportion 0.5 + proportion 0.667 + + // Fixed sets the width in logical pixels exactly. + // fixed 1920 +} + binds { // Keys consist of modifiers separated by + signs, followed by an XKB key name // in the end. To find an XKB name for a particular key, you may use a program diff --git a/src/config.rs b/src/config.rs index 730a0f4b..bb8cfcf6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,6 +22,8 @@ pub struct Config { pub prefer_no_csd: bool, #[knuffel(child, default)] pub cursor: Cursor, + #[knuffel(child, unwrap(children), default)] + pub preset_column_widths: Vec<PresetWidth>, #[knuffel(child, default)] pub binds: Binds, #[knuffel(child, default)] @@ -125,7 +127,7 @@ pub struct SpawnAtStartup { pub command: Vec<String>, } -#[derive(knuffel::Decode, Debug, Clone, PartialEq)] +#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] pub struct FocusRing { #[knuffel(child)] pub off: bool, @@ -189,6 +191,12 @@ impl Default for Cursor { } } +#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +pub enum PresetWidth { + Proportion(#[knuffel(argument)] f64), + Fixed(#[knuffel(argument)] i32), +} + #[derive(knuffel::Decode, Debug, Default, PartialEq)] pub struct Binds(#[knuffel(children)] pub Vec<Bind>); @@ -513,6 +521,13 @@ mod tests { xcursor-size 16 } + preset-column-widths { + proportion 0.25 + proportion 0.5 + fixed 960 + fixed 1280 + } + binds { Mod+T { spawn "alacritty"; } Mod+Q { close-window; } @@ -580,6 +595,12 @@ mod tests { xcursor_theme: String::from("breeze_cursors"), xcursor_size: 16, }, + preset_column_widths: vec![ + PresetWidth::Proportion(0.25), + PresetWidth::Proportion(0.5), + PresetWidth::Fixed(960), + PresetWidth::Fixed(1280), + ], binds: Binds(vec![ Bind { key: Key { diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index b77ef829..d8d93d9c 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -87,7 +87,7 @@ impl CompositorHandler for State { let window = entry.remove(); window.on_commit(); - if let Some(output) = self.niri.monitor_set.add_window(window, true).cloned() { + if let Some(output) = self.niri.layout.add_window(window, true).cloned() { self.niri.queue_redraw(output); } return; @@ -100,7 +100,7 @@ impl CompositorHandler for State { } // This is a commit of a previously-mapped root or a non-toplevel root. - if let Some((window, output)) = self.niri.monitor_set.find_window_and_output(surface) { + if let Some((window, output)) = self.niri.layout.find_window_and_output(surface) { // This is a commit of a previously-mapped toplevel. window.on_commit(); @@ -110,14 +110,14 @@ impl CompositorHandler for State { if !is_mapped { // The toplevel got unmapped. - self.niri.monitor_set.remove_window(&window); + self.niri.layout.remove_window(&window); self.niri.unmapped_windows.insert(surface.clone(), window); self.niri.queue_redraw(output); return; } // The toplevel remains mapped. - self.niri.monitor_set.update_window(&window); + self.niri.layout.update_window(&window); self.niri.queue_redraw(output); return; @@ -127,10 +127,10 @@ impl CompositorHandler for State { } // This is a commit of a non-root or a non-toplevel root. - let root_window_output = self.niri.monitor_set.find_window_and_output(&root_surface); + let root_window_output = self.niri.layout.find_window_and_output(&root_surface); if let Some((window, output)) = root_window_output { window.on_commit(); - self.niri.monitor_set.update_window(&window); + self.niri.layout.update_window(&window); self.niri.queue_redraw(output); return; } @@ -139,7 +139,7 @@ impl CompositorHandler for State { self.popups_handle_commit(surface); if let Some(popup) = self.niri.popups.find_popup(surface) { if let Ok(root) = find_popup_root_surface(&popup) { - let root_window_output = self.niri.monitor_set.find_window_and_output(&root); + let root_window_output = self.niri.layout.find_window_and_output(&root); if let Some((_window, output)) = root_window_output { self.niri.queue_redraw(output); } diff --git a/src/handlers/layer_shell.rs b/src/handlers/layer_shell.rs index c426d321..6e0ef318 100644 --- a/src/handlers/layer_shell.rs +++ b/src/handlers/layer_shell.rs @@ -26,7 +26,7 @@ impl WlrLayerShellHandler for State { let output = wl_output .as_ref() .and_then(Output::from_resource) - .or_else(|| self.niri.monitor_set.active_output().cloned()) + .or_else(|| self.niri.layout.active_output().cloned()) .unwrap(); let mut map = layer_map_for_output(&output); map.map_layer(&LayerSurface::new(surface, namespace)) @@ -35,7 +35,7 @@ impl WlrLayerShellHandler for State { fn layer_destroyed(&mut self, surface: WlrLayerSurface) { let output = if let Some((output, mut map, layer)) = - self.niri.monitor_set.outputs().find_map(|o| { + self.niri.layout.outputs().find_map(|o| { let map = layer_map_for_output(o); let layer = map .layers() @@ -59,7 +59,7 @@ impl State { pub fn layer_shell_handle_commit(&mut self, surface: &WlSurface) { let Some(output) = self .niri - .monitor_set + .layout .outputs() .find(|o| { let map = layer_map_for_output(o); diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 546d22e0..87d4af4d 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -65,7 +65,7 @@ impl InputMethodHandler for State { } fn parent_geometry(&self, parent: &WlSurface) -> Rectangle<i32, Logical> { self.niri - .monitor_set + .layout .find_window_and_output(parent) .map(|(window, _)| window.geometry()) .unwrap_or_default() diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index e8cee1b5..c5af09a9 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -1,4 +1,4 @@ -use smithay::desktop::{find_popup_root_surface, layer_map_for_output, PopupKind, Window}; +use smithay::desktop::{find_popup_root_surface, PopupKind, Window}; use smithay::output::Output; use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::{self, ResizeEdge}; @@ -15,7 +15,6 @@ use smithay::wayland::shell::xdg::{ }; use smithay::{delegate_kde_decoration, delegate_xdg_decoration, delegate_xdg_shell}; -use crate::layout::configure_new_window; use crate::niri::State; impl XdgShellHandler for State { @@ -28,9 +27,9 @@ impl XdgShellHandler for State { let window = Window::new(surface); // Tell the surface the preferred size and bounds for its likely output. - let output = self.niri.monitor_set.active_output().unwrap(); - let working_area = layer_map_for_output(output).non_exclusive_zone(); - configure_new_window(working_area, &window); + if let Some(ws) = self.niri.layout.active_workspace() { + ws.configure_new_window(&window); + } // At the moment of creation, xdg toplevels must have no buffer. let existing = self.niri.unmapped_windows.insert(wl_surface, window); @@ -106,18 +105,18 @@ impl XdgShellHandler for State { // independently from its buffer size if let Some((window, current_output)) = self .niri - .monitor_set + .layout .find_window_and_output(surface.wl_surface()) { if let Some(requested_output) = wl_output.as_ref().and_then(Output::from_resource) { if requested_output != current_output { self.niri - .monitor_set + .layout .move_window_to_output(window.clone(), &requested_output); } } - self.niri.monitor_set.set_fullscreen(&window, true); + self.niri.layout.set_fullscreen(&window, true); } } @@ -129,10 +128,10 @@ impl XdgShellHandler for State { fn unfullscreen_request(&mut self, surface: ToplevelSurface) { if let Some((window, _)) = self .niri - .monitor_set + .layout .find_window_and_output(surface.wl_surface()) { - self.niri.monitor_set.set_fullscreen(&window, false); + self.niri.layout.set_fullscreen(&window, false); } } @@ -149,16 +148,16 @@ impl XdgShellHandler for State { let (window, output) = self .niri - .monitor_set + .layout .find_window_and_output(surface.wl_surface()) .unwrap(); - self.niri.monitor_set.remove_window(&window); + self.niri.layout.remove_window(&window); self.niri.queue_redraw(output); } fn popup_destroyed(&mut self, surface: PopupSurface) { if let Ok(root) = find_popup_root_surface(&surface.into()) { - let root_window_output = self.niri.monitor_set.find_window_and_output(&root); + let root_window_output = self.niri.layout.find_window_and_output(&root); if let Some((_window, output)) = root_window_output { self.niri.queue_redraw(output); } diff --git a/src/input.rs b/src/input.rs index b76a98af..033b90f4 100644 --- a/src/input.rs +++ b/src/input.rs @@ -101,9 +101,7 @@ impl State { // doesn't always trigger due to damage, etc. So run it here right before it might prove // important. Besides, animations affect the input, so it's best to have up-to-date values // here. - self.niri - .monitor_set - .advance_animations(get_monotonic_time()); + self.niri.layout.advance_animations(get_monotonic_time()); let comp_mod = self.backend.mod_key(); @@ -150,7 +148,7 @@ impl State { } } Action::Screenshot => { - let active = self.niri.monitor_set.active_output().cloned(); + let active = self.niri.layout.active_output().cloned(); if let Some(active) = active { if let Some(renderer) = self.backend.renderer() { if let Err(err) = self.niri.screenshot(renderer, &active) { @@ -160,144 +158,144 @@ impl State { } } Action::CloseWindow => { - if let Some(window) = self.niri.monitor_set.focus() { + if let Some(window) = self.niri.layout.focus() { window.toplevel().send_close(); } } Action::FullscreenWindow => { - let focus = self.niri.monitor_set.focus().cloned(); + let focus = self.niri.layout.focus().cloned(); if let Some(window) = focus { - self.niri.monitor_set.toggle_fullscreen(&window); + self.niri.layout.toggle_fullscreen(&window); } } Action::MoveColumnLeft => { - self.niri.monitor_set.move_left(); + self.niri.layout.move_left(); // FIXME: granular self.niri.queue_redraw_all(); } Action::MoveColumnRight => { - self.niri.monitor_set.move_right(); + self.niri.layout.move_right(); // FIXME: granular self.niri.queue_redraw_all(); } Action::MoveWindowDown => { - self.niri.monitor_set.move_down(); + self.niri.layout.move_down(); // FIXME: granular self.niri.queue_redraw_all(); } Action::MoveWindowUp => { - self.niri.monitor_set.move_up(); + self.niri.layout.move_up(); // FIXME: granular self.niri.queue_redraw_all(); } Action::FocusColumnLeft => { - self.niri.monitor_set.focus_left(); + self.niri.layout.focus_left(); } Action::FocusColumnRight => { - self.niri.monitor_set.focus_right(); + self.niri.layout.focus_right(); } Action::FocusWindowDown => { - self.niri.monitor_set.focus_down(); + self.niri.layout.focus_down(); } Action::FocusWindowUp => { - self.niri.monitor_set.focus_up(); + self.niri.layout.focus_up(); } Action::MoveWindowToWorkspaceDown => { - self.niri.monitor_set.move_to_workspace_down(); + self.niri.layout.move_to_workspace_down(); // FIXME: granular self.niri.queue_redraw_all(); } Action::MoveWindowToWorkspaceUp => { - self.niri.monitor_set.move_to_workspace_up(); + self.niri.layout.move_to_workspace_up(); // FIXME: granular self.niri.queue_redraw_all(); } Action::MoveWindowToWorkspace(idx) => { - self.niri.monitor_set.move_to_workspace(idx); + self.niri.layout.move_to_workspace(idx); // FIXME: granular self.niri.queue_redraw_all(); } Action::FocusWorkspaceDown => { - self.niri.monitor_set.switch_workspace_down(); + self.niri.layout.switch_workspace_down(); // FIXME: granular self.niri.queue_redraw_all(); } Action::FocusWorkspaceUp => { - self.niri.monitor_set.switch_workspace_up(); + self.niri.layout.switch_workspace_up(); // FIXME: granular self.niri.queue_redraw_all(); } Action::FocusWorkspace(idx) => { - self.niri.monitor_set.switch_workspace(idx); + self.niri.layout.switch_workspace(idx); // FIXME: granular self.niri.queue_redraw_all(); } Action::ConsumeWindowIntoColumn => { - self.niri.monitor_set.consume_into_column(); + self.niri.layout.consume_into_column(); // FIXME: granular self.niri.queue_redraw_all(); } Action::ExpelWindowFromColumn => { - self.niri.monitor_set.expel_from_column(); + self.niri.layout.expel_from_column(); // FIXME: granular self.niri.queue_redraw_all(); } Action::SwitchPresetColumnWidth => { - self.niri.monitor_set.toggle_width(); + self.niri.layout.toggle_width(); } Action::MaximizeColumn => { - self.niri.monitor_set.toggle_full_width(); + self.niri.layout.toggle_full_width(); } Action::FocusMonitorLeft => { if let Some(output) = self.niri.output_left() { - self.niri.monitor_set.focus_output(&output); + self.niri.layout.focus_output(&output); self.move_cursor_to_output(&output); } } Action::FocusMonitorRight => { if let Some(output) = self.niri.output_right() { - self.niri.monitor_set.focus_output(&output); + self.niri.layout.focus_output(&output); self.move_cursor_to_output(&output); } } Action::FocusMonitorDown => { if let Some(output) = self.niri.output_down() { - self.niri.monitor_set.focus_output(&output); + self.niri.layout.focus_output(&output); self.move_cursor_to_output(&output); } } Action::FocusMonitorUp => { if let Some(output) = self.niri.output_up() { - self.niri.monitor_set.focus_output(&output); + self.niri.layout.focus_output(&output); self.move_cursor_to_output(&output); } } Action::MoveWindowToMonitorLeft => { if let Some(output) = self.niri.output_left() { - self.niri.monitor_set.move_to_output(&output); + self.niri.layout.move_to_output(&output); self.move_cursor_to_output(&output); } } Action::MoveWindowToMonitorRight => { if let Some(output) = self.niri.output_right() { - self.niri.monitor_set.move_to_output(&output); + self.niri.layout.move_to_output(&output); self.move_cursor_to_output(&output); } } Action::MoveWindowToMonitorDown => { if let Some(output) = self.niri.output_down() { - self.niri.monitor_set.move_to_output(&output); + self.niri.layout.move_to_output(&output); self.move_cursor_to_output(&output); } } Action::MoveWindowToMonitorUp => { if let Some(output) = self.niri.output_up() { - self.niri.monitor_set.move_to_output(&output); + self.niri.layout.move_to_output(&output); self.move_cursor_to_output(&output); } } Action::SetColumnWidth(change) => { - self.niri.monitor_set.set_column_width(change); + self.niri.layout.set_column_width(change); } } } @@ -415,9 +413,9 @@ impl State { if ButtonState::Pressed == button_state && !pointer.is_grabbed() { if let Some(window) = self.niri.window_under_cursor() { let window = window.clone(); - self.niri.monitor_set.activate_window(&window); + self.niri.layout.activate_window(&window); } else if let Some(output) = self.niri.output_under_cursor() { - self.niri.monitor_set.activate_output(&output); + self.niri.layout.activate_output(&output); } }; @@ -546,9 +544,9 @@ impl State { if !pointer.is_grabbed() { if let Some(window) = self.niri.window_under_cursor() { let window = window.clone(); - self.niri.monitor_set.activate_window(&window); + self.niri.layout.activate_window(&window); } else if let Some(output) = self.niri.output_under_cursor() { - self.niri.monitor_set.activate_output(&output); + self.niri.layout.activate_output(&output); } }; } diff --git a/src/layout.rs b/src/layout.rs index 308af207..a8a935f2 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -31,6 +31,7 @@ use std::cmp::{max, min}; use std::mem; +use std::rc::Rc; use std::time::Duration; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; @@ -52,14 +53,9 @@ use smithay::wayland::compositor::with_states; use smithay::wayland::shell::xdg::SurfaceCachedState; use crate::animation::Animation; -use crate::config::{Color, Config, SizeChange}; +use crate::config::{self, Color, Config, PresetWidth, SizeChange}; const PADDING: i32 = 16; -const WIDTH_PROPORTIONS: [ColumnWidth; 3] = [ - ColumnWidth::Proportion(1. / 3.), - ColumnWidth::Proportion(0.5), - ColumnWidth::Proportion(2. / 3.), -]; #[derive(Debug, Clone, PartialEq, Eq)] pub struct OutputId(String); @@ -82,7 +78,15 @@ pub trait LayoutElement: SpaceElement + PartialEq + Clone { } #[derive(Debug)] -pub enum MonitorSet<W: LayoutElement> { +pub struct Layout<W: LayoutElement> { + /// Monitors and workspaes in the layout. + monitor_set: MonitorSet<W>, + /// Configurable properties of the layout. + options: Rc<Options>, +} + +#[derive(Debug)] +enum MonitorSet<W: LayoutElement> { /// At least one output is connected. Normal { /// Connected monitors. @@ -93,7 +97,10 @@ pub enum MonitorSet<W: LayoutElement> { active_monitor_idx: usize, }, /// No outputs are connected, and these are the workspaces. - NoOutputs(Vec<Workspace<W>>), + NoOutputs { + /// The workspaces. + workspaces: Vec<Workspace<W>>, + }, } #[derive(Debug)] @@ -106,6 +113,8 @@ pub struct Monitor<W: LayoutElement> { active_workspace_idx: usize, /// Animation for workspace switching. workspace_idx_anim: Option<Animation>, + /// Configurable properties of the layout. + options: Rc<Options>, } #[derive(Debug)] @@ -155,6 +164,9 @@ pub struct Workspace<W: LayoutElement> { /// contrast to tabs in Firefox, for example), we can track this as a bool, rather than an /// index of the previous column to activate. activate_prev_column_on_removal: bool, + + /// Configurable properties of the layout. + options: Rc<Options>, } #[derive(Debug)] @@ -166,8 +178,49 @@ struct FocusRing { inactive_color: Color, } +#[derive(Debug, PartialEq)] +struct Options { + focus_ring: config::FocusRing, + /// Column widths that `toggle_width()` switches between. + preset_widths: Vec<ColumnWidth>, +} + +impl Default for Options { + fn default() -> Self { + Self { + focus_ring: Default::default(), + preset_widths: vec![ + ColumnWidth::Proportion(1. / 3.), + ColumnWidth::Proportion(0.5), + ColumnWidth::Proportion(2. / 3.), + ], + } + } +} + +impl Options { + fn from_config(config: &Config) -> Self { + let preset_column_widths = &config.preset_column_widths; + + let preset_widths = if preset_column_widths.is_empty() { + Options::default().preset_widths + } else { + preset_column_widths + .iter() + .copied() + .map(ColumnWidth::from) + .collect() + }; + + Self { + focus_ring: config.focus_ring, + preset_widths, + } + } +} + /// Width of a column. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] enum ColumnWidth { /// Proportion of the current view width. Proportion(f64), @@ -175,11 +228,20 @@ enum ColumnWidth { /// /// This is separate from Proportion in order to be able to reliably cycle between preset /// proportions. - PresetProportion(usize), + Preset(usize), /// Fixed width in logical pixels. Fixed(i32), } +impl From<PresetWidth> for ColumnWidth { + fn from(value: PresetWidth) -> Self { + match value { + PresetWidth::Proportion(p) => Self::Proportion(p.clamp(0., 10000.)), + PresetWidth::Fixed(f) => Self::Fixed(f.clamp(1, 100000)), + } + } +} + #[derive(Debug)] struct Column<W: LayoutElement> { /// Windows in this column. @@ -201,6 +263,9 @@ struct Column<W: LayoutElement> { /// Latest known working area for this column's workspace. working_area: Rectangle<i32, Logical>, + + /// Configurable properties of the layout. + options: Rc<Options>, } impl OutputId { @@ -277,23 +342,23 @@ impl FocusRing { } } -impl Default for FocusRing { - fn default() -> Self { +impl FocusRing { + fn new(config: config::FocusRing) -> Self { Self { buffer: SolidColorBuffer::new((0, 0), [0., 0., 0., 0.]), - is_off: true, - width: 0, - active_color: Color::default(), - inactive_color: Color::default(), + is_off: config.off, + width: config.width.into(), + active_color: config.active_color, + inactive_color: config.inactive_color, } } } impl ColumnWidth { - fn resolve(self, view_width: i32) -> i32 { + fn resolve(self, options: &Options, view_width: i32) -> i32 { match self { ColumnWidth::Proportion(proportion) => (view_width as f64 * proportion).floor() as i32, - ColumnWidth::PresetProportion(idx) => WIDTH_PROPORTIONS[idx].resolve(view_width), + ColumnWidth::Preset(idx) => options.preset_widths[idx].resolve(options, view_width), // FIXME: remove this PADDING from here after redesigning how padding works. ColumnWidth::Fixed(width) => width + PADDING, } @@ -306,15 +371,18 @@ impl Default for ColumnWidth { } } -impl<W: LayoutElement> MonitorSet<W> { - pub fn new() -> Self { - Self::NoOutputs(vec![]) +impl<W: LayoutElement> Layout<W> { + pub fn new(config: &Config) -> Self { + Self { + monitor_set: MonitorSet::NoOutputs { workspaces: vec![] }, + options: Rc::new(Options::from_config(config)), + } } pub fn add_output(&mut self, output: Output) { let id = OutputId::new(&output); - *self = match mem::take(self) { + self.monitor_set = match mem::take(&mut self.monitor_set) { MonitorSet::Normal { mut monitors, primary_idx, @@ -337,29 +405,30 @@ impl<W: LayoutElement> MonitorSet<W> { workspaces.reverse(); if workspaces.iter().all(|ws| ws.has_windows()) { // Make sure there's always an empty workspace. - workspaces.push(Workspace::new(output.clone())); + workspaces.push(Workspace::new(output.clone(), self.options.clone())); } for ws in &mut workspaces { ws.set_output(Some(output.clone())); } - monitors.push(Monitor::new(output, workspaces)); + monitors.push(Monitor::new(output, workspaces, self.options.clone())); MonitorSet::Normal { monitors, primary_idx, active_monitor_idx, } } - MonitorSet::NoOutputs(mut workspaces) => { + MonitorSet::NoOutputs { mut workspaces } => { // We know there are no empty workspaces there, so add one. - workspaces.push(Workspace::new(output.clone())); + workspaces.push(Workspace::new(output.clone(), self.options.clone())); for workspace in &mut workspaces { workspace.set_output(Some(output.clone())); } - let monitor = Monitor::new(output, workspaces); + let monitor = Monitor::new(output, workspaces, self.options.clone()); + MonitorSet::Normal { monitors: vec![monitor], primary_idx: 0, @@ -370,7 +439,7 @@ impl<W: LayoutElement> MonitorSet<W> { } pub fn remove_output(&mut self, output: &Output) { - *self = match mem::take(self) { + self.monitor_set = match mem::take(&mut self.monitor_set) { MonitorSet::Normal { mut monitors, mut primary_idx, @@ -392,7 +461,7 @@ impl<W: LayoutElement> MonitorSet<W> { if monitors.is_empty() { // Removed the last monitor. - MonitorSet::NoOutputs(workspaces) + MonitorSet::NoOutputs { workspaces } } else { if primary_idx >= idx { // Update primary_idx to either still point at the same monitor, or at some @@ -422,7 +491,7 @@ impl<W: LayoutElement> MonitorSet<W> { } } } - MonitorSet::NoOutputs(_) => { + MonitorSet::NoOutputs { .. } => { panic!("tried to remove output when there were already none") } } @@ -439,7 +508,7 @@ impl<W: LayoutElement> MonitorSet<W> { monitors, active_monitor_idx, .. - } = self + } = &mut self.monitor_set else { panic!() }; @@ -455,7 +524,7 @@ impl<W: LayoutElement> MonitorSet<W> { /// /// Returns an output that the window was added to, if there were any outputs. pub fn add_window(&mut self, window: W, activate: bool) -> Option<&Output> { - match self { + match &mut self.monitor_set { MonitorSet::Normal { monitors, active_monitor_idx, @@ -465,11 +534,11 @@ impl<W: LayoutElement> MonitorSet<W> { mon.add_window(mon.active_workspace_idx, window, activate); Some(&mon.output) } - MonitorSet::NoOutputs(workspaces) => { + MonitorSet::NoOutputs { workspaces } => { let ws = if let Some(ws) = workspaces.get_mut(0) { ws } else { - workspaces.push(Workspace::new_no_outputs()); + workspaces.push(Workspace::new_no_outputs(self.options.clone())); &mut workspaces[0] }; ws.add_window(window, activate); @@ -479,7 +548,7 @@ impl<W: LayoutElement> MonitorSet<W> { } pub fn remove_window(&mut self, window: &W) { - match self { + match &mut self.monitor_set { MonitorSet::Normal { monitors, .. } => { for mon in monitors { for (idx, ws) in mon.workspaces.iter_mut().enumerate() { @@ -503,7 +572,7 @@ impl<W: LayoutElement> MonitorSet<W> { } } } - MonitorSet::NoOutputs(workspaces) => { + MonitorSet::NoOutputs { workspaces, .. } => { for (idx, ws) in workspaces.iter_mut().enumerate() { if ws.has_window(window) { ws.remove_window(window); @@ -521,7 +590,7 @@ impl<W: LayoutElement> MonitorSet<W> { } pub fn update_window(&mut self, window: &W) { - match self { + match &mut self.monitor_set { MonitorSet::Normal { monitors, .. } => { for mon in monitors { for ws in &mut mon.workspaces { @@ -532,7 +601,7 @@ impl<W: LayoutElement> MonitorSet<W> { } } } - MonitorSet::NoOutputs(workspaces) => { + MonitorSet::NoOutputs { workspaces, .. } => { for ws in workspaces { if ws.has_window(window) { ws.update_window(window); @@ -544,7 +613,7 @@ impl<W: LayoutElement> MonitorSet<W> { } pub fn find_window_and_output(&self, wl_surface: &WlSurface) -> Option<(W, Output)> { - if let MonitorSet::Normal { monitors, .. } = self { + if let MonitorSet::Normal { monitors, .. } = &self.monitor_set { for mon in monitors { for ws in &mon.workspaces { if let Some(window) = ws.find_wl_surface(wl_surface) { @@ -558,7 +627,7 @@ impl<W: LayoutElement> MonitorSet<W> { } pub fn update_output_size(&mut self, output: &Output) { - let MonitorSet::Normal { monitors, .. } = self else { + let MonitorSet::Normal { monitors, .. } = &mut self.monitor_set else { |
