Skip to content

Commit 0e669bc

Browse files
committed
feat(wm): add padding per monitor
This commit adds the ability to set a container and workspace padding per monitor. To do so and to simplify any future need of changing some value per monitor and have it pass through to each workspace a new field was added to the `Workspace` called `globals` which has a new struct called `WorkspaceGlobals` which includes any global values that might be needed by the workspace. This field is updated by the monitor for all its workspaces whenever the config is loaded or reloaded. It is also updated on `RetileAll` and on the function `update_focused_workspace`. This should make sure that every time a workspace needs to use it's `update` function it has all the `globals` up to date! This also means that now the `update` function from workspaces doesn't take any argument at all, reducing all the need to get all the `work_area`, `work_area_offset`, `window_based_work_area_offset` or `window_based_work_area_offset_limit` simplifying the callers of this function quite a bit. Lastly this commit has also (sort of accidentaly) fixed an existing bug with the `move_workspace_to_monitor` function which was removing the workspace from a monitor but wasn't changing it's `focused_workspace_idx` meaning that komorebi would get all messed up after that command, like the `border_manager` would get stuck and the komorebi-bar would crash. Now the `remove_focused_workspace` function also focus the previous workspace (which in turn will create a new workspace in case the removed one was the last workspace).
1 parent 9d41a29 commit 0e669bc

File tree

6 files changed

+181
-119
lines changed

6 files changed

+181
-119
lines changed

komorebi-client/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub use komorebi::window::Window;
4949
pub use komorebi::window_manager_event::WindowManagerEvent;
5050
pub use komorebi::workspace::Workspace;
5151
pub use komorebi::workspace::WorkspaceLayer;
52+
pub use komorebi::workspace::WorkspaceGlobals;
5253
pub use komorebi::AnimationsConfig;
5354
pub use komorebi::AspectRatio;
5455
pub use komorebi::BorderColours;

komorebi/src/monitor.rs

+60-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
22
use std::collections::VecDeque;
3+
use std::sync::atomic::Ordering;
34

45
use color_eyre::eyre::anyhow;
56
use color_eyre::eyre::bail;
@@ -21,6 +22,8 @@ use crate::DefaultLayout;
2122
use crate::Layout;
2223
use crate::OperationDirection;
2324
use crate::WindowsApi;
25+
use crate::DEFAULT_CONTAINER_PADDING;
26+
use crate::DEFAULT_WORKSPACE_PADDING;
2427

2528
#[derive(
2629
Debug,
@@ -61,6 +64,10 @@ pub struct Monitor {
6164
pub last_focused_workspace: Option<usize>,
6265
#[getset(get_mut = "pub")]
6366
pub workspace_names: HashMap<usize, String>,
67+
#[getset(get_copy = "pub", set = "pub")]
68+
pub container_padding: Option<i32>,
69+
#[getset(get_copy = "pub", set = "pub")]
70+
pub workspace_padding: Option<i32>,
6471
}
6572

6673
impl_ring_elements!(Monitor, Workspace);
@@ -114,6 +121,8 @@ pub fn new(
114121
workspaces,
115122
last_focused_workspace: None,
116123
workspace_names: HashMap::default(),
124+
container_padding: None,
125+
workspace_padding: None,
117126
}
118127
}
119128

@@ -153,6 +162,8 @@ impl Monitor {
153162
workspaces: Default::default(),
154163
last_focused_workspace: None,
155164
workspace_names: Default::default(),
165+
container_padding: None,
166+
workspace_padding: None,
156167
}
157168
}
158169

@@ -175,6 +186,52 @@ impl Monitor {
175186
Ok(())
176187
}
177188

