From 5b1de86d336f7d617f98048fe4318061320d6a29 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Thu, 21 Dec 2023 08:37:30 +0400 Subject: Add configurable struts --- src/config.rs | 26 ++++++++++++++++++++++++++ src/layout.rs | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b5428429..b5e98adf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -28,6 +28,8 @@ pub struct Config { pub default_column_width: Option, #[knuffel(child, unwrap(argument), default = 16)] pub gaps: u16, + #[knuffel(child, default)] + pub struts: Struts, #[knuffel( child, unwrap(argument), @@ -238,6 +240,18 @@ pub enum PresetWidth { #[derive(knuffel::Decode, Debug, Clone, PartialEq)] pub struct DefaultColumnWidth(#[knuffel(children)] pub Vec); +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Struts { + #[knuffel(child, unwrap(argument), default)] + pub left: u16, + #[knuffel(child, unwrap(argument), default)] + pub right: u16, + #[knuffel(child, unwrap(argument), default)] + pub top: u16, + #[knuffel(child, unwrap(argument), default)] + pub bottom: u16, +} + #[derive(knuffel::Decode, Debug, Default, PartialEq)] pub struct Binds(#[knuffel(children)] pub Vec); @@ -594,6 +608,12 @@ mod tests { gaps 8 + struts { + left 1 + right 2 + top 3 + } + screenshot-path "~/Screenshots/screenshot.png" binds { @@ -673,6 +693,12 @@ mod tests { ], default_column_width: Some(DefaultColumnWidth(vec![PresetWidth::Proportion(0.25)])), gaps: 8, + struts: Struts { + left: 1, + right: 2, + top: 3, + bottom: 0, + }, screenshot_path: Some(String::from("~/Screenshots/screenshot.png")), binds: Binds(vec![ Bind { diff --git a/src/layout.rs b/src/layout.rs index b53529f5..bf012311 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -56,7 +56,7 @@ use smithay::wayland::compositor::{send_surface_state, with_states}; use smithay::wayland::shell::xdg::SurfaceCachedState; use crate::animation::Animation; -use crate::config::{self, Color, Config, PresetWidth, SizeChange}; +use crate::config::{self, Color, Config, PresetWidth, SizeChange, Struts}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct OutputId(String); @@ -205,6 +205,8 @@ struct FocusRing { struct Options { /// Padding around windows in logical pixels. gaps: i32, + /// Extra padding around the working area in logical pixels. + struts: Struts, focus_ring: config::FocusRing, /// Column widths that `toggle_width()` switches between. preset_widths: Vec, @@ -216,6 +218,7 @@ impl Default for Options { fn default() -> Self { Self { gaps: 16, + struts: Default::default(), focus_ring: Default::default(), preset_widths: vec![ ColumnWidth::Proportion(1. / 3.), @@ -251,6 +254,7 @@ impl Options { Self { gaps: config.gaps.into(), + struts: config.struts, focus_ring: config.focus_ring, preset_widths, default_width, @@ -830,7 +834,7 @@ impl Layout { for mon in monitors { if &mon.output == output { let view_size = output_size(output); - let working_area = layer_map_for_output(output).non_exclusive_zone(); + let working_area = compute_working_area(output, self.options.struts); for ws in &mut mon.workspaces { ws.set_view_size(view_size, working_area); @@ -1886,6 +1890,15 @@ impl Monitor { ws.update_config(options.clone()); } + if self.options.struts != options.struts { + let view_size = output_size(&self.output); + let working_area = compute_working_area(&self.output, options.struts); + + for ws in &mut self.workspaces { + ws.set_view_size(view_size, working_area); + } + } + self.options = options; } @@ -2064,7 +2077,7 @@ impl Monitor { impl Workspace { fn new(output: Output, options: Rc) -> Self { - let working_area = layer_map_for_output(&output).non_exclusive_zone(); + let working_area = compute_working_area(&output, options.struts); Self { original_output: OutputId::new(&output), view_size: output_size(&output), @@ -2164,7 +2177,7 @@ impl Workspace { self.output = output; if let Some(output) = &self.output { - let working_area = layer_map_for_output(output).non_exclusive_zone(); + let working_area = compute_working_area(output, self.options.struts); self.set_view_size(output_size(output), working_area); for win in self.windows() { @@ -3261,6 +3274,27 @@ pub fn output_size(output: &Output) -> Size { .to_logical(output_scale) } +fn compute_working_area(output: &Output, struts: Struts) -> Rectangle { + // Start with the layer-shell non-exclusive zone. + let mut working_area = layer_map_for_output(output).non_exclusive_zone(); + + // Add struts. + let w = working_area.size.w; + let h = working_area.size.h; + + working_area.size.w = w + .saturating_sub(struts.left.into()) + .saturating_sub(struts.right.into()); + working_area.loc.x += struts.left as i32; + + working_area.size.h = h + .saturating_sub(struts.top.into()) + .saturating_sub(struts.bottom.into()); + working_area.loc.y += struts.top as i32; + + working_area +} + fn compute_new_view_offset( cur_x: i32, view_width: i32, -- cgit