Skip to content

Commit

Permalink
feat(wm): run orphan reaper in a dedicated thread
Browse files Browse the repository at this point in the history
Until now the orphan window/container reaper has always run on every
WinEvent. Unfortunately Windows Terminal does not sent a WinEvent when
it is closed.

This is a problem for the new border_manager module which draws and
destroys borders based on notifications sent to it after WinEvents and
SocketMessages have been processed.

Since Windows Terminal is not sending a WinEvent on close, this means
that user interaction is required to remove the ghost border that gets
left behind.

This commit starts a separate thread for the reaper where it runs once
every second in a loop.

This is quite wasteful and definitely not something I wanted to
implement, but a temporary solution is needed given the popularity of
the buggy application in question.

An issue on the Windows Terminal tracker has been opened here:
microsoft/terminal#17298
  • Loading branch information
LGUG2Z committed May 22, 2024
1 parent 69680b4 commit c4d62fc
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 30 deletions.
1 change: 1 addition & 0 deletions komorebi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod monitor_reconciliator;
pub mod process_command;
pub mod process_event;
pub mod process_movement;
pub mod reaper;
pub mod set_window_position;
pub mod stackbar_manager;
pub mod static_config;
Expand Down
2 changes: 2 additions & 0 deletions komorebi/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use komorebi::process_command::listen_for_commands;
use komorebi::process_command::listen_for_commands_tcp;
use komorebi::process_event::listen_for_events;
use komorebi::process_movement::listen_for_movements;
use komorebi::reaper;
use komorebi::stackbar_manager;
use komorebi::static_config::StaticConfig;
use komorebi::window_manager::WindowManager;
Expand Down Expand Up @@ -258,6 +259,7 @@ fn main() -> Result<()> {
stackbar_manager::listen_for_notifications(wm.clone());
workspace_reconciliator::listen_for_notifications(wm.clone());
monitor_reconciliator::listen_for_notifications(wm.clone())?;
reaper::watch_for_orphans(wm.clone());

let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1);
ctrlc::set_handler(move || {
Expand Down
42 changes: 13 additions & 29 deletions komorebi/src/process_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::window::RuleDebug;
use crate::window_manager::WindowManager;
use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi;
use crate::winevent::WinEvent;
use crate::workspace_reconciliator;
use crate::workspace_reconciliator::ALT_TAB_HWND;
use crate::workspace_reconciliator::ALT_TAB_HWND_INSTANT;
Expand Down Expand Up @@ -120,37 +121,11 @@ impl WindowManager {
_ => {}
}

let offset = self.work_area_offset;

for (i, monitor) in self.monitors_mut().iter_mut().enumerate() {
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);

let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};

for (j, workspace) in monitor.workspaces_mut().iter_mut().enumerate() {
for monitor in self.monitors_mut() {
for workspace in monitor.workspaces_mut() {
if let WindowManagerEvent::FocusChange(_, window) = event {
let _ = workspace.focus_changed(window.hwnd);
}

let reaped_orphans = workspace.reap_orphans()?;
if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 {
workspace.update(&work_area, offset, window_based_work_area_offset)?;
tracing::info!(
"reaped {} orphan window(s) and {} orphaned container(s) on monitor: {}, workspace: {}",
reaped_orphans.0,
reaped_orphans.1,
i,
j
);
}
}
}

Expand Down Expand Up @@ -637,7 +612,16 @@ impl WindowManager {
border_manager::event_tx().send(border_manager::Notification)?;
stackbar_manager::event_tx().send(stackbar_manager::Notification)?;

tracing::info!("processed: {}", event.window().to_string());
// Too many spammy OBJECT_NAMECHANGE events from JetBrains IDEs
if !matches!(
event,
WindowManagerEvent::Show(WinEvent::ObjectNameChange, _)
) {
tracing::info!("processed: {}", event.window().to_string());
} else {
tracing::trace!("processed: {}", event.window().to_string());
}

Ok(())
}
}
66 changes: 66 additions & 0 deletions komorebi/src/reaper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![deny(clippy::unwrap_used, clippy::expect_used)]

use crate::border_manager;
use crate::WindowManager;
use parking_lot::Mutex;
use std::sync::Arc;
use std::time::Duration;

pub fn watch_for_orphans(wm: Arc<Mutex<WindowManager>>) {
std::thread::spawn(move || loop {
match find_orphans(wm.clone()) {
Ok(()) => {
tracing::warn!("restarting finished thread");
}
Err(error) => {
if cfg!(debug_assertions) {
tracing::error!("restarting failed thread: {:?}", error)
} else {
tracing::error!("restarting failed thread: {}", error)
}
}
}
});
}

pub fn find_orphans(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()> {
tracing::info!("watching");

let arc = wm.clone();

loop {
std::thread::sleep(Duration::from_secs(1));

let mut wm = arc.lock();
let offset = wm.work_area_offset;

for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);

let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};

for (j, workspace) in monitor.workspaces_mut().iter_mut().enumerate() {
let reaped_orphans = workspace.reap_orphans()?;
if reaped_orphans.0 > 0 || reaped_orphans.1 > 0 {
workspace.update(&work_area, offset, window_based_work_area_offset)?;
border_manager::event_tx().send(border_manager::Notification)?;
tracing::info!(
"reaped {} orphan window(s) and {} orphaned container(s) on monitor: {}, workspace: {}",
reaped_orphans.0,
reaped_orphans.1,
i,
j
);
}
}
}
}
}
2 changes: 1 addition & 1 deletion komorebi/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ impl Workspace {
layout.bottom -= total_height;
}

window.set_position(&layout, false)?;
window.set_position(layout, false)?;
}
}

Expand Down

0 comments on commit c4d62fc

Please sign in to comment.