feat(wm): add dynamic work area offsets

This commit adds a config setting to let you set custom
work_area_offset_rules for a workspace, following the same schema as
layout_rules.
This commit is contained in:
omark96
2025-08-02 23:14:11 +02:00
committed by LGUG2Z
parent c84fa50fc9
commit d3779e5a74
3 changed files with 41 additions and 2 deletions

View File

@@ -253,6 +253,7 @@ impl From<&WindowManager> for State {
layout: workspace.layout.clone(),
layout_options: workspace.layout_options,
layout_rules: workspace.layout_rules.clone(),
work_area_offset_rules: workspace.work_area_offset_rules.clone(),
layout_flip: workspace.layout_flip,
workspace_padding: workspace.workspace_padding,
container_padding: workspace.container_padding,

View File

@@ -223,6 +223,9 @@ pub struct WorkspaceConfig {
/// Layout rules in the format of threshold => layout
#[serde(skip_serializing_if = "Option::is_none")]
pub layout_rules: Option<HashMap<usize, DefaultLayout>>,
/// Work area offset rules in the format of threshold => Rect (default: None)
#[serde(skip_serializing_if = "Option::is_none")]
pub work_area_offset_rules: Option<HashMap<usize, Rect>>,
/// END OF LIFE FEATURE: Custom layout rules
#[deprecated(note = "End of life feature")]
#[serde(skip_serializing_if = "Option::is_none")]
@@ -287,6 +290,13 @@ impl From<&Workspace> for WorkspaceConfig {
}
let layout_rules = (!layout_rules.is_empty()).then_some(layout_rules);
let mut work_area_offset_rules = HashMap::new();
for (threshold, offset) in &value.work_area_offset_rules {
work_area_offset_rules.insert(*threshold, *offset);
}
let work_area_offset_rules =
(!work_area_offset_rules.is_empty()).then_some(work_area_offset_rules);
let mut window_container_behaviour_rules = HashMap::new();
for (threshold, behaviour) in value.window_container_behaviour_rules.iter().flatten() {
window_container_behaviour_rules.insert(*threshold, *behaviour);
@@ -353,6 +363,7 @@ impl From<&Workspace> for WorkspaceConfig {
.workspace_config
.as_ref()
.and_then(|c| c.workspace_rules.clone()),
work_area_offset_rules,
work_area_offset: value.work_area_offset,
apply_window_based_work_area_offset: Some(value.apply_window_based_work_area_offset),
window_container_behaviour: value.window_container_behaviour,

View File

@@ -61,6 +61,7 @@ pub struct Workspace {
pub layout: Layout,
pub layout_options: Option<LayoutOptions>,
pub layout_rules: Vec<(usize, Layout)>,
pub work_area_offset_rules: Vec<(usize, Rect)>,
pub layout_flip: Option<Axis>,
pub workspace_padding: Option<i32>,
pub container_padding: Option<i32>,
@@ -118,6 +119,7 @@ impl Default for Workspace {
layout: Layout::Default(DefaultLayout::BSP),
layout_options: None,
layout_rules: vec![],
work_area_offset_rules: vec![],
layout_flip: None,
workspace_padding: Option::from(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)),
container_padding: Option::from(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)),
@@ -213,6 +215,15 @@ impl Workspace {
self.layout_rules = all_layout_rules;
}
let mut all_work_area_offset_rules = vec![];
if let Some(work_area_offset_rules) = &config.work_area_offset_rules {
for (count, rect) in work_area_offset_rules {
all_work_area_offset_rules.push((*count, *rect));
}
all_work_area_offset_rules.sort_by_key(|(i, _)| *i);
self.work_area_offset_rules = all_work_area_offset_rules;
}
self.work_area_offset = config.work_area_offset;
self.apply_window_based_work_area_offset =
@@ -479,9 +490,26 @@ impl Workspace {
let border_width = self.globals.border_width;
let border_offset = self.globals.border_offset;
let work_area = self.globals.work_area;
let work_area_offset = self.work_area_offset.or(self.globals.work_area_offset);
let window_based_work_area_offset = self.globals.window_based_work_area_offset;
let window_based_work_area_offset_limit = self.globals.window_based_work_area_offset_limit;
let mut rules_work_area_offset = None;
if !self.work_area_offset_rules.is_empty() && self.monocle_container.is_none() {
for (threshold, work_area_offset_rule) in &self.work_area_offset_rules {
if self.containers().len() >= *threshold {
rules_work_area_offset = Some(*work_area_offset_rule);
}
}
// if self.monocle_container.is_some() {
// for (threshold, work_area_offset) in &self.work_area_offset_rules {
// if 1 >= *threshold {
// updated_work_area_offset = Option::from(work_area_offset);
// }
// }
// }
};
let work_area_offset = rules_work_area_offset
.or(self.work_area_offset)
.or(self.globals.work_area_offset);
let mut adjusted_work_area = work_area_offset.map_or_else(
|| work_area,
@@ -495,7 +523,6 @@ impl Workspace {
with_offset
},
);
if (self.containers().len() <= window_based_work_area_offset_limit as usize
|| self.monocle_container.is_some() && window_based_work_area_offset_limit > 0)
&& self.apply_window_based_work_area_offset