diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-09-25 16:45:39 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-10-02 09:33:08 +0300 |
| commit | 8c3345807ace2c2b9afcec550277a822e3e3f701 (patch) | |
| tree | 24c6d0dc0e8320fea1921f43b4b659911666707f /src/layout/monitor.rs | |
| parent | c353a7dae900382893cde03a84a85add24abfc45 (diff) | |
| download | niri-8c3345807ace2c2b9afcec550277a822e3e3f701.tar.gz niri-8c3345807ace2c2b9afcec550277a822e3e3f701.tar.bz2 niri-8c3345807ace2c2b9afcec550277a822e3e3f701.zip | |
layout: Extract Monitor::verify_invariants()
Diffstat (limited to 'src/layout/monitor.rs')
| -rw-r--r-- | src/layout/monitor.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index bcb6a5c3..21cbfcab 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -1881,4 +1881,110 @@ impl<W: LayoutElement> Monitor<W> { pub fn working_area(&self) -> Rectangle<f64, Logical> { self.working_area } + + #[cfg(test)] + pub(super) fn verify_invariants(&self) { + use approx::assert_abs_diff_eq; + + assert!( + !self.workspaces.is_empty(), + "monitor must have at least one workspace" + ); + assert!(self.active_workspace_idx < self.workspaces.len()); + + if let Some(WorkspaceSwitch::Animation(anim)) = &self.workspace_switch { + let before_idx = anim.from() as usize; + let after_idx = anim.to() as usize; + + assert!(before_idx < self.workspaces.len()); + assert!(after_idx < self.workspaces.len()); + } + + assert!( + !self.workspaces.last().unwrap().has_windows(), + "monitor must have an empty workspace in the end" + ); + if self.options.layout.empty_workspace_above_first { + assert!( + !self.workspaces.first().unwrap().has_windows(), + "first workspace must be empty when empty_workspace_above_first is set" + ) + } + + assert!( + self.workspaces.last().unwrap().name.is_none(), + "monitor must have an unnamed workspace in the end" + ); + if self.options.layout.empty_workspace_above_first { + assert!( + self.workspaces.first().unwrap().name.is_none(), + "first workspace must be unnamed when empty_workspace_above_first is set" + ) + } + + if self.options.layout.empty_workspace_above_first { + assert!( + self.workspaces.len() != 2, + "if empty_workspace_above_first is set there must be just 1 or 3+ workspaces" + ) + } + + // If there's no workspace switch in progress, there can't be any non-last non-active + // empty workspaces. If empty_workspace_above_first is set then the first workspace + // will be empty too. + let pre_skip = if self.options.layout.empty_workspace_above_first { + 1 + } else { + 0 + }; + if self.workspace_switch.is_none() { + for (idx, ws) in self + .workspaces + .iter() + .enumerate() + .skip(pre_skip) + .rev() + // skip last + .skip(1) + { + if idx != self.active_workspace_idx { + assert!( + ws.has_windows_or_name(), + "non-active workspace can't be empty and unnamed except the last one" + ); + } + } + } + + for workspace in &self.workspaces { + assert_eq!(self.clock, workspace.clock); + + assert_eq!( + self.scale().integer_scale(), + workspace.scale().integer_scale() + ); + assert_eq!( + self.scale().fractional_scale(), + workspace.scale().fractional_scale() + ); + assert_eq!(self.view_size, workspace.view_size()); + assert_eq!(self.working_area, workspace.working_area()); + + assert_eq!( + workspace.base_options, self.options, + "workspace options must be synchronized with layout" + ); + } + + let scale = self.scale().fractional_scale(); + let iter = self.workspaces_with_render_geo(); + for (_ws, ws_geo) in iter { + let pos = ws_geo.loc; + let rounded_pos = pos.to_physical_precise_round(scale).to_logical(scale); + + // Workspace positions must be rounded to physical pixels. + assert_abs_diff_eq!(pos.x, rounded_pos.x, epsilon = 1e-5); + assert_abs_diff_eq!(pos.y, rounded_pos.y, epsilon = 1e-5); + } + } } |
