mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-09 06:25:23 +02:00
feat(wm): add cmd to specify work area offsets
This commit adds a new komorebic command to specify offsets for work areas to be applied across all monitors. The areas covered by these offsets will be excluded from the tiling area, and can be used for custom task bars, Rainmeter desktop widgets etc. When setting an offset at the top, the same offset will need to be applied to the bottom to ensure that the tiling area is not pushed off of the screen, but this is not necessary when applying an offset to the bottom as the top of the work area will never go lower than 0. resolve #46
This commit is contained in:
Generated
+2
-2
@@ -1172,9 +1172,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.20.4"
|
version = "0.20.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffff4a02fa61eee51f95210fc9c98ea6eeb46bb071adeafd61e1a0b9b22c6a6d"
|
checksum = "e223c65cd36b485a34c2ce6e38efa40777d31c4166d9076030c74cdcf971679f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ cycle-monitor Focus the monitor in the given cycle direction
|
|||||||
cycle-workspace Focus the workspace in the given cycle direction
|
cycle-workspace Focus the workspace in the given cycle direction
|
||||||
new-workspace Create and append a new workspace on the focused monitor
|
new-workspace Create and append a new workspace on the focused monitor
|
||||||
invisible-borders Set the invisible border dimensions around each window
|
invisible-borders Set the invisible border dimensions around each window
|
||||||
|
work-area-offset Set offsets to exclude parts of the work area from tiling
|
||||||
adjust-container-padding Adjust container padding on the focused workspace
|
adjust-container-padding Adjust container padding on the focused workspace
|
||||||
adjust-workspace-padding Adjust workspace padding on the focused workspace
|
adjust-workspace-padding Adjust workspace padding on the focused workspace
|
||||||
change-layout Set the layout on the focused workspace
|
change-layout Set the layout on the focused workspace
|
||||||
@@ -313,6 +314,7 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
|||||||
- [x] Additional manage rules based on exe name and window class
|
- [x] Additional manage rules based on exe name and window class
|
||||||
- [x] Identify applications which overflow their borders by exe name and class
|
- [x] Identify applications which overflow their borders by exe name and class
|
||||||
- [x] Identify 'close/minimize to tray' applications by exe name and class
|
- [x] Identify 'close/minimize to tray' applications by exe name and class
|
||||||
|
- [x] Configure work area offsets to preserve space for custom taskbars
|
||||||
- [x] Configure and compensate for the size of Windows 10's invisible borders
|
- [x] Configure and compensate for the size of Windows 10's invisible borders
|
||||||
- [x] Toggle floating windows
|
- [x] Toggle floating windows
|
||||||
- [x] Toggle monocle window
|
- [x] Toggle monocle window
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ pub enum SocketMessage {
|
|||||||
ReloadConfiguration,
|
ReloadConfiguration,
|
||||||
WatchConfiguration(bool),
|
WatchConfiguration(bool),
|
||||||
InvisibleBorders(Rect),
|
InvisibleBorders(Rect),
|
||||||
|
WorkAreaOffset(Rect),
|
||||||
WorkspaceRule(ApplicationIdentifier, String, usize, usize),
|
WorkspaceRule(ApplicationIdentifier, String, usize, usize),
|
||||||
FloatRule(ApplicationIdentifier, String),
|
FloatRule(ApplicationIdentifier, String),
|
||||||
ManageRule(ApplicationIdentifier, String),
|
ManageRule(ApplicationIdentifier, String),
|
||||||
|
|||||||
@@ -146,12 +146,16 @@ impl Monitor {
|
|||||||
self.workspaces().len()
|
self.workspaces().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_focused_workspace(&mut self, invisible_borders: &Rect) -> Result<()> {
|
pub fn update_focused_workspace(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<Rect>,
|
||||||
|
invisible_borders: &Rect,
|
||||||
|
) -> Result<()> {
|
||||||
let work_area = *self.work_area_size();
|
let work_area = *self.work_area_size();
|
||||||
|
|
||||||
self.focused_workspace_mut()
|
self.focused_workspace_mut()
|
||||||
.ok_or_else(|| anyhow!("there is no workspace"))?
|
.ok_or_else(|| anyhow!("there is no workspace"))?
|
||||||
.update(&work_area, invisible_borders)?;
|
.update(&work_area, offset, invisible_borders)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,6 +371,10 @@ impl WindowManager {
|
|||||||
self.invisible_borders = rect;
|
self.invisible_borders = rect;
|
||||||
self.retile_all()?;
|
self.retile_all()?;
|
||||||
}
|
}
|
||||||
|
SocketMessage::WorkAreaOffset(rect) => {
|
||||||
|
self.work_area_offset = Option::from(rect);
|
||||||
|
self.retile_all()?;
|
||||||
|
}
|
||||||
SocketMessage::QuickSave => {
|
SocketMessage::QuickSave => {
|
||||||
let workspace = self.focused_workspace()?;
|
let workspace = self.focused_workspace()?;
|
||||||
let resize = workspace.resize_dimensions();
|
let resize = workspace.resize_dimensions();
|
||||||
|
|||||||
@@ -66,13 +66,14 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
|
|
||||||
for (i, monitor) in self.monitors_mut().iter_mut().enumerate() {
|
for (i, monitor) in self.monitors_mut().iter_mut().enumerate() {
|
||||||
let work_area = *monitor.work_area_size();
|
let work_area = *monitor.work_area_size();
|
||||||
for (j, workspace) in monitor.workspaces_mut().iter_mut().enumerate() {
|
for (j, workspace) in monitor.workspaces_mut().iter_mut().enumerate() {
|
||||||
let reaped_orphans = workspace.reap_orphans()?;
|
let reaped_orphans = workspace.reap_orphans()?;
|
||||||
if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 {
|
if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 {
|
||||||
workspace.update(&work_area, &invisible_borders)?;
|
workspace.update(&work_area, offset, &invisible_borders)?;
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"reaped {} orphan window(s) and {} orphaned container(s) on monitor: {}, workspace: {}",
|
"reaped {} orphan window(s) and {} orphaned container(s) on monitor: {}, workspace: {}",
|
||||||
reaped_orphans.0,
|
reaped_orphans.0,
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ pub struct WindowManager {
|
|||||||
pub command_listener: UnixListener,
|
pub command_listener: UnixListener,
|
||||||
pub is_paused: bool,
|
pub is_paused: bool,
|
||||||
pub invisible_borders: Rect,
|
pub invisible_borders: Rect,
|
||||||
|
pub work_area_offset: Option<Rect>,
|
||||||
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
||||||
pub hotwatch: Hotwatch,
|
pub hotwatch: Hotwatch,
|
||||||
pub virtual_desktop_id: Option<usize>,
|
pub virtual_desktop_id: Option<usize>,
|
||||||
@@ -56,6 +57,7 @@ pub struct State {
|
|||||||
pub monitors: Ring<Monitor>,
|
pub monitors: Ring<Monitor>,
|
||||||
pub is_paused: bool,
|
pub is_paused: bool,
|
||||||
pub invisible_borders: Rect,
|
pub invisible_borders: Rect,
|
||||||
|
pub work_area_offset: Option<Rect>,
|
||||||
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
|
||||||
pub has_pending_raise_op: bool,
|
pub has_pending_raise_op: bool,
|
||||||
pub float_identifiers: Vec<String>,
|
pub float_identifiers: Vec<String>,
|
||||||
@@ -72,6 +74,7 @@ impl From<&mut WindowManager> for State {
|
|||||||
monitors: wm.monitors.clone(),
|
monitors: wm.monitors.clone(),
|
||||||
is_paused: wm.is_paused,
|
is_paused: wm.is_paused,
|
||||||
invisible_borders: wm.invisible_borders,
|
invisible_borders: wm.invisible_borders,
|
||||||
|
work_area_offset: wm.work_area_offset,
|
||||||
focus_follows_mouse: wm.focus_follows_mouse.clone(),
|
focus_follows_mouse: wm.focus_follows_mouse.clone(),
|
||||||
has_pending_raise_op: wm.has_pending_raise_op,
|
has_pending_raise_op: wm.has_pending_raise_op,
|
||||||
float_identifiers: FLOAT_IDENTIFIERS.lock().clone(),
|
float_identifiers: FLOAT_IDENTIFIERS.lock().clone(),
|
||||||
@@ -143,6 +146,7 @@ impl WindowManager {
|
|||||||
right: 14,
|
right: 14,
|
||||||
bottom: 7,
|
bottom: 7,
|
||||||
},
|
},
|
||||||
|
work_area_offset: None,
|
||||||
focus_follows_mouse: None,
|
focus_follows_mouse: None,
|
||||||
hotwatch: Hotwatch::new()?,
|
hotwatch: Hotwatch::new()?,
|
||||||
virtual_desktop_id,
|
virtual_desktop_id,
|
||||||
@@ -265,6 +269,7 @@ impl WindowManager {
|
|||||||
self.monitors_mut().retain(|m| !invalid.contains(&m.id()));
|
self.monitors_mut().retain(|m| !invalid.contains(&m.id()));
|
||||||
|
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
|
|
||||||
for monitor in self.monitors_mut() {
|
for monitor in self.monitors_mut() {
|
||||||
let mut should_update = false;
|
let mut should_update = false;
|
||||||
@@ -293,7 +298,7 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if should_update {
|
if should_update {
|
||||||
monitor.update_focused_workspace(&invisible_borders)?;
|
monitor.update_focused_workspace(offset, &invisible_borders)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,6 +428,8 @@ impl WindowManager {
|
|||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn retile_all(&mut self) -> Result<()> {
|
pub fn retile_all(&mut self) -> Result<()> {
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
|
|
||||||
for monitor in self.monitors_mut() {
|
for monitor in self.monitors_mut() {
|
||||||
let work_area = *monitor.work_area_size();
|
let work_area = *monitor.work_area_size();
|
||||||
let workspace = monitor
|
let workspace = monitor
|
||||||
@@ -434,7 +441,7 @@ impl WindowManager {
|
|||||||
*resize = None;
|
*resize = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
workspace.update(&work_area, &invisible_borders)?;
|
workspace.update(&work_area, offset, &invisible_borders)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -534,10 +541,11 @@ impl WindowManager {
|
|||||||
tracing::info!("updating");
|
tracing::info!("updating");
|
||||||
|
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
|
|
||||||
self.focused_monitor_mut()
|
self.focused_monitor_mut()
|
||||||
.ok_or_else(|| anyhow!("there is no monitor"))?
|
.ok_or_else(|| anyhow!("there is no monitor"))?
|
||||||
.update_focused_workspace(&invisible_borders)?;
|
.update_focused_workspace(offset, &invisible_borders)?;
|
||||||
|
|
||||||
if mouse_follows_focus {
|
if mouse_follows_focus {
|
||||||
if let Some(window) = self.focused_workspace()?.maximized_window() {
|
if let Some(window) = self.focused_workspace()?.maximized_window() {
|
||||||
@@ -660,6 +668,7 @@ impl WindowManager {
|
|||||||
tracing::info!("moving container");
|
tracing::info!("moving container");
|
||||||
|
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
|
|
||||||
let monitor = self
|
let monitor = self
|
||||||
.focused_monitor_mut()
|
.focused_monitor_mut()
|
||||||
@@ -685,7 +694,7 @@ impl WindowManager {
|
|||||||
|
|
||||||
target_monitor.add_container(container)?;
|
target_monitor.add_container(container)?;
|
||||||
target_monitor.load_focused_workspace()?;
|
target_monitor.load_focused_workspace()?;
|
||||||
target_monitor.update_focused_workspace(&invisible_borders)?;
|
target_monitor.update_focused_workspace(offset, &invisible_borders)?;
|
||||||
|
|
||||||
if follow {
|
if follow {
|
||||||
self.focus_monitor(idx)?;
|
self.focus_monitor(idx)?;
|
||||||
@@ -1075,6 +1084,7 @@ impl WindowManager {
|
|||||||
tracing::info!("setting workspace layout");
|
tracing::info!("setting workspace layout");
|
||||||
|
|
||||||
let invisible_borders = self.invisible_borders;
|
let invisible_borders = self.invisible_borders;
|
||||||
|
let offset = self.work_area_offset;
|
||||||
let focused_monitor_idx = self.focused_monitor_idx();
|
let focused_monitor_idx = self.focused_monitor_idx();
|
||||||
|
|
||||||
let monitor = self
|
let monitor = self
|
||||||
@@ -1094,7 +1104,7 @@ impl WindowManager {
|
|||||||
|
|
||||||
// If this is the focused workspace on a non-focused screen, let's update it
|
// 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 {
|
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
|
||||||
workspace.update(&work_area, &invisible_borders)?;
|
workspace.update(&work_area, offset, &invisible_borders)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Ok(self.update_focused_workspace(false)?)
|
Ok(self.update_focused_workspace(false)?)
|
||||||
|
|||||||
@@ -138,8 +138,25 @@ impl Workspace {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, work_area: &Rect, invisible_borders: &Rect) -> Result<()> {
|
pub fn update(
|
||||||
let mut adjusted_work_area = *work_area;
|
&mut self,
|
||||||
|
work_area: &Rect,
|
||||||
|
offset: Option<Rect>,
|
||||||
|
invisible_borders: &Rect,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut adjusted_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());
|
adjusted_work_area.add_padding(self.workspace_padding());
|
||||||
|
|
||||||
self.enforce_resize_constraints();
|
self.enforce_resize_constraints();
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ InvisibleBorders(left, top, right, bottom) {
|
|||||||
Run, komorebic.exe invisible-borders %left% %top% %right% %bottom%, , Hide
|
Run, komorebic.exe invisible-borders %left% %top% %right% %bottom%, , Hide
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorkAreaOffset(left, top, right, bottom) {
|
||||||
|
Run, komorebic.exe work-area-offset %left% %top% %right% %bottom%, , Hide
|
||||||
|
}
|
||||||
|
|
||||||
AdjustContainerPadding(sizing, adjustment) {
|
AdjustContainerPadding(sizing, adjustment) {
|
||||||
Run, komorebic.exe adjust-container-padding %sizing% %adjustment%, , Hide
|
Run, komorebic.exe adjust-container-padding %sizing% %adjustment%, , Hide
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,6 +167,18 @@ struct InvisibleBorders {
|
|||||||
bottom: i32,
|
bottom: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clap, AhkFunction)]
|
||||||
|
struct WorkAreaOffset {
|
||||||
|
/// Size of the left work area offset (set right to left * 2 to maintain right padding)
|
||||||
|
left: i32,
|
||||||
|
/// Size of the top work area offset (set bottom to the same value to maintain bottom padding)
|
||||||
|
top: i32,
|
||||||
|
/// Size of the right work area offset
|
||||||
|
right: i32,
|
||||||
|
/// Size of the bottom work area offset
|
||||||
|
bottom: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clap, AhkFunction)]
|
#[derive(Clap, AhkFunction)]
|
||||||
struct EnsureWorkspaces {
|
struct EnsureWorkspaces {
|
||||||
/// Monitor index (zero-indexed)
|
/// Monitor index (zero-indexed)
|
||||||
@@ -366,6 +378,9 @@ enum SubCommand {
|
|||||||
/// Set the invisible border dimensions around each window
|
/// Set the invisible border dimensions around each window
|
||||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
InvisibleBorders(InvisibleBorders),
|
InvisibleBorders(InvisibleBorders),
|
||||||
|
/// Set offsets to exclude parts of the work area from tiling
|
||||||
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
|
WorkAreaOffset(WorkAreaOffset),
|
||||||
/// Adjust container padding on the focused workspace
|
/// Adjust container padding on the focused workspace
|
||||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||||
AdjustContainerPadding(AdjustContainerPadding),
|
AdjustContainerPadding(AdjustContainerPadding),
|
||||||
@@ -538,6 +553,17 @@ fn main() -> Result<()> {
|
|||||||
.as_bytes()?,
|
.as_bytes()?,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
SubCommand::WorkAreaOffset(arg) => {
|
||||||
|
send_message(
|
||||||
|
&*SocketMessage::WorkAreaOffset(Rect {
|
||||||
|
left: arg.left,
|
||||||
|
top: arg.top,
|
||||||
|
right: arg.right,
|
||||||
|
bottom: arg.bottom,
|
||||||
|
})
|
||||||
|
.as_bytes()?,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
SubCommand::ContainerPadding(arg) => {
|
SubCommand::ContainerPadding(arg) => {
|
||||||
send_message(
|
send_message(
|
||||||
&*SocketMessage::ContainerPadding(arg.monitor, arg.workspace, arg.size)
|
&*SocketMessage::ContainerPadding(arg.monitor, arg.workspace, arg.size)
|
||||||
|
|||||||
Reference in New Issue
Block a user