mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-05-17 01:07:02 +02:00
feat(wm): run orphan reaper in a dedicated thread
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: https://github.com/microsoft/terminal/issues/17298
This commit is contained in:
@@ -9,6 +9,7 @@ pub mod monitor_reconciliator;
|
|||||||
pub mod process_command;
|
pub mod process_command;
|
||||||
pub mod process_event;
|
pub mod process_event;
|
||||||
pub mod process_movement;
|
pub mod process_movement;
|
||||||
|
pub mod reaper;
|
||||||
pub mod set_window_position;
|
pub mod set_window_position;
|
||||||
pub mod stackbar_manager;
|
pub mod stackbar_manager;
|
||||||
pub mod static_config;
|
pub mod static_config;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ use komorebi::process_command::listen_for_commands;
|
|||||||
use komorebi::process_command::listen_for_commands_tcp;
|
use komorebi::process_command::listen_for_commands_tcp;
|
||||||
use komorebi::process_event::listen_for_events;
|
use komorebi::process_event::listen_for_events;
|
||||||
use komorebi::process_movement::listen_for_movements;
|
use komorebi::process_movement::listen_for_movements;
|
||||||
|
use komorebi::reaper;
|
||||||
use komorebi::stackbar_manager;
|
use komorebi::stackbar_manager;
|
||||||
use komorebi::static_config::StaticConfig;
|
use komorebi::static_config::StaticConfig;
|
||||||
use komorebi::window_manager::WindowManager;
|
use komorebi::window_manager::WindowManager;
|
||||||
@@ -258,6 +259,7 @@ fn main() -> Result<()> {
|
|||||||
stackbar_manager::listen_for_notifications(wm.clone());
|
stackbar_manager::listen_for_notifications(wm.clone());
|
||||||
workspace_reconciliator::listen_for_notifications(wm.clone());
|
workspace_reconciliator::listen_for_notifications(wm.clone());
|
||||||
monitor_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);
|
let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1);
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use crate::window::RuleDebug;
|
|||||||
use crate::window_manager::WindowManager;
|
use crate::window_manager::WindowManager;
|
||||||
use crate::window_manager_event::WindowManagerEvent;
|
use crate::window_manager_event::WindowManagerEvent;
|
||||||
use crate::windows_api::WindowsApi;
|
use crate::windows_api::WindowsApi;
|
||||||
|
use crate::winevent::WinEvent;
|
||||||
use crate::workspace_reconciliator;
|
use crate::workspace_reconciliator;
|
||||||
use crate::workspace_reconciliator::ALT_TAB_HWND;
|
use crate::workspace_reconciliator::ALT_TAB_HWND;
|
||||||
use crate::workspace_reconciliator::ALT_TAB_HWND_INSTANT;
|
use crate::workspace_reconciliator::ALT_TAB_HWND_INSTANT;
|
||||||
@@ -120,37 +121,11 @@ impl WindowManager {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = self.work_area_offset;
|
for monitor in self.monitors_mut() {
|
||||||
|
for workspace in monitor.workspaces_mut() {
|
||||||
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() {
|
|
||||||
if let WindowManagerEvent::FocusChange(_, window) = event {
|
if let WindowManagerEvent::FocusChange(_, window) = event {
|
||||||
let _ = workspace.focus_changed(window.hwnd);
|
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +612,16 @@ impl WindowManager {
|
|||||||
border_manager::event_tx().send(border_manager::Notification)?;
|
border_manager::event_tx().send(border_manager::Notification)?;
|
||||||
stackbar_manager::event_tx().send(stackbar_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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
komorebi/src/reaper.rs
Normal file
66
komorebi/src/reaper.rs
Normal file
@@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -357,7 +357,7 @@ impl Workspace {
|
|||||||
layout.bottom -= total_height;
|
layout.bottom -= total_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.set_position(&layout, false)?;
|
window.set_position(layout, false)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user