Skip to content

Commit

Permalink
feat: add gaps.scale_with_dpi config option for adjusting inner/out…
Browse files Browse the repository at this point in the history
…er gaps (#768)
  • Loading branch information
lars-berger authored Oct 4, 2024
1 parent 0f9b562 commit 829bf0a
Show file tree
Hide file tree
Showing 25 changed files with 171 additions and 154 deletions.
5 changes: 3 additions & 2 deletions packages/wm/src/common/commands/platform_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ fn redraw_containers(state: &mut WmState) -> anyhow::Result<()> {
},
);

let rect =
window.to_rect()?.apply_delta(&window.total_border_delta()?);
let rect = window
.to_rect()?
.apply_delta(&window.total_border_delta()?, None);

let is_visible = match window.display_state() {
DisplayState::Showing | DisplayState::Shown => true,
Expand Down
4 changes: 2 additions & 2 deletions packages/wm/src/common/commands/reload_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ fn update_container_gaps(state: &mut WmState, config: &UserConfig) {
.filter_map(|container| container.as_tiling_container().ok());

for container in tiling_containers {
container.set_inner_gap(config.value.gaps.inner_gap.clone());
container.set_gaps_config(config.value.gaps.clone());
}

for workspace in state.workspaces() {
workspace.set_outer_gap(config.value.gaps.outer_gap.clone());
workspace.set_gaps_config(config.value.gaps.clone());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ use tracing::info;

use crate::{
common::platform::Platform,
containers::{
traits::{CommonGetters, PositionGetters},
WindowContainer,
},
containers::traits::{CommonGetters, PositionGetters},
monitors::commands::{
add_monitor, remove_monitor, sort_monitors, update_monitor,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ fn drop_as_tiling_window(
if should_split {
let split_container = SplitContainer::new(
tiling_direction.inverse(),
config.value.gaps.inner_gap.clone(),
config.value.gaps.clone(),
);

wrap_in_split_container(
Expand Down
25 changes: 5 additions & 20 deletions packages/wm/src/common/length_value.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{ops::Mul, str::FromStr};
use std::str::FromStr;

use anyhow::{bail, Context};
use regex::Regex;
Expand All @@ -25,17 +25,12 @@ impl LengthValue {
}
}

pub fn to_px(&self, total_px: i32) -> i32 {
match self.unit {
LengthUnit::Percentage => (self.amount * total_px as f32) as i32,
LengthUnit::Pixel => self.amount as i32,
}
}
pub fn to_px(&self, total_px: i32, scale_factor: Option<f32>) -> i32 {
let scale_factor = scale_factor.unwrap_or(1.0);

pub fn to_px_scaled(&self, total_px: i32, scale_factor: f32) -> i32 {
match self.unit {
LengthUnit::Percentage => self.to_px(total_px),
LengthUnit::Pixel => (scale_factor * self.amount) as i32,
LengthUnit::Percentage => (self.amount * total_px as f32) as i32,
LengthUnit::Pixel => (self.amount * scale_factor) as i32,
}
}

Expand Down Expand Up @@ -111,13 +106,3 @@ impl<'de> Deserialize<'de> for LengthValue {
}
}
}

impl Mul<f32> for LengthValue {
type Output = Self;
fn mul(self, rhs: f32) -> Self {
Self {
amount: self.amount * rhs,
unit: self.unit,
}
}
}
42 changes: 29 additions & 13 deletions packages/wm/src/common/rect.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};

use super::{Direction, Point, RectDelta};
use super::{Direction, LengthValue, Point, RectDelta};

#[derive(Debug, Deserialize, Clone, Serialize, Eq, PartialEq)]
pub struct Rect {
Expand Down Expand Up @@ -115,23 +115,39 @@ impl Rect {
}
}

// TODO: Pass in a `Rect` for unit conversion.
pub fn apply_delta(&self, delta: &RectDelta) -> Self {
/// Gets the delta between this rect and another rect.
pub fn delta(&self, other: &Rect) -> RectDelta {
RectDelta {
left: LengthValue::from_px(self.left - other.left),
top: LengthValue::from_px(self.top - other.top),
right: LengthValue::from_px(self.right - other.right),
bottom: LengthValue::from_px(self.bottom - other.bottom),
}
}

pub fn apply_delta(
&self,
delta: &RectDelta,
scale_factor: Option<f32>,
) -> Self {
Self::from_ltrb(
self.left - delta.left.to_px(self.width()),
self.top - delta.top.to_px(self.height()),
self.right + delta.right.to_px(self.width()),
self.bottom + delta.bottom.to_px(self.height()),
self.left - delta.left.to_px(self.width(), scale_factor),
self.top - delta.top.to_px(self.height(), scale_factor),
self.right + delta.right.to_px(self.width(), scale_factor),
self.bottom + delta.bottom.to_px(self.height(), scale_factor),
)
}

// TODO: Pass in a `Rect` for unit conversion.
pub fn apply_inverse_delta(&self, delta: &RectDelta) -> Self {
pub fn apply_inverse_delta(
&self,
delta: &RectDelta,
scale_factor: Option<f32>,
) -> Self {
Self::from_ltrb(
self.left + delta.left.to_px(self.width()),
self.top + delta.top.to_px(self.height()),
self.right - delta.right.to_px(self.width()),
self.bottom - delta.bottom.to_px(self.height()),
self.left + delta.left.to_px(self.width(), scale_factor),
self.top + delta.top.to_px(self.height(), scale_factor),
self.right - delta.right.to_px(self.width(), scale_factor),
self.bottom - delta.bottom.to_px(self.height(), scale_factor),
)
}

Expand Down
14 changes: 0 additions & 14 deletions packages/wm/src/common/rect_delta.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::ops::Mul;

use serde::{Deserialize, Serialize};

use super::LengthValue;
Expand Down Expand Up @@ -34,15 +32,3 @@ impl RectDelta {
}
}
}

impl Mul<f32> for RectDelta {
type Output = Self;
fn mul(self, rhs: f32) -> Self {
Self::new(
self.left * rhs,
self.top * rhs,
self.right * rhs,
self.bottom * rhs,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn toggle_window_direction(
// Create a new split container to wrap the window.
let split_container = SplitContainer::new(
parent.tiling_direction().inverse(),
config.value.gaps.inner_gap.clone(),
config.value.gaps.clone(),
);

wrap_in_split_container(
Expand Down
6 changes: 3 additions & 3 deletions packages/wm/src/containers/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use uuid::Uuid;
use super::{RootContainer, SplitContainer};
use crate::{
common::{
platform::NativeWindow, Direction, DisplayState, LengthValue, Rect,
RectDelta, TilingDirection,
platform::NativeWindow, Direction, DisplayState, Rect, RectDelta,
TilingDirection,
},
containers::{traits::*, ContainerDto},
monitors::Monitor,
user_config::{UserConfig, WindowRuleConfig},
user_config::{GapsConfig, UserConfig, WindowRuleConfig},
windows::{
traits::*, ActiveDrag, NonTilingWindow, TilingWindow, WindowState,
},
Expand Down
9 changes: 5 additions & 4 deletions packages/wm/src/containers/split_container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ use super::{
WindowContainer,
};
use crate::{
common::{LengthValue, Rect, TilingDirection},
common::{Rect, TilingDirection},
impl_common_getters, impl_container_debug,
impl_position_getters_as_resizable, impl_tiling_direction_getters,
impl_tiling_size_getters,
user_config::GapsConfig,
};

#[derive(Clone)]
Expand All @@ -33,7 +34,7 @@ struct SplitContainerInner {
child_focus_order: VecDeque<Uuid>,
tiling_size: f32,
tiling_direction: TilingDirection,
inner_gap: LengthValue,
gaps_config: GapsConfig,
}

/// User-friendly representation of a split container.
Expand All @@ -58,7 +59,7 @@ pub struct SplitContainerDto {
impl SplitContainer {
pub fn new(
tiling_direction: TilingDirection,
inner_gap: LengthValue,
gaps_config: GapsConfig,
) -> Self {
let split = SplitContainerInner {
id: Uuid::new_v4(),
Expand All @@ -67,7 +68,7 @@ impl SplitContainer {
child_focus_order: VecDeque::new(),
tiling_size: 1.0,
tiling_direction,
inner_gap,
gaps_config,
};

Self(Rc::new(RefCell::new(split)))
Expand Down
10 changes: 3 additions & 7 deletions packages/wm/src/containers/traits/position_getters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,11 @@ macro_rules! impl_position_getters_as_resizable {
.context("Parent does not have a tiling direction.")?;

let parent_rect = parent.to_rect()?;
let monitor = self.monitor().context("No monitor.")?;

let (horizontal_gap, vertical_gap) = self.inner_gaps()?;
let inner_gap = match parent.tiling_direction() {
TilingDirection::Vertical => {
self.inner_gap().to_px(monitor.to_rect()?.height())
}
TilingDirection::Horizontal => {
self.inner_gap().to_px(monitor.to_rect()?.width())
}
TilingDirection::Vertical => vertical_gap,
TilingDirection::Horizontal => horizontal_gap,
};

let (width, height) = match parent.tiling_direction() {
Expand Down
47 changes: 32 additions & 15 deletions packages/wm/src/containers/traits/tiling_size_getters.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::cell::Ref;

use ambassador::delegatable_trait;
use anyhow::Context;

use super::{CommonGetters, TilingDirectionGetters};
use super::{CommonGetters, PositionGetters, TilingDirectionGetters};
use crate::{
common::{LengthValue, TilingDirection},
common::TilingDirection,
containers::{Container, DirectionContainer, TilingContainer},
user_config::GapsConfig,
};

pub const MIN_TILING_SIZE: f32 = 0.01;
Expand All @@ -15,9 +18,30 @@ pub trait TilingSizeGetters: CommonGetters {

fn set_tiling_size(&self, tiling_size: f32);

fn inner_gap(&self) -> LengthValue;
fn gaps_config(&self) -> Ref<'_, GapsConfig>;

fn set_gaps_config(&self, gaps_config: GapsConfig);

fn set_inner_gap(&self, inner_gap: LengthValue);
/// Gets the horizontal and vertical gaps between windows in pixels.
fn inner_gaps(&self) -> anyhow::Result<(i32, i32)> {
let monitor = self.monitor().context("No monitor.")?;
let monitor_rect = monitor.to_rect()?;
let gaps_config = self.gaps_config();

let scale_factor = match gaps_config.scale_with_dpi {
true => monitor.native().dpi()?,
false => 1.,
};

Ok((
gaps_config
.inner_gap
.to_px(monitor_rect.height(), Some(scale_factor)),
gaps_config
.inner_gap
.to_px(monitor_rect.width(), Some(scale_factor)),
))
}

/// Gets the container to resize when resizing a tiling window.
fn container_to_resize(
Expand Down Expand Up @@ -76,19 +100,12 @@ macro_rules! impl_tiling_size_getters {
self.0.borrow_mut().tiling_size = tiling_size;
}

fn inner_gap(&self) -> LengthValue {
let scale = match self.monitor() {
None => 1_f32,
Some(monitor) => match monitor.native().dpi() {
Ok(dpi) => dpi,
Err(_) => 1_f32,
},
};
self.0.borrow().inner_gap.clone() * scale
fn gaps_config(&self) -> Ref<'_, GapsConfig> {
Ref::map(self.0.borrow(), |inner| &inner.gaps_config)
}

fn set_inner_gap(&self, inner_gap: LengthValue) {
self.0.borrow_mut().inner_gap = inner_gap;
fn set_gaps_config(&self, gaps_config: GapsConfig) {
self.0.borrow_mut().gaps_config = gaps_config;
}
}
};
Expand Down
4 changes: 4 additions & 0 deletions packages/wm/src/user_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,10 @@ pub struct BindingModeConfig {
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all(serialize = "camelCase"))]
pub struct GapsConfig {
/// Whether to scale the gaps with the DPI of the monitor.
#[serde(default = "default_bool::<true>")]
pub scale_with_dpi: bool,

/// Gap between adjacent windows.
pub inner_gap: LengthValue,

Expand Down
4 changes: 2 additions & 2 deletions packages/wm/src/windows/commands/manage_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ fn create_window(
LengthValue::from_px(0),
);

let inner_gap = config.value.gaps.inner_gap.clone();
let gaps_config = config.value.gaps.clone();
let window_state =
window_state_to_create(&native_window, &nearest_monitor, config)?;

Expand All @@ -134,7 +134,7 @@ fn create_window(
None,
border_delta,
floating_placement,
inner_gap,
gaps_config,
Vec::new(),
None,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ fn invert_workspace_tiling_direction(
if workspace_children.len() > 1 {
let split_container = SplitContainer::new(
workspace.tiling_direction(),
config.value.gaps.inner_gap.clone(),
config.value.gaps.clone(),
);

wrap_in_split_container(
Expand Down
Loading

0 comments on commit 829bf0a

Please sign in to comment.