189+
/// Updates the `globals` field of all workspaces
190+
pub fn update_workspaces_globals(&mut self, offset: Option<Rect>) {
191+
let container_padding = self
192+
.container_padding()
193+
.or(Some(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)));
194+
let workspace_padding = self
195+
.workspace_padding()
196+
.or(Some(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)));
197+
let work_area = *self.work_area_size();
198+
let offset = self.work_area_offset.or(offset);
199+
let window_based_work_area_offset = self.window_based_work_area_offset();
200+
let limit = self.window_based_work_area_offset_limit();
201+
202+
for workspace in self.workspaces_mut() {
203+
workspace.globals_mut().container_padding = container_padding;
204+
workspace.globals_mut().workspace_padding = workspace_padding;
205+
workspace.globals_mut().work_area = work_area;
206+
workspace.globals_mut().work_area_offset = offset;
207+
workspace.globals_mut().window_based_work_area_offset = window_based_work_area_offset;
208+
workspace.globals_mut().window_based_work_area_offset_limit = limit;
209+
}
210+
}
211+
212+
/// Updates the `globals` field of workspace with index `workspace_idx`
213+
pub fn update_workspace_globals(&mut self, workspace_idx: usize, offset: Option<Rect>) {
214+
let container_padding = self
215+
.container_padding()
216+
.or(Some(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)));
217+
let workspace_padding = self
218+
.workspace_padding()
219+
.or(Some(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)));
220+
let work_area = *self.work_area_size();
221+
let offset = self.work_area_offset.or(offset);
222+
let window_based_work_area_offset = self.window_based_work_area_offset();
223+
let limit = self.window_based_work_area_offset_limit();
224+
225+
if let Some(workspace) = self.workspaces_mut().get_mut(workspace_idx) {
226+
workspace.globals_mut().container_padding = container_padding;
227+
workspace.globals_mut().workspace_padding = workspace_padding;
228+
workspace.globals_mut().work_area = work_area;
229+
workspace.globals_mut().work_area_offset = offset;
230+
workspace.globals_mut().window_based_work_area_offset = window_based_work_area_offset;
231+
workspace.globals_mut().window_based_work_area_offset_limit = limit;
232+
}
233+
}
234+
178235
pub fn add_container(
179236
&mut self,
180237
container: Container,
@@ -401,21 +458,17 @@ impl Monitor {
401458
}
402459

403460
pub fn update_focused_workspace(&mut self, offset: Option<Rect>) -> Result<()> {
404-
let work_area = *self.work_area_size();
405-
let window_based_work_area_offset = (
406-
self.window_based_work_area_offset_limit(),
407-
self.window_based_work_area_offset(),
408-
);
409-
410461
let offset = if self.work_area_offset().is_some() {
411462
self.work_area_offset()
412463
} else {
413464
offset
414465
};
415466

467+
let focused_workspace_idx = self.focused_workspace_idx();
468+
self.update_workspace_globals(focused_workspace_idx, offset);
416469
self.focused_workspace_mut()
417470
.ok_or_else(|| anyhow!("there is no workspace"))?
418-
.update(&work_area, offset, window_based_work_area_offset)?;
471+
.update()?;
419472

420473
Ok(())
421474
}

komorebi/src/reaper.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,12 @@ fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()>
7070
for notification in receiver {
7171
let orphan_hwnds = notification.0;
7272
let mut wm = wm.lock();
73-
let offset = wm.work_area_offset;
7473

7574
let mut update_borders = false;
7675

7776
for (hwnd, (m_idx, w_idx)) in orphan_hwnds.iter() {
7877
if let Some(monitor) = wm.monitors_mut().get_mut(*m_idx) {
7978
let focused_workspace_idx = monitor.focused_workspace_idx();
80-
let work_area = *monitor.work_area_size();
81-
let window_based_work_area_offset = (
82-
monitor.window_based_work_area_offset_limit(),
83-
monitor.window_based_work_area_offset(),
84-
);
85-
86-
let offset = if monitor.work_area_offset().is_some() {
87-
monitor.work_area_offset()
88-
} else {
89-
offset
90-
};
9179

9280
if let Some(workspace) = monitor.workspaces_mut().get_mut(*w_idx) {
9381
// Remove orphan window
@@ -105,7 +93,7 @@ fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()>
10593
// If this is not a focused workspace there is no need to update the
10694
// workspace or the borders. That will already be done when the user
10795
// changes to this workspace.
108-
workspace.update(&work_area, offset, window_based_work_area_offset)?;
96+
workspace.update()?;
10997
update_borders = true;
11098
}
11199
tracing::info!(

komorebi/src/static_config.rs

+44
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,12 @@ pub struct MonitorConfig {
256256
/// Open window limit after which the window based work area offset will no longer be applied (default: 1)
257257
#[serde(skip_serializing_if = "Option::is_none")]
258258
pub window_based_work_area_offset_limit: Option<isize>,
259+
/// Container padding (default: global)
260+
#[serde(skip_serializing_if = "Option::is_none")]
261+
pub container_padding: Option<i32>,
262+
/// Container padding (default: global)
263+
#[serde(skip_serializing_if = "Option::is_none")]
264+
pub workspace_padding: Option<i32>,
259265
}
260266

261267
impl From<&Monitor> for MonitorConfig {
@@ -265,11 +271,32 @@ impl From<&Monitor> for MonitorConfig {
265271
workspaces.push(WorkspaceConfig::from(w));
266272
}
267273

274+
let default_container_padding = DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst);
275+
let default_workspace_padding = DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst);
276+
277+
let container_padding = value.container_padding().and_then(|container_padding| {
278+
if container_padding == default_container_padding {
279+
None
280+
} else {
281+
Option::from(container_padding)
282+
}
283+
});
284+
285+
let workspace_padding = value.workspace_padding().and_then(|workspace_padding| {
286+
if workspace_padding == default_workspace_padding {
287+
None
288+
} else {
289+
Option::from(workspace_padding)
290+
}
291+
});
292+
268293
Self {
269294
workspaces,
270295
work_area_offset: value.work_area_offset(),
271296
window_based_work_area_offset: value.window_based_work_area_offset(),
272297
window_based_work_area_offset_limit: Some(value.window_based_work_area_offset_limit()),
298+
container_padding,
299+
workspace_padding,
273300
}
274301
}
275302
}
@@ -1250,6 +1277,7 @@ impl StaticConfig {
12501277
workspace_matching_rules.clear();
12511278
drop(workspace_matching_rules);
12521279

1280+
let offset = wm.work_area_offset;
12531281
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
12541282
let preferred_config_idx = {
12551283
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
@@ -1295,7 +1323,10 @@ impl StaticConfig {
12951323
.window_based_work_area_offset_limit
12961324
.unwrap_or(1),
12971325
);
1326+
monitor.set_container_padding(monitor_config.container_padding);
1327+
monitor.set_workspace_padding(monitor_config.workspace_padding);
12981328

1329+
monitor.update_workspaces_globals(offset);
12991330
for (j, ws) in monitor.workspaces_mut().iter_mut().enumerate() {
13001331
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
13011332
ws.load_static_config(workspace_config)?;
@@ -1377,6 +1408,10 @@ impl StaticConfig {
13771408
.window_based_work_area_offset_limit
13781409
.unwrap_or(1),
13791410
);
1411+
m.set_container_padding(monitor_config.container_padding);
1412+
m.set_workspace_padding(monitor_config.workspace_padding);
1413+
1414+
m.update_workspaces_globals(offset);
13801415

13811416
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
13821417
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
@@ -1411,6 +1446,7 @@ impl StaticConfig {
14111446
workspace_matching_rules.clear();
14121447
drop(workspace_matching_rules);
14131448

1449+
let offset = wm.work_area_offset;
14141450
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
14151451
let preferred_config_idx = {
14161452
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
@@ -1458,6 +1494,10 @@ impl StaticConfig {
14581494
.window_based_work_area_offset_limit
14591495
.unwrap_or(1),
14601496
);
1497+
monitor.set_container_padding(monitor_config.container_padding);
1498+
monitor.set_workspace_padding(monitor_config.workspace_padding);
1499+
1500+
monitor.update_workspaces_globals(offset);
14611501

14621502
for (j, ws) in monitor.workspaces_mut().iter_mut().enumerate() {
14631503
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
@@ -1540,6 +1580,10 @@ impl StaticConfig {
15401580
.window_based_work_area_offset_limit
15411581
.unwrap_or(1),
15421582
);
1583+
m.set_container_padding(monitor_config.container_padding);
1584+
m.set_workspace_padding(monitor_config.workspace_padding);
1585+
1586+
m.update_workspaces_globals(offset);
15431587

15441588
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
15451589
if let Some(workspace_config) = monitor_config.workspaces.get(j) {

0 commit comments

Comments
 (0)