From e04ba0e033c4515095d1290019b21bec7a644204 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Fri, 1 Dec 2023 10:19:10 -0800 Subject: [PATCH] feat(win32): set foregroundlocktimeout explicitly After another round of deep diving to find a workaround to all of the mechanisms within Windows that prevent a process from changing the focused window, I came across this gist which I saw setting SPI_SETFOREGROUNDLOCKTIMEOUT to 0: https://gist.github.com/EBNull/1419093 This tentatively seems like it works and it removes the need for the alt_focus_hack setting. However, according to this StackOverflow discussion, it seems like on Win10+ changes to ForegroundLockTimeout in the registry are no longer respected and changes made via SPI_SETFOREGROUNDLOCKTIMEOUT are not persisted: https://stackoverflow.com/questions/73735129/setforegroundwindow-relationship-between-the-foregroundlocktimeout-registry-val Therefore on starting, komorebi will now check the value with SPI_GETFOREGROUNDLOCKTIMEOUT and if it is not 0, it will be set to 0. Logging has been added to inform the user of the changes that are happening. --- komorebi/src/main.rs | 2 ++ komorebi/src/windows_api.rs | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/komorebi/src/main.rs b/komorebi/src/main.rs index f328792ab..c67a3456f 100644 --- a/komorebi/src/main.rs +++ b/komorebi/src/main.rs @@ -496,6 +496,8 @@ fn main() -> Result<()> { // File logging worker guard has to have an assignment in the main fn to work let (_guard, _color_guard) = setup()?; + WindowsApi::foreground_lock_timeout()?; + #[cfg(feature = "deadlock_detection")] detect_deadlocks(); diff --git a/komorebi/src/windows_api.rs b/komorebi/src/windows_api.rs index 4ac889d68..57528456b 100644 --- a/komorebi/src/windows_api.rs +++ b/komorebi/src/windows_api.rs @@ -105,7 +105,9 @@ use windows::Win32::UI::WindowsAndMessaging::SET_WINDOW_POS_FLAGS; use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD; use windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE; use windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING; +use windows::Win32::UI::WindowsAndMessaging::SPI_GETFOREGROUNDLOCKTIMEOUT; use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING; +use windows::Win32::UI::WindowsAndMessaging::SPI_SETFOREGROUNDLOCKTIMEOUT; use windows::Win32::UI::WindowsAndMessaging::SW_HIDE; use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE; use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE; @@ -679,6 +681,42 @@ impl WindowsApi { .process() } + #[tracing::instrument] + pub fn foreground_lock_timeout() -> Result<()> { + let mut value: u32 = 0; + + Self::system_parameters_info_w( + SPI_GETFOREGROUNDLOCKTIMEOUT, + 0, + std::ptr::addr_of_mut!(value).cast(), + SPIF_SENDCHANGE, + )?; + + tracing::info!("current value of ForegroundLockTimeout is {value}"); + + if value != 0 { + tracing::info!("updating value of ForegroundLockTimeout to {value} in order to enable keyboard-driven focus updating"); + + Self::system_parameters_info_w( + SPI_SETFOREGROUNDLOCKTIMEOUT, + 0, + 0 as *mut c_void, + SPIF_SENDCHANGE, + )?; + + Self::system_parameters_info_w( + SPI_GETFOREGROUNDLOCKTIMEOUT, + 0, + std::ptr::addr_of_mut!(value).cast(), + SPIF_SENDCHANGE, + )?; + + tracing::info!("updated value of ForegroundLockTimeout is now {value}"); + } + + Ok(()) + } + #[allow(dead_code)] pub fn focus_follows_mouse() -> Result { let mut is_enabled: BOOL = unsafe { std::mem::zeroed() };