aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-10-05 09:25:07 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-10-05 09:25:07 +0400
commit6fcdb4192275a8112fd45a91eb3e4b70c5ac684f (patch)
treebcd857c8e96952f81c5a049eeaec571c23b6febf /src
parent3ac16074063db2cccdb10d9e5b832aaec0492bb4 (diff)
downloadniri-6fcdb4192275a8112fd45a91eb3e4b70c5ac684f.tar.gz
niri-6fcdb4192275a8112fd45a91eb3e4b70c5ac684f.tar.bz2
niri-6fcdb4192275a8112fd45a91eb3e4b70c5ac684f.zip
Refactor layout for configurability, add preset-column-widths option
layout.rs finally gets a struct actually named Layout.
Diffstat (limited to 'src')
-rw-r--r--src/config.rs23
-rw-r--r--src/handlers/compositor.rs14
-rw-r--r--src/handlers/layer_shell.rs6
-rw-r--r--src/handlers/mod.rs2
-rw-r--r--src/handlers/xdg_shell.rs25
-rw-r--r--src/input.rs74
-rw-r--r--src/layout.rs456
-rw-r--r--src/main.rs2
-rw-r--r--src/niri.rs47
9 files changed, 411 insertions, 238 deletions
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 {