From 8642ac0946c438333823cce4d487ead75de488a4 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Sat, 24 Feb 2024 19:19:44 -0800 Subject: [PATCH] fix(wm): improve maximized window handling This commit addresses a few bugs with regards to maximized window handling. - Correctly restoring and focusing when switching to a workspace containing a window previously maximized with the toggle-maximize command - Unmaximizing a window during the initial window scan when the wm initializes so that windows that are maximized before running komorebi will no longer have the ugly white bar at the top - When updating workspace layouts, windows that have been maximized without using the komorebic toggle-maximize command will be unmaximized to prevent the wm state drifting out of sync with what is happening on the screen --- komorebi/src/window.rs | 8 ++++++++ komorebi/src/window_manager.rs | 9 +++++++++ komorebi/src/windows_api.rs | 5 +++++ komorebi/src/windows_callbacks.rs | 5 +++++ komorebi/src/workspace.rs | 8 ++++++++ 5 files changed, 35 insertions(+) diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index 7b2f0b03..cb00f79f 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -179,6 +179,14 @@ impl Window { WindowsApi::position_window(self.hwnd(), &rect, top) } + pub fn is_maximized(self) -> bool { + WindowsApi::is_zoomed(self.hwnd()) + } + + pub fn is_miminized(self) -> bool { + WindowsApi::is_iconic(self.hwnd()) + } + pub fn hide(self) { let mut programmatically_hidden_hwnds = HIDDEN_HWNDS.lock(); if !programmatically_hidden_hwnds.contains(&self.hwnd) { diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 952a291e..8041b8f9 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -880,6 +880,15 @@ impl WindowManager { } }; + // This is to correctly restore and focus when switching to a workspace which + // contains a managed maximized window + if !follow_focus { + if let Some(window) = self.focused_workspace()?.maximized_window() { + window.restore(); + window.focus(self.mouse_follows_focus)?; + } + } + Ok(()) } diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index a2ba0246..114be56a 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -82,6 +82,7 @@ use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId; use windows::Win32::UI::WindowsAndMessaging::IsIconic; use windows::Win32::UI::WindowsAndMessaging::IsWindow; use windows::Win32::UI::WindowsAndMessaging::IsWindowVisible; +use windows::Win32::UI::WindowsAndMessaging::IsZoomed; use windows::Win32::UI::WindowsAndMessaging::PostMessageW; use windows::Win32::UI::WindowsAndMessaging::RealGetWindowClassW; use windows::Win32::UI::WindowsAndMessaging::RegisterClassW; @@ -677,6 +678,10 @@ impl WindowsApi { unsafe { IsIconic(hwnd) }.into() } + pub fn is_zoomed(hwnd: HWND) -> bool { + unsafe { IsZoomed(hwnd) }.into() + } + pub fn monitor_info_w(hmonitor: HMONITOR) -> Result { let mut ex_info = MONITORINFOEXW::default(); ex_info.monitorInfo.cbSize = u32::try_from(std::mem::size_of::())?; diff --git a/komorebi/src/windows_callbacks.rs b/komorebi/src/windows_callbacks.rs index ca16041e..3fc734be 100644 --- a/komorebi/src/windows_callbacks.rs +++ b/komorebi/src/windows_callbacks.rs @@ -146,12 +146,17 @@ pub extern "system" fn enum_window(hwnd: HWND, lparam: LPARAM) -> BOOL { let is_visible = WindowsApi::is_window_visible(hwnd); let is_window = WindowsApi::is_window(hwnd); let is_minimized = WindowsApi::is_iconic(hwnd); + let is_maximized = WindowsApi::is_zoomed(hwnd); if is_visible && is_window && !is_minimized { let window = Window { hwnd: hwnd.0 }; if let Ok(should_manage) = window.should_manage(None) { if should_manage { + if is_maximized { + WindowsApi::restore_window(hwnd); + } + let mut container = Container::default(); container.windows_mut().push_back(window); containers.push_back(container); diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index c6fdfdf9..a08c22a7 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -247,6 +247,8 @@ impl Workspace { } } + let managed_maximized_window = self.maximized_window().is_some(); + if *self.tile() { if let Some(container) = self.monocle_container_mut() { if let Some(window) = container.focused_window_mut() { @@ -280,6 +282,12 @@ impl Workspace { window.add_title_bar()?; } + // If a window has been unmaximized via toggle-maximize, this block + // will make sure that it is unmaximized via restore_window + if window.is_maximized() && !managed_maximized_window { + WindowsApi::restore_window(window.hwnd()); + } + window.set_position(layout, invisible_borders, false)?; } }