mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-24 18:31:22 +01:00
feat(wm): add single window work area offsets
This commit adds a new monitor configuration option, single_window_work_area_offset, which will apply to a monitor when only a single window is open on a workspace. This is implemented as a Rect to enable its use on both horizontally and vertically positioned monitors. This option will be particularly useful for ultrawide monitor users, where a single window taking up the full width of the work area can often hinder usability. resolve #434
This commit is contained in:
@@ -36,6 +36,8 @@ pub struct Monitor {
|
||||
work_area_size: Rect,
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
work_area_offset: Option<Rect>,
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
single_window_work_area_offset: Option<Rect>,
|
||||
workspaces: Ring<Workspace>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[getset(get_copy = "pub", set = "pub")]
|
||||
@@ -58,6 +60,7 @@ pub fn new(id: isize, size: Rect, work_area_size: Rect, name: String) -> Monitor
|
||||
size,
|
||||
work_area_size,
|
||||
work_area_offset: None,
|
||||
single_window_work_area_offset: None,
|
||||
workspaces,
|
||||
last_focused_workspace: None,
|
||||
workspace_names: HashMap::default(),
|
||||
@@ -194,6 +197,7 @@ impl Monitor {
|
||||
|
||||
pub fn update_focused_workspace(&mut self, offset: Option<Rect>) -> Result<()> {
|
||||
let work_area = *self.work_area_size();
|
||||
let single_window_work_area_offset = self.single_window_work_area_offset();
|
||||
let offset = if self.work_area_offset().is_some() {
|
||||
self.work_area_offset()
|
||||
} else {
|
||||
@@ -202,7 +206,7 @@ impl Monitor {
|
||||
|
||||
self.focused_workspace_mut()
|
||||
.ok_or_else(|| anyhow!("there is no workspace"))?
|
||||
.update(&work_area, offset)?;
|
||||
.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ impl WindowManager {
|
||||
|
||||
for (i, monitor) in self.monitors_mut().iter_mut().enumerate() {
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
} else {
|
||||
@@ -139,7 +140,7 @@ impl WindowManager {
|
||||
|
||||
let reaped_orphans = workspace.reap_orphans()?;
|
||||
if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
tracing::info!(
|
||||
"reaped {} orphan window(s) and {} orphaned container(s) on monitor: {}, workspace: {}",
|
||||
reaped_orphans.0,
|
||||
|
||||
@@ -201,6 +201,9 @@ pub struct MonitorConfig {
|
||||
/// Monitor-specific work area offset (default: None)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub work_area_offset: Option<Rect>,
|
||||
/// Single window work area offset (default: None)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub single_window_work_area_offset: Option<Rect>,
|
||||
}
|
||||
|
||||
impl From<&Monitor> for MonitorConfig {
|
||||
@@ -213,6 +216,7 @@ impl From<&Monitor> for MonitorConfig {
|
||||
Self {
|
||||
workspaces,
|
||||
work_area_offset: value.work_area_offset(),
|
||||
single_window_work_area_offset: value.single_window_work_area_offset(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -694,6 +698,7 @@ impl StaticConfig {
|
||||
if let Some(m) = wm.monitors_mut().get_mut(i) {
|
||||
m.ensure_workspace_count(monitor.workspaces.len());
|
||||
m.set_work_area_offset(monitor.work_area_offset);
|
||||
m.set_single_window_work_area_offset(monitor.single_window_work_area_offset);
|
||||
|
||||
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
|
||||
ws.load_static_config(
|
||||
@@ -749,6 +754,7 @@ impl StaticConfig {
|
||||
if let Some(m) = wm.monitors_mut().get_mut(i) {
|
||||
m.ensure_workspace_count(monitor.workspaces.len());
|
||||
m.set_work_area_offset(monitor.work_area_offset);
|
||||
m.set_single_window_work_area_offset(monitor.single_window_work_area_offset);
|
||||
|
||||
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
|
||||
ws.load_static_config(
|
||||
|
||||
@@ -713,6 +713,7 @@ impl WindowManager {
|
||||
|
||||
for monitor in self.monitors_mut() {
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
} else {
|
||||
@@ -730,7 +731,7 @@ impl WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1943,6 +1944,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
@@ -1962,7 +1964,7 @@ impl WindowManager {
|
||||
|
||||
// If this is the focused workspace on a non-focused screen, let's update it
|
||||
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.update_focused_workspace(false, false)?)
|
||||
@@ -1991,6 +1993,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
@@ -2012,7 +2015,7 @@ impl WindowManager {
|
||||
|
||||
// If this is the focused workspace on a non-focused screen, let's update it
|
||||
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.update_focused_workspace(false, false)?)
|
||||
@@ -2036,6 +2039,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
@@ -2053,7 +2057,7 @@ impl WindowManager {
|
||||
|
||||
// If this is the focused workspace on a non-focused screen, let's update it
|
||||
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.update_focused_workspace(false, false)?)
|
||||
@@ -2078,6 +2082,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
@@ -2094,7 +2099,7 @@ impl WindowManager {
|
||||
|
||||
// If this is the focused workspace on a non-focused screen, let's update it
|
||||
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.update_focused_workspace(false, false)?)
|
||||
@@ -2122,6 +2127,7 @@ impl WindowManager {
|
||||
.ok_or_else(|| anyhow!("there is no monitor"))?;
|
||||
|
||||
let work_area = *monitor.work_area_size();
|
||||
let single_window_work_area_offset = monitor.single_window_work_area_offset();
|
||||
let focused_workspace_idx = monitor.focused_workspace_idx();
|
||||
let offset = if monitor.work_area_offset().is_some() {
|
||||
monitor.work_area_offset()
|
||||
@@ -2139,7 +2145,7 @@ impl WindowManager {
|
||||
|
||||
// If this is the focused workspace on a non-focused screen, let's update it
|
||||
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||
workspace.update(&work_area, offset)?;
|
||||
workspace.update(&work_area, offset, single_window_work_area_offset)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(self.update_focused_workspace(false, false)?)
|
||||
|
||||
@@ -219,13 +219,18 @@ impl Workspace {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update(&mut self, work_area: &Rect, offset: Option<Rect>) -> Result<()> {
|
||||
pub fn update(
|
||||
&mut self,
|
||||
work_area: &Rect,
|
||||
work_area_offset: Option<Rect>,
|
||||
single_window_work_area_offset: Option<Rect>,
|
||||
) -> Result<()> {
|
||||
if !INITIAL_CONFIGURATION_LOADED.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let container_padding = self.container_padding();
|
||||
let mut adjusted_work_area = offset.map_or_else(
|
||||
let mut adjusted_work_area = work_area_offset.map_or_else(
|
||||
|| *work_area,
|
||||
|offset| {
|
||||
let mut with_offset = *work_area;
|
||||
@@ -238,6 +243,21 @@ impl Workspace {
|
||||
},
|
||||
);
|
||||
|
||||
if self.containers().len() == 1 {
|
||||
adjusted_work_area = single_window_work_area_offset.map_or_else(
|
||||
|| *work_area,
|
||||
|offset| {
|
||||
let mut with_offset = *work_area;
|
||||
with_offset.left += offset.left;
|
||||
with_offset.top += offset.top;
|
||||
with_offset.right -= offset.right;
|
||||
with_offset.bottom -= offset.bottom;
|
||||
|
||||
with_offset
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
adjusted_work_area.add_padding(self.workspace_padding().unwrap_or_default());
|
||||
|
||||
self.enforce_resize_constraints();
|
||||
|
||||
Reference in New Issue
Block a user