aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Versteeg <t@versteeg.email>2024-01-08 17:17:19 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-01-08 17:37:18 +0400
commitfb93038bd88e4443015fb482de3450c27f009219 (patch)
treea2b5bbcce4c2c2fc9f9a070565800a44d1646013 /src
parent71fef2ad2e873c45279cdd6e629218fb5dea1115 (diff)
downloadniri-fb93038bd88e4443015fb482de3450c27f009219.tar.gz
niri-fb93038bd88e4443015fb482de3450c27f009219.tar.bz2
niri-fb93038bd88e4443015fb482de3450c27f009219.zip
Add center-focused-column setting
Diffstat (limited to 'src')
-rw-r--r--src/layout/mod.rs3
-rw-r--r--src/layout/workspace.rs133
2 files changed, 91 insertions, 45 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 69d78676..c18fe6b5 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -139,6 +139,7 @@ pub struct Options {
struts: Struts,
focus_ring: niri_config::FocusRing,
border: niri_config::FocusRing,
+ center_focused_column: niri_config::CenterFocusedColumn,
/// Column widths that `toggle_width()` switches between.
preset_widths: Vec<ColumnWidth>,
/// Initial width for new columns.
@@ -152,6 +153,7 @@ impl Default for Options {
struts: Default::default(),
focus_ring: Default::default(),
border: niri_config::default_border(),
+ center_focused_column: Default::default(),
preset_widths: vec![
ColumnWidth::Proportion(1. / 3.),
ColumnWidth::Proportion(0.5),
@@ -190,6 +192,7 @@ impl Options {
struts: layout.struts,
focus_ring: layout.focus_ring,
border: layout.border,
+ center_focused_column: layout.center_focused_column,
preset_widths,
default_width,
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index a0782718..3259785d 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -3,7 +3,7 @@ use std::iter::zip;
use std::rc::Rc;
use std::time::Duration;
-use niri_config::{PresetWidth, SizeChange, Struts};
+use niri_config::{CenterFocusedColumn, PresetWidth, SizeChange, Struts};
use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
use smithay::backend::renderer::element::utils::RelocateRenderElement;
use smithay::backend::renderer::{ImportAll, Renderer};
@@ -397,9 +397,7 @@ impl<W: LayoutElement> Workspace<W> {
new_offset - self.working_area.loc.x
}
- fn animate_view_offset_to_column(&mut self, current_x: i32, idx: usize) {
- let new_view_offset = self.compute_new_view_offset_for_column(current_x, idx);
-
+ fn animate_view_offset(&mut self, current_x: i32, idx: usize, new_view_offset: i32) {
let new_col_x = self.column_x(idx);
let from_view_offset = current_x - new_col_x;
self.view_offset = from_view_offset;
@@ -426,13 +424,78 @@ impl<W: LayoutElement> Workspace<W> {
));
}
+ fn animate_view_offset_to_column(&mut self, current_x: i32, idx: usize) {
+ let new_view_offset = self.compute_new_view_offset_for_column(current_x, idx);
+ self.animate_view_offset(current_x, idx, new_view_offset);
+ }
+
+ fn animate_view_offset_to_column_centered(&mut self, current_x: i32, idx: usize) {
+ if self.columns.is_empty() {
+ return;
+ }
+
+ let col = &self.columns[idx];
+ if col.is_fullscreen {
+ self.animate_view_offset_to_column(current_x, idx);
+ return;
+ }
+
+ let width = col.width();
+
+ // If the column is wider than the working area, then on commit it will be shifted to left
+ // edge alignment by the usual positioning code, so there's no use in trying to center it
+ // here.
+ if self.working_area.size.w <= width {
+ self.animate_view_offset_to_column(current_x, idx);
+ return;
+ }
+
+ let new_view_offset = -(self.working_area.size.w - width) / 2 - self.working_area.loc.x;
+
+ self.animate_view_offset(current_x, idx, new_view_offset);
+ }
+
fn activate_column(&mut self, idx: usize) {
if self.active_column_idx == idx {
return;
}
let current_x = self.view_pos();
- self.animate_view_offset_to_column(current_x, idx);
+ match self.options.center_focused_column {
+ CenterFocusedColumn::Always => {
+ self.animate_view_offset_to_column_centered(current_x, idx)
+ }
+ CenterFocusedColumn::OnOverflow => {
+ // Always take the left or right neighbor of the target as the source.
+ let source_idx = if self.active_column_idx > idx {
+ min(idx + 1, self.columns.len() - 1)
+ } else {
+ idx.saturating_sub(1)
+ };
+
+ let source_x = self.column_x(source_idx);
+ let source_width = self.columns[source_idx].width();
+
+ let target_x = self.column_x(idx);
+ let target_width = self.columns[idx].width();
+
+ let total_width = if source_x < target_x {
+ // Source is left from target.
+ target_x - source_x + target_width
+ } else {
+ // Source is right from target.
+ source_x - target_x + source_width
+ } + self.options.gaps * 2;
+
+ // If it fits together, do a normal animation, otherwise center the new column.
+ if total_width <= self.working_area.size.w {
+ self.animate_view_offset_to_column(current_x, idx);
+ } else {
+ self.animate_view_offset_to_column_centered(current_x, idx);
+ }
+ }
+ CenterFocusedColumn::Never => self.animate_view_offset_to_column(current_x, idx),
+ };
self.active_column_idx = idx;
@@ -488,15 +551,21 @@ impl<W: LayoutElement> Workspace<W> {
width,
is_full_width,
);
+ let width = column.width();
self.columns.insert(idx, column);
if activate {
// If this is the first window on an empty workspace, skip the animation from whatever
// view_offset was left over.
if was_empty {
- // Try to make the code produce a left-aligned offset, even in presence of left
- // exclusive zones.
- self.view_offset = self.compute_new_view_offset_for_column(self.column_x(0), 0);
+ if self.options.center_focused_column == CenterFocusedColumn::Always {
+ self.view_offset =
+ -(self.working_area.size.w - width) / 2 - self.working_area.loc.x;
+ } else {
+ // Try to make the code produce a left-aligned offset, even in presence of left
+ // exclusive zones.
+ self.view_offset = self.compute_new_view_offset_for_column(self.column_x(0), 0);
+ }
self.view_offset_anim = None;
}
@@ -574,7 +643,14 @@ impl<W: LayoutElement> Workspace<W> {
if idx == self.active_column_idx {
// We might need to move the view to ensure the resized window is still visible.
let current_x = self.view_pos();
- self.animate_view_offset_to_column(current_x, idx);
+
+ if self.options.center_focused_column == CenterFocusedColumn::Always {
+ // FIXME: we will want to skip the animation in some cases here to make
+ // continuously resizing windows not look janky.
+ self.animate_view_offset_to_column_centered(current_x, idx);
+ } else {
+ self.animate_view_offset_to_column(current_x, idx);
+ }
}
}
@@ -654,6 +730,7 @@ impl<W: LayoutElement> Workspace<W> {
let column = self.columns.remove(self.active_column_idx);
self.columns.insert(new_idx, column);
+ // FIXME: should this be different when always centering?
self.view_offset =
self.compute_new_view_offset_for_column(current_x, self.active_column_idx);
@@ -738,42 +815,8 @@ impl<W: LayoutElement> Workspace<W> {
}
pub fn center_column(&mut self) {
- if self.columns.is_empty() {
- return;
- }
-
- let col = &self.columns[self.active_column_idx];
- if col.is_fullscreen {
- return;
- }
-
- let width = col.width();
-
- // If the column is wider than the working area, then on commit it will be shifted to left
- // edge alignment by the usual positioning code, so there's no use in doing anything here.
- if self.working_area.size.w <= width {
- return;
- }
-
- let new_view_offset = -(self.working_area.size.w - width) / 2 - self.working_area.loc.x;
-
- // If we're already animating towards that, don't restart it.
- if let Some(anim) = &self.view_offset_anim {
- if anim.to().round() as i32 == new_view_offset {
- return;
- }
- }
-
- // If our view offset is already this, we don't need to do anything.
- if self.view_offset == new_view_offset {
- return;
- }
-
- self.view_offset_anim = Some(Animation::new(
- self.view_offset as f64,
- new_view_offset as f64,
- Duration::from_millis(250),
- ));
+ let center_x = self.view_pos();
+ self.animate_view_offset_to_column_centered(center_x, self.active_column_idx);
}
fn view_pos(&self) -> i32 {