fix(wm): don't reap ws windows when using hide instead of cloak

This commit ensures that workspace windows that are hidden when the user
is using HidingBehaviour::Hide will not be unintentionally reaped by a
hard-coded workaround for Microsoft Office's continuing
enshittification.

HidingBehaviour::Hide has also been marked in the docs as an EOL
feature, and some dead code that was ultimately migrated to reaper.rs
has been cleaned up.

fix #1426
This commit is contained in:
LGUG2Z
2025-05-02 17:29:14 -07:00
parent c28773b96a
commit 82c2241601
3 changed files with 16 additions and 86 deletions

View File

@@ -486,7 +486,7 @@ pub enum CrossBoundaryBehaviour {
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, PartialEq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum HidingBehaviour {
/// Use the SW_HIDE flag to hide windows when switching workspaces (has issues with Electron apps)
/// END OF LIFE FEATURE: Use the SW_HIDE flag to hide windows when switching workspaces (has issues with Electron apps)
Hide,
/// Use the SW_MINIMIZE flag to hide windows when switching workspaces (has issues with frequent workspace switching)
Minimize,

View File

@@ -3,11 +3,13 @@
use crate::border_manager;
use crate::notify_subscribers;
use crate::winevent::WinEvent;
use crate::HidingBehaviour;
use crate::NotificationEvent;
use crate::Window;
use crate::WindowManager;
use crate::WindowManagerEvent;
use crate::DATA_DIR;
use crate::HIDING_BEHAVIOUR;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
@@ -169,6 +171,7 @@ fn find_orphans() -> color_eyre::Result<()> {
loop {
std::thread::sleep(Duration::from_millis(20));
let hiding_behaviour = *HIDING_BEHAVIOUR.lock();
let mut cache = HWNDS_CACHE.lock();
let mut orphan_hwnds = HashMap::new();
@@ -177,13 +180,18 @@ fn find_orphans() -> color_eyre::Result<()> {
let window = Window::from(*hwnd);
if !window.is_window()
// This one is a hack because WINWORD.EXE is an absolute trainwreck of an app
// when multiple docs are open, it keeps open an invisible window, with WS_EX_LAYERED
// (A STYLE THAT THE REGULAR WINDOWS NEED IN ORDER TO BE MANAGED!) when one of the
// docs is closed
//
// I hate every single person who worked on Microsoft Office 365, especially Word
|| !window.is_visible()
|| (
// This one is a hack because WINWORD.EXE is an absolute trainwreck of an app
// when multiple docs are open, it keeps open an invisible window, with WS_EX_LAYERED
// (A STYLE THAT THE REGULAR WINDOWS NEED IN ORDER TO BE MANAGED!) when one of the
// docs is closed
//
// I hate every single person who worked on Microsoft Office 365, especially Word
!window.is_visible()
// We cannot execute this lovely hack if the user is using HidingBehaviour::Hide because
// it will result in legitimate hidden, non-visible windows being yeeted from the state
&& !matches!(hiding_behaviour, HidingBehaviour::Hide)
)
{
orphan_hwnds.insert(window.hwnd, (*m_idx, *w_idx));
}

View File

@@ -660,84 +660,6 @@ impl Workspace {
Ok(())
}
pub fn reap_orphans(&mut self) -> Result<(usize, usize)> {
let mut hwnds = vec![];
let mut floating_hwnds = vec![];
let mut remove_monocle = false;
let mut remove_maximized = false;
if let Some(monocle) = &self.monocle_container {
let window_count = monocle.windows().len();
let mut orphan_count = 0;
for window in monocle.windows() {
if !window.is_window() {
hwnds.push(window.hwnd);
orphan_count += 1;
}
}
remove_monocle = orphan_count == window_count;
}
if let Some(window) = &self.maximized_window {
if !window.is_window() {
hwnds.push(window.hwnd);
remove_maximized = true;
}
}
for window in self.visible_windows().into_iter().flatten() {
if !window.is_window()
// This one is a hack because WINWORD.EXE is an absolute trainwreck of an app
// when multiple docs are open, it keeps open an invisible window, with WS_EX_LAYERED
// (A STYLE THAT THE REGULAR WINDOWS NEED IN ORDER TO BE MANAGED!) when one of the
// docs is closed
//
// I hate every single person who worked on Microsoft Office 365, especially Word
|| !window.is_visible()
{
hwnds.push(window.hwnd);
}
}
for window in self.floating_windows() {
if !window.is_window() {
floating_hwnds.push(window.hwnd);
}
}
for hwnd in &hwnds {
tracing::debug!("reaping hwnd: {}", hwnd);
self.remove_window(*hwnd)?;
}
for hwnd in &floating_hwnds {
tracing::debug!("reaping floating hwnd: {}", hwnd);
self.floating_windows_mut()
.retain(|w| !floating_hwnds.contains(&w.hwnd));
}
let mut container_ids = vec![];
for container in self.containers() {
if container.windows().is_empty() {
container_ids.push(container.id().clone());
}
}
self.containers_mut()
.retain(|c| !container_ids.contains(c.id()));
if remove_monocle {
self.set_monocle_container(None);
}
if remove_maximized {
self.set_maximized_window(None);
}
Ok((hwnds.len() + floating_hwnds.len(), container_ids.len()))
}
pub fn container_for_window(&self, hwnd: isize) -> Option<&Container> {
self.containers().get(self.container_idx_for_window(hwnd)?)
}