aboutsummaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-09-20 12:57:42 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-10-02 09:33:08 +0300
commit4c524b47196badd281bc159bef3137cf16f963e5 (patch)
tree3284ab9c888e5883a525dbf04ad32818cc1c7f81 /src/layout
parent1fa9dd32ed028c88248644a13421c098fef72894 (diff)
downloadniri-4c524b47196badd281bc159bef3137cf16f963e5.tar.gz
niri-4c524b47196badd281bc159bef3137cf16f963e5.tar.bz2
niri-4c524b47196badd281bc159bef3137cf16f963e5.zip
layout: Store Layout directly in Options
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/floating.rs20
-rw-r--r--src/layout/mod.rs130
-rw-r--r--src/layout/monitor.rs30
-rw-r--r--src/layout/scrolling.rs149
-rw-r--r--src/layout/tests.rs121
-rw-r--r--src/layout/tests/animations.rs5
-rw-r--r--src/layout/tests/fullscreen.rs9
-rw-r--r--src/layout/tile.rs30
-rw-r--r--src/layout/workspace.rs13
9 files changed, 253 insertions, 254 deletions
diff --git a/src/layout/floating.rs b/src/layout/floating.rs
index 5f5767ad..260775d3 100644
--- a/src/layout/floating.rs
+++ b/src/layout/floating.rs
@@ -340,7 +340,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
}
pub fn new_window_toplevel_bounds(&self, rules: &ResolvedWindowRules) -> Size<i32, Logical> {
- let border_config = self.options.border.merged_with(&rules.border);
+ let border_config = self.options.layout.border.merged_with(&rules.border);
compute_toplevel_bounds(border_config, self.working_area.size)
}
@@ -633,7 +633,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
let available_size = self.working_area.size.w;
- let len = self.options.preset_column_widths.len();
+ let len = self.options.layout.preset_column_widths.len();
let tile = &mut self.tiles[idx];
let preset_idx = if let Some(idx) = tile.floating_preset_width_idx {
(idx + if forwards { 1 } else { len - 1 }) % len
@@ -643,6 +643,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
let mut it = self
.options
+ .layout
.preset_column_widths
.iter()
.map(|preset| resolve_preset_size(*preset, available_size));
@@ -668,7 +669,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
}
};
- let preset = self.options.preset_column_widths[preset_idx];
+ let preset = self.options.layout.preset_column_widths[preset_idx];
self.set_window_width(Some(&id), SizeChange::from(preset), true);
self.tiles[idx].floating_preset_width_idx = Some(preset_idx);
@@ -693,7 +694,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
let available_size = self.working_area.size.h;
- let len = self.options.preset_window_heights.len();
+ let len = self.options.layout.preset_window_heights.len();
let tile = &mut self.tiles[idx];
let preset_idx = if let Some(idx) = tile.floating_preset_height_idx {
(idx + if forwards { 1 } else { len - 1 }) % len
@@ -703,6 +704,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
let mut it = self
.options
+ .layout
.preset_window_heights
.iter()
.map(|preset| resolve_preset_size(*preset, available_size));
@@ -728,7 +730,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
}
};
- let preset = self.options.preset_window_heights[preset_idx];
+ let preset = self.options.layout.preset_window_heights[preset_idx];
self.set_window_height(Some(&id), SizeChange::from(preset), true);
let tile = &mut self.tiles[idx];
@@ -1156,7 +1158,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
.map(|resize| resize.data);
win.set_interactive_resize(resize_data);
- let border_config = self.options.border.merged_with(&win.rules().border);
+ let border_config = self.options.layout.border.merged_with(&win.rules().border);
let bounds = compute_toplevel_bounds(border_config, self.working_area.size);
win.set_bounds(bounds);
@@ -1220,7 +1222,7 @@ impl<W: LayoutElement> FloatingSpace<W> {
height: Option<PresetSize>,
rules: &ResolvedWindowRules,
) -> Size<i32, Logical> {
- let border = self.options.border.merged_with(&rules.border);
+ let border = self.options.layout.border.merged_with(&rules.border);
let resolve = |size: Option<PresetSize>, working_area_size: f64| {
if let Some(size) = size {
@@ -1317,10 +1319,10 @@ impl<W: LayoutElement> FloatingSpace<W> {
tile.verify_invariants();
if let Some(idx) = tile.floating_preset_width_idx {
- assert!(idx < self.options.preset_column_widths.len());
+ assert!(idx < self.options.layout.preset_column_widths.len());
}
if let Some(idx) = tile.floating_preset_height_idx {
- assert!(idx < self.options.preset_window_heights.len());
+ assert!(idx < self.options.layout.preset_window_heights.len());
}
assert!(
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 40f1deed..ff13ee23 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -40,8 +40,7 @@ use std::time::Duration;
use monitor::{InsertHint, InsertPosition, InsertWorkspace, MonitorAddWindowTarget};
use niri_config::utils::MergeWith as _;
use niri_config::{
- CenterFocusedColumn, Config, CornerRadius, PresetSize, Struts, Workspace as WorkspaceConfig,
- WorkspaceReference,
+ Config, CornerRadius, PresetSize, Workspace as WorkspaceConfig, WorkspaceReference,
};
use niri_ipc::{ColumnDisplay, PositionChange, SizeChange, WindowLayout};
use scrolling::{Column, ColumnWidth};
@@ -334,27 +333,9 @@ enum MonitorSet<W: LayoutElement> {
},
}
-#[derive(Debug, Clone, PartialEq)]
+#[derive(Debug, Default, Clone, PartialEq)]
pub struct Options {
- /// Padding around windows in logical pixels.
- pub gaps: f64,
- /// Extra padding around the working area in logical pixels.
- pub struts: Struts,
- pub focus_ring: niri_config::FocusRing,
- pub border: niri_config::Border,
- pub shadow: niri_config::Shadow,
- pub tab_indicator: niri_config::TabIndicator,
- pub insert_hint: niri_config::InsertHint,
- pub center_focused_column: CenterFocusedColumn,
- pub always_center_single_column: bool,
- pub empty_workspace_above_first: bool,
- pub default_column_display: ColumnDisplay,
- /// Column or window widths that `toggle_width()` switches between.
- pub preset_column_widths: Vec<PresetSize>,
- /// Initial width for new columns.
- pub default_column_width: Option<PresetSize>,
- /// Window height that `toggle_window_height()` switches between.
- pub preset_window_heights: Vec<PresetSize>,
+ pub layout: niri_config::Layout,
pub animations: niri_config::Animations,
pub gestures: niri_config::Gestures,
pub overview: niri_config::Overview,
@@ -364,41 +345,6 @@ pub struct Options {
pub deactivate_unfocused_windows: bool,
}
-impl Default for Options {
- fn default() -> Self {
- Self {
- gaps: 16.,
- struts: Default::default(),
- focus_ring: Default::default(),
- border: Default::default(),
- shadow: Default::default(),
- tab_indicator: Default::default(),
- insert_hint: Default::default(),
- center_focused_column: Default::default(),
- always_center_single_column: false,
- empty_workspace_above_first: false,
- default_column_display: ColumnDisplay::Normal,
- preset_column_widths: vec![
- PresetSize::Proportion(1. / 3.),
- PresetSize::Proportion(0.5),
- PresetSize::Proportion(2. / 3.),
- ],
- default_column_width: None,
- animations: Default::default(),
- gestures: Default::default(),
- overview: Default::default(),
- disable_resize_throttling: false,
- disable_transactions: false,
- preset_window_heights: vec![
- PresetSize::Proportion(1. / 3.),
- PresetSize::Proportion(0.5),
- PresetSize::Proportion(2. / 3.),
- ],
- deactivate_unfocused_windows: false,
- }
- }
-}
-
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
enum InteractiveMoveState<W: LayoutElement> {
@@ -620,49 +566,23 @@ impl HitType {
impl Options {
fn from_config(config: &Config) -> Self {
- let layout = config.resolve_layout();
-
- let preset_column_widths = if layout.preset_column_widths.is_empty() {
- Options::default().preset_column_widths
- } else {
- layout.preset_column_widths.clone()
- };
- let preset_window_heights = if layout.preset_window_heights.is_empty() {
- Options::default().preset_window_heights
- } else {
- layout.preset_window_heights.clone()
- };
-
Self {
- gaps: layout.gaps,
- struts: layout.struts,
- focus_ring: layout.focus_ring,
- border: layout.border,
- shadow: layout.shadow,
- tab_indicator: layout.tab_indicator,
- insert_hint: layout.insert_hint,
- center_focused_column: layout.center_focused_column,
- always_center_single_column: layout.always_center_single_column,
- empty_workspace_above_first: layout.empty_workspace_above_first,
- default_column_display: layout.default_column_display,
- preset_column_widths,
- default_column_width: layout.default_column_width,
+ layout: config.resolve_layout(),
animations: config.animations.clone(),
gestures: config.gestures,
overview: config.overview,
disable_resize_throttling: config.debug.disable_resize_throttling,
disable_transactions: config.debug.disable_transactions,
deactivate_unfocused_windows: config.debug.deactivate_unfocused_windows,
- preset_window_heights,
}
}
fn adjusted_for_scale(mut self, scale: f64) -> Self {
let round = |logical: f64| round_logical_in_physical_max1(scale, logical);
- self.gaps = round(self.gaps);
- self.focus_ring.width = round(self.focus_ring.width);
- self.border.width = round(self.border.width);
+ self.layout.gaps = round(self.layout.gaps);
+ self.layout.focus_ring.width = round(self.layout.focus_ring.width);
+ self.layout.border.width = round(self.layout.border.width);
self
}
@@ -775,7 +695,7 @@ impl<W: LayoutElement> Layout<W> {
// workspaces set up across multiple monitors. Without this check, the
// first monitor to connect can end up with the first empty workspace
// focused instead of the first named workspace.
- && !(self.options.empty_workspace_above_first
+ && !(self.options.layout.empty_workspace_above_first
&& primary.active_workspace_idx == 1)
{
primary.active_workspace_idx =
@@ -790,7 +710,7 @@ impl<W: LayoutElement> Layout<W> {
// takes care of this.
if stopped_primary_ws_switch
- || (primary.options.empty_workspace_above_first
+ || (primary.options.layout.empty_workspace_above_first
&& primary.workspaces.len() == 2)
{
primary.clean_up_workspaces();
@@ -810,7 +730,7 @@ impl<W: LayoutElement> Layout<W> {
self.options.clone(),
));
- if self.options.empty_workspace_above_first && workspaces.len() > 1 {
+ if self.options.layout.empty_workspace_above_first && workspaces.len() > 1 {
workspaces.insert(
0,
Workspace::new(output.clone(), self.clock.clone(), self.options.clone()),
@@ -844,7 +764,7 @@ impl<W: LayoutElement> Layout<W> {
));
let mut active_workspace_idx = 0;
- if self.options.empty_workspace_above_first && workspaces.len() > 1 {
+ if self.options.layout.empty_workspace_above_first && workspaces.len() > 1 {
workspaces.insert(
0,
Workspace::new(output.clone(), self.clock.clone(), self.options.clone()),
@@ -944,7 +864,7 @@ impl<W: LayoutElement> Layout<W> {
// If empty_workspace_above_first is set and the first workspace is now no
// longer empty, add a new empty workspace on top.
- if primary.options.empty_workspace_above_first
+ if primary.options.layout.empty_workspace_above_first
&& primary.workspaces[0].has_windows_or_name()
{
primary.add_workspace_top();
@@ -1242,7 +1162,7 @@ impl<W: LayoutElement> Layout<W> {
// Special case handling when empty_workspace_above_first is set and all
// workspaces are empty.
- if mon.options.empty_workspace_above_first
+ if mon.options.layout.empty_workspace_above_first
&& mon.workspaces.len() == 2
&& mon.workspace_switch.is_none()
{
@@ -2637,7 +2557,7 @@ impl<W: LayoutElement> Layout<W> {
!monitor.workspaces.last().unwrap().has_windows(),
"monitor must have an empty workspace in the end"
);
- if monitor.options.empty_workspace_above_first {
+ if monitor.options.layout.empty_workspace_above_first {
assert!(
!monitor.workspaces.first().unwrap().has_windows(),
"first workspace must be empty when empty_workspace_above_first is set"
@@ -2648,14 +2568,14 @@ impl<W: LayoutElement> Layout<W> {
monitor.workspaces.last().unwrap().name.is_none(),
"monitor must have an unnamed workspace in the end"
);
- if monitor.options.empty_workspace_above_first {
+ if monitor.options.layout.empty_workspace_above_first {
assert!(
monitor.workspaces.first().unwrap().name.is_none(),
"first workspace must be unnamed when empty_workspace_above_first is set"
)
}
- if monitor.options.empty_workspace_above_first {
+ if monitor.options.layout.empty_workspace_above_first {
assert!(
monitor.workspaces.len() != 2,
"if empty_workspace_above_first is set there must be just 1 or 3+ workspaces"
@@ -2665,7 +2585,7 @@ impl<W: LayoutElement> Layout<W> {
// 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 monitor.options.empty_workspace_above_first {
+ let pre_skip = if monitor.options.layout.empty_workspace_above_first {
1
} else {
0
@@ -3107,7 +3027,7 @@ impl<W: LayoutElement> Layout<W> {
let mon = &mut monitors[mon_idx];
let mut insert_idx = 0;
- if mon.options.empty_workspace_above_first {
+ if mon.options.layout.empty_workspace_above_first {
// need to insert new empty workspace on top
mon.add_workspace_top();
insert_idx += 1;
@@ -3622,7 +3542,7 @@ impl<W: LayoutElement> Layout<W> {
// Insert a new empty workspace.
current.add_workspace_bottom();
}
- if current.options.empty_workspace_above_first && current.active_workspace_idx == 0 {
+ if current.options.layout.empty_workspace_above_first && current.active_workspace_idx == 0 {
current.add_workspace_top();
}
@@ -3642,7 +3562,7 @@ impl<W: LayoutElement> Layout<W> {
target.previous_workspace_id = Some(target.workspaces[target.active_workspace_idx].id());
- if target.options.empty_workspace_above_first && target.workspaces.len() == 1 {
+ if target.options.layout.empty_workspace_above_first && target.workspaces.len() == 1 {
// Insert a new empty workspace on top to prepare for insertion of new workspace.
target.add_workspace_top();
}
@@ -3711,7 +3631,7 @@ impl<W: LayoutElement> Layout<W> {
let mut ws = current.workspaces.remove(old_idx);
- if current.options.empty_workspace_above_first && old_idx == 0 {
+ if current.options.layout.empty_workspace_above_first && old_idx == 0 {
current.add_workspace_top();
}
@@ -3728,7 +3648,7 @@ impl<W: LayoutElement> Layout<W> {
target.previous_workspace_id = Some(target.workspaces[target.active_workspace_idx].id());
- if target.options.empty_workspace_above_first && target.workspaces.len() == 1 {
+ if target.options.layout.empty_workspace_above_first && target.workspaces.len() == 1 {
// Insert a new empty workspace on top to prepare for insertion of new workspace.
target.add_workspace_top();
}
@@ -4480,7 +4400,7 @@ impl<W: LayoutElement> Layout<W> {
.position(|ws| ws.id() == ws_id)
.unwrap(),
InsertWorkspace::NewAt(ws_idx) => {
- if self.options.empty_workspace_above_first && ws_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && ws_idx == 0 {
// Reuse the top empty workspace.
0
} else if mon.workspaces.len() - 1 <= ws_idx {
@@ -4813,7 +4733,7 @@ impl<W: LayoutElement> Layout<W> {
} = &mut self.monitor_set
{
let monitor = &mut monitors[*active_monitor_idx];
- if self.options.empty_workspace_above_first
+ if self.options.layout.empty_workspace_above_first
&& monitor
.workspaces
.first()
@@ -5242,7 +5162,7 @@ impl<W: LayoutElement> Layout<W> {
// Add border width since ColumnWidth includes borders.
let rules = window.rules();
- let border = self.options.border.merged_with(&rules.border);
+ let border = self.options.layout.border.merged_with(&rules.border);
if !border.off {
fixed += border.width * 2.;
}
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs
index 5dc0aed6..bcb6a5c3 100644
--- a/src/layout/monitor.rs
+++ b/src/layout/monitor.rs
@@ -293,7 +293,7 @@ impl<W: LayoutElement> Monitor<W> {
active_workspace_idx: 0,
previous_workspace_id: None,
insert_hint: None,
- insert_hint_element: InsertHintElement::new(options.insert_hint),
+ insert_hint_element: InsertHintElement::new(options.layout.insert_hint),
insert_hint_render_loc: None,
overview_open: false,
overview_progress: None,
@@ -463,7 +463,7 @@ impl<W: LayoutElement> Monitor<W> {
if workspace_idx == self.workspaces.len() - 1 {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && workspace_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && workspace_idx == 0 {
self.add_workspace_top();
workspace_idx += 1;
}
@@ -522,7 +522,7 @@ impl<W: LayoutElement> Monitor<W> {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && workspace_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && workspace_idx == 0 {
self.add_workspace_top();
workspace_idx += 1;
}
@@ -562,7 +562,7 @@ impl<W: LayoutElement> Monitor<W> {
pub fn clean_up_workspaces(&mut self) {
assert!(self.workspace_switch.is_none());
- let range_start = if self.options.empty_workspace_above_first {
+ let range_start = if self.options.layout.empty_workspace_above_first {
1
} else {
0
@@ -582,7 +582,7 @@ impl<W: LayoutElement> Monitor<W> {
// Special case handling when empty_workspace_above_first is set and all workspaces
// are empty.
- if self.options.empty_workspace_above_first && self.workspaces.len() == 2 {
+ if self.options.layout.empty_workspace_above_first && self.workspaces.len() == 2 {
assert!(!self.workspaces[0].has_windows_or_name());
assert!(!self.workspaces[1].has_windows_or_name());
self.workspaces.remove(1);
@@ -1023,10 +1023,11 @@ impl<W: LayoutElement> Monitor<W> {
}
pub fn update_config(&mut self, options: Rc<Options>) {
- if self.options.empty_workspace_above_first != options.empty_workspace_above_first
+ if self.options.layout.empty_workspace_above_first
+ != options.layout.empty_workspace_above_first
&& self.workspaces.len() > 1
{
- if options.empty_workspace_above_first {
+ if options.layout.empty_workspace_above_first {
self.add_workspace_top();
} else if self.workspace_switch.is_none() && self.active_workspace_idx != 0 {
self.workspaces.remove(0);
@@ -1038,7 +1039,8 @@ impl<W: LayoutElement> Monitor<W> {
ws.update_config(options.clone());
}
- self.insert_hint_element.update_config(options.insert_hint);
+ self.insert_hint_element
+ .update_config(options.layout.insert_hint);
self.options = options;
}
@@ -1074,7 +1076,7 @@ impl<W: LayoutElement> Monitor<W> {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && self.active_workspace_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && self.active_workspace_idx == 0 {
self.add_workspace_top();
new_idx += 1;
}
@@ -1100,7 +1102,7 @@ impl<W: LayoutElement> Monitor<W> {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && new_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && new_idx == 0 {
self.add_workspace_top();
new_idx += 1;
}
@@ -1132,7 +1134,7 @@ impl<W: LayoutElement> Monitor<W> {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && old_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && old_idx == 0 {
self.add_workspace_top();
new_idx += 1;
}
@@ -1142,7 +1144,7 @@ impl<W: LayoutElement> Monitor<W> {
self.add_workspace_bottom();
}
- if self.options.empty_workspace_above_first && new_idx == 0 {
+ if self.options.layout.empty_workspace_above_first && new_idx == 0 {
self.add_workspace_top();
new_idx += 1;
}
@@ -1464,7 +1466,7 @@ impl<W: LayoutElement> Monitor<W> {
) -> impl Iterator<Item = MonitorRenderElement<R>> {
let mut rv = None;
- if !self.options.insert_hint.off {
+ if !self.options.layout.insert_hint.off {
if let Some(render_loc) = self.insert_hint_render_loc {
if let InsertWorkspace::NewAt(_) = render_loc.workspace {
let iter = self
@@ -1525,7 +1527,7 @@ impl<W: LayoutElement> Monitor<W> {
// Draw the insert hint.
let mut insert_hint = None;
- if !self.options.insert_hint.off {
+ if !self.options.layout.insert_hint.off {
if let Some(render_loc) = self.insert_hint_render_loc {
if let InsertWorkspace::Existing(workspace_id) = render_loc.workspace {
insert_hint = Some((
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index 52869024..9c483e72 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -276,7 +276,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
clock: Clock,
options: Rc<Options>,
) -> Self {
- let working_area = compute_working_area(parent_area, scale, options.struts);
+ let working_area = compute_working_area(parent_area, scale, options.layout.struts);
Self {
columns: Vec::new(),
@@ -303,7 +303,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
scale: f64,
options: Rc<Options>,
) {
- let working_area = compute_working_area(parent_area, scale, options.struts);
+ let working_area = compute_working_area(parent_area, scale, options.layout.struts);
for (column, data) in zip(&mut self.columns, &mut self.data) {
column.update_config(view_size, working_area, scale, options.clone());
@@ -444,14 +444,14 @@ impl<W: LayoutElement> ScrollingSpace<W> {
}
pub fn new_window_toplevel_bounds(&self, rules: &ResolvedWindowRules) -> Size<i32, Logical> {
- let border_config = self.options.border.merged_with(&rules.border);
+ let border_config = self.options.layout.border.merged_with(&rules.border);
let display_mode = rules
.default_column_display
- .unwrap_or(self.options.default_column_display);
+ .unwrap_or(self.options.layout.default_column_display);
let will_tab = display_mode == ColumnDisplay::Tabbed;
let extra_size = if will_tab {
- TabIndicator::new(self.options.tab_indicator).extra_size(1, self.scale)
+ TabIndicator::new(self.options.layout.tab_indicator).extra_size(1, self.scale)
} else {
Size::from((0., 0.))
};
@@ -460,7 +460,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
border_config,
self.working_area.size,
extra_size,
- self.options.gaps,
+ self.options.layout.gaps,
)
}
@@ -470,14 +470,14 @@ impl<W: LayoutElement> ScrollingSpace<W> {
height: Option<PresetSize>,
rules: &ResolvedWindowRules,
) -> Size<i32, Logical> {
- let border = self.options.border.merged_with(&rules.border);
+ let border = self.options.layout.border.merged_with(&rules.border);
let display_mode = rules
.default_column_display
- .unwrap_or(self.options.default_column_display);
+ .unwrap_or(self.options.layout.default_column_display);
let will_tab = display_mode == ColumnDisplay::Tabbed;
let extra = if will_tab {
- TabIndicator::new(self.options.tab_indicator).extra_size(1, self.scale)
+ TabIndicator::new(self.options.layout.tab_indicator).extra_size(1, self.scale)
} else {
Size::from((0., 0.))
};
@@ -500,7 +500,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
0
};
- let mut full_height = self.working_area.size.h - self.options.gaps * 2.;
+ let mut full_height = self.working_area.size.h - self.options.layout.gaps * 2.;
if !border.off {
full_height -= border.width * 2.;
}
@@ -524,8 +524,8 @@ impl<W: LayoutElement> ScrollingSpace<W> {
}
pub fn is_centering_focused_column(&self) -> bool {
- self.options.center_focused_column == CenterFocusedColumn::Always
- || (self.options.always_center_single_column && self.columns.len() <= 1)
+ self.options.layout.center_focused_column == CenterFocusedColumn::Always
+ || (self.options.layout.always_center_single_column && self.columns.len() <= 1)
}
fn compute_new_view_offset_fit(
@@ -546,7 +546,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.working_area.size.w,
col_x,
width,
- self.options.gaps,
+ self.options.layout.gaps,
);
// Non-fullscreen windows are always offset at least by the working area position.
@@ -606,7 +606,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
return self.compute_new_view_offset_for_column_centered(target_x, idx);
}
- match self.options.center_focused_column {
+ match self.options.layout.center_focused_column {
CenterFocusedColumn::Always => {
self.compute_new_view_offset_for_column_centered(target_x, idx)
}
@@ -639,7 +639,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
} else {
// Source is right from target.
source_col_x - target_col_x + source_col_width
- } + self.options.gaps * 2.;
+ } + self.options.layout.gaps * 2.;
// If it fits together, do a normal animation, otherwise center the new column.
if total_width <= self.working_area.size.w {
@@ -783,8 +783,8 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let x = pos.x + self.view_pos();
// Aim for the center of the gap.
- let x = x + self.options.gaps / 2.;
- let y = pos.y + self.options.gaps / 2.;
+ let x = x + self.options.layout.gaps / 2.;
+ let y = pos.y + self.options.layout.gaps / 2.;
// Insert position is before the first column.
if x < 0. {
@@ -2224,7 +2224,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let mut leftmost_col_x = None;
let mut active_col_x = None;
- let gap = self.options.gaps;
+ let gap = self.options.layout.gaps;
let col_xs = self.column_xs(self.data.iter().copied());
for (idx, col_x) in col_xs.take(self.columns.len()).enumerate() {
if col_x < view_x + working_x + gap {
@@ -2274,7 +2274,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
// HACK: pass a self.data iterator in manually as a workaround for the lack of method partial
// borrowing. Note that this method's return value does not borrow the entire &Self!
fn column_xs(&self, data: impl Iterator<Item = ColumnData>) -> impl Iterator<Item = f64> {
- let gaps = self.options.gaps;
+ let gaps = self.options.layout.gaps;
let mut x = 0.;
// Chain with a dummy value to be able to get one past all columns' X.
@@ -2408,25 +2408,29 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let mut hint_area = match position {
InsertPosition::NewColumn(column_index) => {
if column_index == 0 || column_index == self.columns.len() {
- let size =
- Size::from((300., self.working_area.size.h - self.options.gaps * 2.));
+ let size = Size::from((
+ 300.,
+ self.working_area.size.h - self.options.layout.gaps * 2.,
+ ));
let mut loc = Point::from((
self.column_x(column_index),
- self.working_area.loc.y + self.options.gaps,
+ self.working_area.loc.y + self.options.layout.gaps,
));
if column_index == 0 && !self.columns.is_empty() {
- loc.x -= size.w + self.options.gaps;
+ loc.x -= size.w + self.options.layout.gaps;
}
Rectangle::new(loc, size)
} else if column_index > self.columns.len() {
error!("insert hint column index is out of range");
return None;
} else {
- let size =
- Size::from((300., self.working_area.size.h - self.options.gaps * 2.));
+ let size = Size::from((
+ 300.,
+ self.working_area.size.h - self.options.layout.gaps * 2.,
+ ));
let loc = Point::from((
- self.column_x(column_index) - size.w / 2. - self.options.gaps / 2.,
- self.working_area.loc.y + self.options.gaps,
+ self.column_x(column_index) - size.w / 2. - self.options.layout.gaps / 2.,
+ self.working_area.loc.y + self.options.layout.gaps,
));
Rectangle::new(loc, size)
}
@@ -2462,9 +2466,9 @@ impl<W: LayoutElement> ScrollingSpace<W> {
if tile_index == 0 {
(150., top)
} else if tile_index == col.tiles.len() {
- (150., top - self.options.gaps - 150.)
+ (150., top - self.options.layout.gaps - 150.)
} else {
- (300., top - self.options.gaps / 2. - 150.)
+ (300., top - self.options.layout.gaps / 2. - 150.)
}
};
@@ -2716,7 +2720,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let mut active_col_x = None;
let mut counted_non_active_column = false;
- let gap = self.options.gaps;
+ let gap = self.options.layout.gaps;
let col_xs = self.column_xs(self.data.iter().copied());
for (idx, col_x) in col_xs.take(self.columns.len()).enumerate() {
if col_x < view_x + working_x + gap {
@@ -3051,7 +3055,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let (leftmost, rightmost) = if self.columns.is_empty() {
(0., 0.)
} else {
- let gaps = self.options.gaps;
+ let gaps = self.options.layout.gaps;
let mut leftmost = -self.working_area.size.w;
@@ -3147,17 +3151,17 @@ impl<W: LayoutElement> ScrollingSpace<W> {
};
snapping_points.push(Snap { view_pos, col_idx });
- col_x += col_w + self.options.gaps;
+ col_x += col_w + self.options.layout.gaps;
}
} else {
let center_on_overflow = matches!(
- self.options.center_focused_column,
+ self.options.layout.center_focused_column,
CenterFocusedColumn::OnOverflow
);
let view_width = self.view_size.w;
let working_area_width = self.working_area.size.w;
- let gaps = self.options.gaps;
+ let gaps = self.options.layout.gaps;
let snap_points =
|col_x, col: &Column<W>, prev_col_w: Option<f64>, next_col_w: Option<f64>| {
@@ -3297,8 +3301,8 @@ impl<W: LayoutElement> ScrollingSpace<W> {
break;
}
} else {
- let padding =
- ((self.working_area.size.w - col_w) / 2.).clamp(0., self.options.gaps);
+ let padding = ((self.working_area.size.w - col_w) / 2.)
+ .clamp(0., self.options.layout.gaps);
if target_snap.view_pos + left_strut + self.working_area.size.w
< col_x + col_w + padding
{
@@ -3319,8 +3323,8 @@ impl<W: LayoutElement> ScrollingSpace<W> {
break;
}
} else {
- let padding =
- ((self.working_area.size.w - col_w) / 2.).clamp(0., self.options.gaps);
+ let padding = ((self.working_area.size.w - col_w) / 2.)
+ .clamp(0., self.options.layout.gaps);
if col_x - padding < target_snap.view_pos + left_strut {
break;
}
@@ -3548,12 +3552,12 @@ impl<W: LayoutElement> ScrollingSpace<W> {
win.set_interactive_resize(col_resize_data);
- let border_config = self.options.border.merged_with(&win.rules().border);
+ let border