From 547c2486f7d4e5b5d720b1c91d142d2604c48ca3 Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Mon, 10 Jul 2023 17:52:16 +0200 Subject: [PATCH 1/7] Prevent restore of app window --- src/appwindow.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/appwindow.rs b/src/appwindow.rs index 9c414a8..3e7319a 100644 --- a/src/appwindow.rs +++ b/src/appwindow.rs @@ -13,7 +13,7 @@ use windows::{ CW_USEDEFAULT, EVENT_OBJECT_CLOAKED, EVENT_OBJECT_UNCLOAKED, EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MOVESIZEEND, EVENT_SYSTEM_MOVESIZESTART, GWLP_USERDATA, OBJID_WINDOW, WINDOW_EX_STYLE, WM_APP, - WM_CREATE, WM_DESTROY, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, + WM_CREATE, WM_DESTROY, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, WM_SYSCOMMAND, SC_RESTORE, }, }, }, @@ -181,6 +181,13 @@ impl AppWindow { win32::set_window_long_ptr(hwnd, GWLP_USERDATA, wm as _); LRESULT(0) } + WM_SYSCOMMAND => { + debug!("WM_SYSCOMMAND {:?}\t{}", wparam, SC_RESTORE); + if wparam.0 as u32 == SC_RESTORE { + return LRESULT(0); + } + win32::def_window_proc(hwnd, msg, wparam, lparam) + } _ => { let wm = win32::get_window_long_ptr(hwnd, GWLP_USERDATA) as *mut WindowManager; if !wm.is_null() { From 280ff68918336bf246d48f5dc867b39f6f90fd4d Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sat, 15 Jul 2023 06:40:59 +0200 Subject: [PATCH 2/7] Add application icon --- Cargo.lock | 129 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + build.rs | 2 + resources/app.ico | Bin 0 -> 361102 bytes resources/res.rc | 1 + src/appwindow.rs | 3 +- src/win32.rs | 6 ++- 7 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 resources/app.ico create mode 100644 resources/res.rc diff --git a/Cargo.lock b/Cargo.lock index 1d5fdb5..fa63a48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,18 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "copy_to_output" version = "2.1.0" @@ -18,6 +30,19 @@ dependencies = [ "fs_extra", ] +[[package]] +name = "embed-resource" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7f1e82a60222fc67bfd50d752a9c89da5cce4c39ed39decc84a443b07bbd69a" +dependencies = [ + "cc", + "rustc_version", + "toml", + "vswhom", + "winreg", +] + [[package]] name = "equivalent" version = "1.0.0" @@ -41,6 +66,7 @@ name = "grout-wm" version = "0.1.0" dependencies = [ "copy_to_output", + "embed-resource", "glob", "log", "serde", @@ -89,6 +115,12 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + [[package]] name = "proc-macro2" version = "1.0.63" @@ -113,12 +145,27 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "ryu" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.164" @@ -139,6 +186,15 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "serde_yaml" version = "0.9.22" @@ -185,6 +241,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.9" @@ -197,6 +287,26 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "winapi" version = "0.3.9" @@ -284,3 +394,22 @@ name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189" +dependencies = [ + "cfg-if", + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml index ac8e720..73db13f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ windows = { version = "0.48.0", features = ["Win32_Foundation", "Win32_Graphics_ [build-dependencies] copy_to_output = "2.1.0" +embed-resource = "2.2.0" glob = "0.3.1" diff --git a/build.rs b/build.rs index 452d10c..35f4e33 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,9 @@ use copy_to_output::copy_to_output; use std::env; +extern crate embed_resource; fn main() { + embed_resource::compile("resources/res.rc", embed_resource::NONE); copy_to_output("default.yaml", &env::var("PROFILE").unwrap()).expect("Could not copy"); copy_to_output("user.yaml", &env::var("PROFILE").unwrap()).expect("Could not copy"); } diff --git a/resources/app.ico b/resources/app.ico new file mode 100644 index 0000000000000000000000000000000000000000..0c8ce10cda83f5dfdc13e565b0772c41959bd31c GIT binary patch literal 361102 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 JEWZEz@jtZ6&_w_M literal 0 HcmV?d00001 diff --git a/resources/res.rc b/resources/res.rc new file mode 100644 index 0000000..f7beb20 --- /dev/null +++ b/resources/res.rc @@ -0,0 +1 @@ +appicon ICON "app.ico" diff --git a/src/appwindow.rs b/src/appwindow.rs index 3e7319a..e526ae2 100644 --- a/src/appwindow.rs +++ b/src/appwindow.rs @@ -22,7 +22,7 @@ use windows::{ use grout_wm::Result; use crate::{ - win32, + win32::{self, load_icon}, windowmanager::{ WindowManager, MSG_CLOAKED, MSG_MINIMIZEEND, MSG_MINIMIZESTART, MSG_MOVESIZEEND, MSG_UNCLOAKED, @@ -57,6 +57,7 @@ impl AppWindow { let windows_class = w!("grout-wm.window"); let wc = WNDCLASSW { hInstance: instance, + hIcon: load_icon(instance, w!("appicon"))?, hbrBackground: HBRUSH((COLOR_WINDOW.0 + 1) as isize), lpszClassName: windows_class, lpfnWndProc: Some(Self::wnd_proc), diff --git a/src/win32.rs b/src/win32.rs index 1fec0d0..ac49afe 100644 --- a/src/win32.rs +++ b/src/win32.rs @@ -46,7 +46,7 @@ use windows::{ HWND_TOP, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, SPI_GETWORKAREA, SWP_NOACTIVATE, SW_SHOWMINNOACTIVE, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WINDOW_LONG_PTR_INDEX, WINEVENT_OUTOFCONTEXT, - WNDCLASSW, WNDENUMPROC, + WNDCLASSW, WNDENUMPROC, HICON, LoadIconW, }, }, }, @@ -336,6 +336,10 @@ pub fn point_in_rect(lprc: RECT, pt: POINT) -> bool { unsafe { PtInRect(&lprc, pt).into() } } +pub fn load_icon(hinstance: HMODULE, lpiconname: PCWSTR) -> windows::core::Result{ + unsafe { LoadIconW(hinstance, lpiconname) } +} + // ===== // Virtual desktop // ===== From 9cf467c14a171117a50f6792982cee5e99c49cf6 Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sat, 15 Jul 2023 08:38:55 +0200 Subject: [PATCH 3/7] Refactor appwindow --- src/appwindow.rs | 186 +++++++++++++++++++++++-------------------- src/main.rs | 6 +- src/windowmanager.rs | 16 ++-- 3 files changed, 113 insertions(+), 95 deletions(-) diff --git a/src/appwindow.rs b/src/appwindow.rs index e526ae2..dd9c9ef 100644 --- a/src/appwindow.rs +++ b/src/appwindow.rs @@ -22,10 +22,10 @@ use windows::{ use grout_wm::Result; use crate::{ - win32::{self, load_icon}, + win32::{self, load_icon, get_module_handle, register_class, show_window, register_shell_hook_window, register_window_messagew, set_win_event_hook, def_window_proc, set_window_long_ptr, post_quit_message, get_window_long_ptr}, windowmanager::{ WindowManager, MSG_CLOAKED, MSG_MINIMIZEEND, MSG_MINIMIZESTART, MSG_MOVESIZEEND, - MSG_UNCLOAKED, + MSG_UNCLOAKED, SHELL_HOOK_ID, }, }; @@ -38,8 +38,94 @@ pub struct AppWindow { movesize_event_hook: HWINEVENTHOOK, } -impl Drop for AppWindow { - fn drop(&mut self) { + +impl AppWindow { + pub fn new_window(wm: &mut WindowManager) -> Result { + let instance = get_module_handle()?; + let window_class = w!("grout-wm.window"); + let wc = WNDCLASSW { + hInstance: instance, + lpszClassName: window_class, + hIcon: load_icon(instance, w!("appicon"))?, + hbrBackground: HBRUSH((COLOR_WINDOW.0 + 1) as isize), + lpfnWndProc: Some(Self::wnd_proc), + ..Default::default() + }; + if register_class(&wc) == 0 { + error!("Could not register class"); + return Err("Could not register class".into()); + } + let hwnd = unsafe { + CreateWindowExW( + WINDOW_EX_STYLE::default(), + window_class, + w!("grout-wm"), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + None, + None, + instance, + Some(wm as *mut _ as *mut c_void) + ) + }; + if hwnd.0 == 0 { + error!("Could not create window"); + return Err("Could not create window".into()); + } + let _ = MY_HWND.set(hwnd); + Ok(Self { + hwnd, + cloaked_event_hook: Default::default (), + minimized_event_hook: Default::default(), + movesize_event_hook: Default::default(), + }) + } + + pub fn show_window(self) -> Result { + show_window(self.hwnd); + Ok(Self { + hwnd: self.hwnd, + cloaked_event_hook: self.cloaked_event_hook, + minimized_event_hook: self.minimized_event_hook, + movesize_event_hook: self.movesize_event_hook, + }) + } + + pub fn register_hooks(self) -> Result { + let shell_hook_res = register_shell_hook_window(self.hwnd); + if !shell_hook_res { + error!("Could not register shell hook window"); + return Err("Could not register shell hook window".into()); + } + let shell_hook_id = register_window_messagew(w!("SHELLHOOK")); + let _ = SHELL_HOOK_ID.set(shell_hook_id); + let cloaked_event_hook = set_win_event_hook( + EVENT_OBJECT_CLOAKED, + EVENT_OBJECT_UNCLOAKED, + Some(Self::wnd_event_proc), + ); + let minimized_event_hook = set_win_event_hook( + EVENT_SYSTEM_MINIMIZESTART, + EVENT_SYSTEM_MINIMIZEEND, + Some(Self::wnd_event_proc), + ); + let movesize_event_hook = set_win_event_hook( + EVENT_SYSTEM_MOVESIZESTART, + EVENT_SYSTEM_MOVESIZEEND, + Some(Self::wnd_event_proc), + ); + Ok(Self { + hwnd: self.hwnd, + cloaked_event_hook, + minimized_event_hook, + movesize_event_hook, + }) + } + + pub fn cleanup(&self) -> Self { info!("Cleaning up handles"); unsafe { DeregisterShellHookWindow(self.hwnd); @@ -47,81 +133,11 @@ impl Drop for AppWindow { UnhookWinEvent(self.minimized_event_hook); UnhookWinEvent(self.movesize_event_hook); } - } -} - -impl AppWindow { - pub fn new(wm: &mut WindowManager) -> Result { - let instance_res = win32::get_module_handle(); - if let Ok(instance) = instance_res { - let windows_class = w!("grout-wm.window"); - let wc = WNDCLASSW { - hInstance: instance, - hIcon: load_icon(instance, w!("appicon"))?, - hbrBackground: HBRUSH((COLOR_WINDOW.0 + 1) as isize), - lpszClassName: windows_class, - lpfnWndProc: Some(Self::wnd_proc), - ..Default::default() - }; - if win32::register_class(&wc) == 0 { - error!("Could not register class"); - return Err("Could not register class".into()); - } - let hwnd = unsafe { - CreateWindowExW( - WINDOW_EX_STYLE::default(), - windows_class, - w!("grout-wm"), - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - None, - None, - instance, - Some(wm as *mut _ as *mut c_void), - ) - }; - if hwnd.0 == 0 { - error!("Could not create window"); - return Err("Could not create window".into()); - } - let _ = MY_HWND.set(hwnd); - win32::show_window(hwnd); - wm.manage(hwnd); - wm.arrange(); - let shell_hook_res = win32::register_shell_hook_window(hwnd); - if !shell_hook_res { - error!("Could not register shell hook window"); - return Err("Could not register shell hook window".into()); - } - let shell_hook_id = win32::register_window_messagew(w!("SHELLHOOK")); - wm.set_shell_hook_id(shell_hook_id); - let cloaked_event_hook = win32::set_win_event_hook( - EVENT_OBJECT_CLOAKED, - EVENT_OBJECT_UNCLOAKED, - Some(Self::wnd_event_proc), - ); - let minimized_event_hook = win32::set_win_event_hook( - EVENT_SYSTEM_MINIMIZESTART, - EVENT_SYSTEM_MINIMIZEEND, - Some(Self::wnd_event_proc), - ); - let movesize_event_hook = win32::set_win_event_hook( - EVENT_SYSTEM_MOVESIZESTART, - EVENT_SYSTEM_MOVESIZEEND, - Some(Self::wnd_event_proc), - ); - Ok(Self { - hwnd, - cloaked_event_hook, - minimized_event_hook, - movesize_event_hook, - }) - } else { - error!("Could not get instace"); - Err("Could not get instance".into()) + Self { + hwnd: self.hwnd, + cloaked_event_hook: Default::default(), + minimized_event_hook: Default::default(), + movesize_event_hook: Default::default(), } } @@ -152,7 +168,6 @@ impl AppWindow { return; } if let Some(&my_hwnd) = MY_HWND.get() { - debug!("event: {event}"); let msg = match event { EVENT_OBJECT_CLOAKED => MSG_CLOAKED, EVENT_OBJECT_UNCLOAKED => MSG_UNCLOAKED, @@ -161,7 +176,6 @@ impl AppWindow { EVENT_SYSTEM_MOVESIZEEND => MSG_MOVESIZEEND, _ => event, }; - debug!("msg: {msg}"); if msg >= WM_USER || msg < WM_APP { win32::post_message(my_hwnd, msg, WPARAM(0), LPARAM(hwnd.0)); } @@ -172,14 +186,14 @@ impl AppWindow { match msg { WM_DESTROY => { info!("Received WM_DESTROY message"); - win32::post_quit_message(0); + post_quit_message(0); LRESULT(0) } WM_CREATE => { info!("Creating application window"); let create_struct = lparam.0 as *const CREATESTRUCTA; let wm = unsafe { (*create_struct).lpCreateParams as *mut WindowManager }; - win32::set_window_long_ptr(hwnd, GWLP_USERDATA, wm as _); + set_window_long_ptr(hwnd, GWLP_USERDATA, wm as _); LRESULT(0) } WM_SYSCOMMAND => { @@ -187,14 +201,14 @@ impl AppWindow { if wparam.0 as u32 == SC_RESTORE { return LRESULT(0); } - win32::def_window_proc(hwnd, msg, wparam, lparam) + def_window_proc(hwnd, msg, wparam, lparam) } _ => { - let wm = win32::get_window_long_ptr(hwnd, GWLP_USERDATA) as *mut WindowManager; + let wm = get_window_long_ptr(hwnd, GWLP_USERDATA) as *mut WindowManager; if !wm.is_null() { return unsafe { (*wm).message_loop(hwnd, msg, wparam, lparam) }; } - win32::def_window_proc(hwnd, msg, wparam, lparam) + def_window_proc(hwnd, msg, wparam, lparam) } } } diff --git a/src/main.rs b/src/main.rs index 37d7b71..3b6f168 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,11 @@ fn main() -> Result<()> { let config = Config::load_default()?.load_or_create_user_config()?; let mut binding = WindowManager::new(config)?; let wm = binding.enum_windows()?; - let _appwindow = AppWindow::new(wm)?.handle_messages(); + let _appwindow = AppWindow::new_window(wm)? + .show_window()? + .register_hooks()? + .handle_messages()? + .cleanup(); info!("quitting"); win32::release_mutex(mutex_handle); Ok(()) diff --git a/src/windowmanager.rs b/src/windowmanager.rs index d5f5bae..a6e3b00 100644 --- a/src/windowmanager.rs +++ b/src/windowmanager.rs @@ -1,3 +1,5 @@ +use std::sync::OnceLock; + use log::{debug, error, info}; use windows::Win32::{ Foundation::{BOOL, HWND, LPARAM, LRESULT, RECT, TRUE, WPARAM}, @@ -21,10 +23,11 @@ pub const MSG_MINIMIZEEND: u32 = WM_USER + 0x0003; pub const MSG_MINIMIZESTART: u32 = WM_USER + 0x0004; pub const MSG_MOVESIZEEND: u32 = WM_USER + 0x0006; +pub static SHELL_HOOK_ID: OnceLock = OnceLock::new(); + pub struct WindowManager { managed_windows: Vec, working_area: RECT, - shell_hook_id: u32, config: Config, virtual_desktop: VirtualDesktopManager, } @@ -37,7 +40,6 @@ impl WindowManager { Ok(WindowManager { managed_windows: Default::default(), working_area, - shell_hook_id: Default::default(), config, virtual_desktop: VirtualDesktopManager::new()?, }) @@ -105,10 +107,6 @@ impl WindowManager { retval } - pub fn set_shell_hook_id(&mut self, shell_hook_id: u32) { - self.shell_hook_id = shell_hook_id; - } - fn unmanage(&mut self, hwnd: HWND) { if !any!(self.managed_windows, hwnd) { return; @@ -151,6 +149,7 @@ impl WindowManager { let handle = HWND(lparam.0); let managed_window = self.get_window(handle); let wmsg = wparam.0 as u32 & 0x7FFF; + let shell_hook_id = SHELL_HOOK_ID.get().unwrap_or(&0); match (msg, wmsg) { (MSG_CLOAKED, _) => { if managed_window.is_some() { @@ -192,14 +191,14 @@ impl WindowManager { self.arrange(); } } - (id, HSHELL_WINDOWCREATED) if id == self.shell_hook_id => { + (id, HSHELL_WINDOWCREATED) if id == *shell_hook_id => { if managed_window.is_none() && self.is_manageable(handle) { debug!("{handle:?} is created"); self.manage(handle); self.arrange(); } } - (id, HSHELL_WINDOWDESTROYED) if id == self.shell_hook_id => { + (id, HSHELL_WINDOWDESTROYED) if id == *shell_hook_id => { if managed_window.is_some() { debug!("{handle:?} is destroyed"); self.unmanage(handle); @@ -214,6 +213,7 @@ impl WindowManager { pub fn enum_windows(&mut self) -> Result<&mut Self> { let self_ptr = LPARAM(self as *mut Self as isize); if win32::enum_windows(Some(Self::scan), self_ptr) { + self.arrange(); Ok(self) } else { error!("Can not enum windows"); From 8f195894312519670b830add79a9d146a824be34 Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sat, 15 Jul 2023 09:15:37 +0200 Subject: [PATCH 4/7] Refactor win32 --- src/main.rs | 2 +- src/win32/com.rs | 24 +++++++ src/win32/dwm.rs | 49 ++++++++++++++ src/{win32.rs => win32/mod.rs} | 120 +++++---------------------------- src/win32/virtualdesktop.rs | 26 +++++++ src/windowmanager.rs | 9 ++- 6 files changed, 122 insertions(+), 108 deletions(-) create mode 100644 src/win32/com.rs create mode 100644 src/win32/dwm.rs rename src/{win32.rs => win32/mod.rs} (69%) create mode 100644 src/win32/virtualdesktop.rs diff --git a/src/main.rs b/src/main.rs index 3b6f168..2d1b53f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ fn main() -> Result<()> { #[cfg(debug_assertions)] simple_logging::log_to_stderr(LevelFilter::Debug); info!("{} {} - starting", app_name, app_version); - let _win32 = win32::Win32Com::new().unwrap_or_else(|_e| { + let _win32 = win32::com::Win32Com::new().unwrap_or_else(|_e| { error!("Can not initialize com"); std::process::exit(1); }); diff --git a/src/win32/com.rs b/src/win32/com.rs new file mode 100644 index 0000000..f364802 --- /dev/null +++ b/src/win32/com.rs @@ -0,0 +1,24 @@ +use log::info; + +pub struct Win32Com; + +impl Win32Com { + pub fn new() -> grout_wm::Result { + use windows::Win32::System::Com::CoInitialize; + info!("Initialize COM"); + unsafe { + CoInitialize(None)?; + } + Ok(Win32Com) + } +} + +impl Drop for Win32Com { + fn drop(&mut self) { + use windows::Win32::System::Com::CoUninitialize; + info!("Uninitializing COM"); + unsafe { + CoUninitialize(); + } + } +} diff --git a/src/win32/dwm.rs b/src/win32/dwm.rs new file mode 100644 index 0000000..e4db9e9 --- /dev/null +++ b/src/win32/dwm.rs @@ -0,0 +1,49 @@ +use std::ffi::c_void; +use std::mem::{size_of, zeroed}; +use windows::Win32::{ + Foundation::{HWND, RECT}, + Graphics::Dwm::{ + DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS, DWM_CLOAKED_APP, + DWM_CLOAKED_INHERITED, DWM_CLOAKED_SHELL, + }, + UI::WindowsAndMessaging::GetWindowRect, +}; + +pub fn get_window_extended_frame_bounds(hwnd: HWND) -> RECT { + let mut rect: RECT = unsafe { zeroed() }; + let mut frame: RECT = unsafe { zeroed() }; + unsafe { + GetWindowRect(hwnd, &mut rect); + let _ = DwmGetWindowAttribute( + hwnd, + DWMWA_EXTENDED_FRAME_BOUNDS, + &mut frame as *mut RECT as *mut c_void, + size_of::().try_into().unwrap(), + ); + } + RECT { + left: frame.left - rect.left, + top: frame.top - rect.top, + right: frame.right - rect.right, + bottom: frame.bottom - rect.bottom, + } +} + +pub fn is_cloaked(hwnd: HWND) -> bool { + let mut cloaked: u32 = 0; + let res = unsafe { + DwmGetWindowAttribute( + hwnd, + DWMWA_CLOAKED, + (&mut cloaked as *mut u32).cast(), + size_of::().try_into().unwrap(), + ) + }; + match res { + Ok(_) => matches!( + cloaked, + DWM_CLOAKED_APP | DWM_CLOAKED_SHELL | DWM_CLOAKED_INHERITED + ), + _ => false, + } +} diff --git a/src/win32.rs b/src/win32/mod.rs similarity index 69% rename from src/win32.rs rename to src/win32/mod.rs index ac49afe..4f91e66 100644 --- a/src/win32.rs +++ b/src/win32/mod.rs @@ -4,7 +4,7 @@ use std::{ path::PathBuf, }; -use log::{debug, info}; +use log::debug; use windows::{ core::PCWSTR, w, @@ -13,15 +13,8 @@ use windows::{ CloseHandle, GetLastError, BOOL, ERROR_ALREADY_EXISTS, FALSE, HANDLE, HMODULE, HWND, LPARAM, LRESULT, MAX_PATH, POINT, RECT, TRUE, WPARAM, }, - Graphics::{ - Dwm::{ - DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS, DWM_CLOAKED_APP, - DWM_CLOAKED_INHERITED, DWM_CLOAKED_SHELL, - }, - Gdi::PtInRect, - }, + Graphics::Gdi::PtInRect, System::{ - Com::{CoCreateInstance, CoInitialize, CoUninitialize, CLSCTX_ALL}, LibraryLoader::GetModuleHandleA, ProcessStatus::{ EnumProcessModules, GetModuleBaseNameW, GetModuleInformation, MODULEINFO, @@ -32,21 +25,18 @@ use windows::{ }, UI::{ Accessibility::{SetWinEventHook, HWINEVENTHOOK, WINEVENTPROC}, - Shell::{ - FOLDERID_LocalAppData, IVirtualDesktopManager, SHGetKnownFolderPath, - VirtualDesktopManager as VirtualDesktopManager_ID, KF_FLAG_DEFAULT, - }, + Shell::{FOLDERID_LocalAppData, SHGetKnownFolderPath, KF_FLAG_DEFAULT}, WindowsAndMessaging::{ DefWindowProcW, EnumWindows, FindWindowW, GetClassNameW, GetCursorPos, - GetSystemMetrics, GetWindow, GetWindowLongPtrW, GetWindowRect, - GetWindowTextLengthW, GetWindowTextW, GetWindowThreadProcessId, IsIconic, - IsWindowVisible, PostMessageW, PostQuitMessage, RegisterClassW, - RegisterShellHookWindow, RegisterWindowMessageW, SetWindowLongPtrW, SetWindowPos, - ShowWindow, SystemParametersInfoW, GET_WINDOW_CMD, GWL_EXSTYLE, GWL_STYLE, - HWND_TOP, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, - SM_YVIRTUALSCREEN, SPI_GETWORKAREA, SWP_NOACTIVATE, SW_SHOWMINNOACTIVE, + GetSystemMetrics, GetWindow, GetWindowLongPtrW, GetWindowTextLengthW, + GetWindowTextW, GetWindowThreadProcessId, IsIconic, IsWindowVisible, LoadIconW, + PostMessageW, PostQuitMessage, RegisterClassW, RegisterShellHookWindow, + RegisterWindowMessageW, SetWindowLongPtrW, SetWindowPos, ShowWindow, + SystemParametersInfoW, GET_WINDOW_CMD, GWL_EXSTYLE, GWL_STYLE, HICON, HWND_TOP, + SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, + SPI_GETWORKAREA, SWP_NOACTIVATE, SW_SHOWMINNOACTIVE, SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS, WINDOW_LONG_PTR_INDEX, WINEVENT_OUTOFCONTEXT, - WNDCLASSW, WNDENUMPROC, HICON, LoadIconW, + WNDCLASSW, WNDENUMPROC, }, }, }, @@ -54,44 +44,9 @@ use windows::{ use grout_wm::Result; -pub struct Win32Com; - -impl Win32Com { - pub fn new() -> Result { - info!("Initialize COM"); - unsafe { - CoInitialize(None)?; - } - Ok(Win32Com) - } -} - -impl Drop for Win32Com { - fn drop(&mut self) { - info!("Uninitializing COM"); - unsafe { - CoUninitialize(); - } - } -} -pub fn is_cloaked(hwnd: HWND) -> bool { - let mut cloaked: u32 = 0; - let res = unsafe { - DwmGetWindowAttribute( - hwnd, - DWMWA_CLOAKED, - (&mut cloaked as *mut u32).cast(), - size_of::().try_into().unwrap(), - ) - }; - match res { - Ok(_) => matches!( - cloaked, - DWM_CLOAKED_APP | DWM_CLOAKED_SHELL | DWM_CLOAKED_INHERITED - ), - _ => false, - } -} +pub(crate) mod com; +pub(crate) mod dwm; +pub(crate) mod virtualdesktop; pub fn is_iconic(hwnd: HWND) -> bool { unsafe { IsIconic(hwnd).into() } @@ -145,7 +100,7 @@ pub fn get_working_area() -> Result { } pub fn set_window_pos(hwnd: HWND, r: RECT) { - let margin = get_window_extended_frame_bounds(hwnd); // should be: { left: 7, top: 0, right:-7, bottom -7 } + let margin = dwm::get_window_extended_frame_bounds(hwnd); // should be: { left: 7, top: 0, right:-7, bottom -7 } debug!("{margin:?}"); unsafe { SetWindowPos( @@ -304,26 +259,6 @@ pub fn get_local_appdata_path() -> Result { Ok(path) } -pub fn get_window_extended_frame_bounds(hwnd: HWND) -> RECT { - let mut rect: RECT = unsafe { zeroed() }; - let mut frame: RECT = unsafe { zeroed() }; - unsafe { - GetWindowRect(hwnd, &mut rect); - let _ = DwmGetWindowAttribute( - hwnd, - DWMWA_EXTENDED_FRAME_BOUNDS, - &mut frame as *mut RECT as *mut c_void, - size_of::().try_into().unwrap(), - ); - } - RECT { - left: frame.left - rect.left, - top: frame.top - rect.top, - right: frame.right - rect.right, - bottom: frame.bottom - rect.bottom, - } -} - pub fn get_cursor_pos() -> POINT { let mut p: POINT = unsafe { zeroed() }; unsafe { @@ -336,29 +271,6 @@ pub fn point_in_rect(lprc: RECT, pt: POINT) -> bool { unsafe { PtInRect(&lprc, pt).into() } } -pub fn load_icon(hinstance: HMODULE, lpiconname: PCWSTR) -> windows::core::Result{ +pub fn load_icon(hinstance: HMODULE, lpiconname: PCWSTR) -> windows::core::Result { unsafe { LoadIconW(hinstance, lpiconname) } } - -// ===== -// Virtual desktop -// ===== - -pub struct VirtualDesktopManager(IVirtualDesktopManager); - -impl VirtualDesktopManager { - pub fn new() -> Result { - info!("Instantiate VirtualDesktopManager"); - unsafe { - CoInitialize(None)?; - } - let virtual_desktop_managr = - unsafe { CoCreateInstance(&VirtualDesktopManager_ID, None, CLSCTX_ALL)? }; - Ok(Self(virtual_desktop_managr)) - } - - pub fn is_window_on_current_desktop(&self, hwnd: HWND) -> windows::core::Result { - let is_on_desktop = unsafe { self.0.IsWindowOnCurrentVirtualDesktop(hwnd)? }; - Ok(is_on_desktop.as_bool()) - } -} diff --git a/src/win32/virtualdesktop.rs b/src/win32/virtualdesktop.rs new file mode 100644 index 0000000..80351f5 --- /dev/null +++ b/src/win32/virtualdesktop.rs @@ -0,0 +1,26 @@ +use windows::Win32::{ + Foundation::HWND, + UI::Shell::{ + IVirtualDesktopManager, VirtualDesktopManager as VirtualDesktopManager_ID + } +}; +use log::info; + +use grout_wm::Result; + +pub struct VirtualDesktopManager(IVirtualDesktopManager); + +impl VirtualDesktopManager { + pub fn new() -> Result { + use windows::Win32::System::Com::{CoCreateInstance, CLSCTX_ALL}; + info!("Instantiate VirtualDesktopManager"); + let virtual_desktop_managr = + unsafe { CoCreateInstance(&VirtualDesktopManager_ID, None, CLSCTX_ALL)? }; + Ok(Self(virtual_desktop_managr)) + } + + pub fn is_window_on_current_desktop(&self, hwnd: HWND) -> windows::core::Result { + let is_on_desktop = unsafe { self.0.IsWindowOnCurrentVirtualDesktop(hwnd)? }; + Ok(is_on_desktop.as_bool()) + } +} diff --git a/src/windowmanager.rs b/src/windowmanager.rs index a6e3b00..3eade0e 100644 --- a/src/windowmanager.rs +++ b/src/windowmanager.rs @@ -4,7 +4,7 @@ use log::{debug, error, info}; use windows::Win32::{ Foundation::{BOOL, HWND, LPARAM, LRESULT, RECT, TRUE, WPARAM}, UI::WindowsAndMessaging::{ - GW_OWNER, HSHELL_WINDOWCREATED, HSHELL_WINDOWDESTROYED, WM_USER, WS_CHILD, WS_DISABLED, + GW_OWNER, HSHELL_WINDOWCREATED, HSHELL_WINDOWDESTROYED, WM_USER, WS_CHILD, WS_DISABLED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, }, }; @@ -12,9 +12,10 @@ use windows::Win32::{ use crate::{ arrange::spiral_subdivide, config::Config, - win32::{self, VirtualDesktopManager}, + win32::{virtualdesktop::VirtualDesktopManager}, window::Window, }; +use crate::win32; use grout_wm::{any, has_flag, Result}; pub const MSG_UNCLOAKED: u32 = WM_USER; @@ -68,7 +69,7 @@ impl WindowManager { let style = win32::get_window_style(hwnd); let exstyle = win32::get_window_exstyle(hwnd); let is_child = has_flag!(style, WS_CHILD.0); - let is_cloaked = win32::is_cloaked(hwnd); + let is_cloaked = win32::dwm::is_cloaked(hwnd); let is_disabled = has_flag!(style, WS_DISABLED.0); let is_tool = has_flag!(exstyle, WS_EX_TOOLWINDOW.0); let is_visible = win32::is_window_visible(hwnd); @@ -117,6 +118,8 @@ impl WindowManager { .unwrap_or(false); if is_on_desktop { self.managed_windows.retain(|w| w.0 != hwnd); + } else { + self.arrange(); } } From 3a8cf2cfebe0172dea3ddb14ab0362c121da8b8b Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sat, 15 Jul 2023 18:31:13 +0200 Subject: [PATCH 5/7] Set screenshot as iconic thumbnail --- src/appwindow.rs | 121 ++++++++++++++++++++++++++++++++++++++++++----- src/win32/dwm.rs | 26 ++++++++-- 2 files changed, 132 insertions(+), 15 deletions(-) diff --git a/src/appwindow.rs b/src/appwindow.rs index dd9c9ef..fb975d2 100644 --- a/src/appwindow.rs +++ b/src/appwindow.rs @@ -1,19 +1,26 @@ -use std::{ffi::c_void, sync::OnceLock}; +use std::{ + ffi::{c_uchar, c_void}, + sync::OnceLock, +}; use log::{debug, error, info}; use windows::{ w, Win32::{ Foundation::{HWND, LPARAM, LRESULT, WPARAM}, - Graphics::Gdi::{COLOR_WINDOW, HBRUSH}, + Graphics::{ + Dwm::{DWMWA_FORCE_ICONIC_REPRESENTATION, DWMWA_HAS_ICONIC_BITMAP}, + Gdi::{BITMAPINFO, BITMAPINFOHEADER, COLOR_WINDOW, HBRUSH}, + }, UI::{ Accessibility::{UnhookWinEvent, HWINEVENTHOOK}, WindowsAndMessaging::{ CreateWindowExW, DeregisterShellHookWindow, CHILDID_SELF, CREATESTRUCTA, CW_USEDEFAULT, EVENT_OBJECT_CLOAKED, EVENT_OBJECT_UNCLOAKED, EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MOVESIZEEND, - EVENT_SYSTEM_MOVESIZESTART, GWLP_USERDATA, OBJID_WINDOW, WINDOW_EX_STYLE, WM_APP, - WM_CREATE, WM_DESTROY, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, WM_SYSCOMMAND, SC_RESTORE, + EVENT_SYSTEM_MOVESIZESTART, GWLP_USERDATA, OBJID_WINDOW, SC_RESTORE, + WINDOW_EX_STYLE, WM_APP, WM_CREATE, WM_DESTROY, WM_DWMSENDICONICTHUMBNAIL, + WM_SYSCOMMAND, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, }, }, }, @@ -22,13 +29,29 @@ use windows::{ use grout_wm::Result; use crate::{ - win32::{self, load_icon, get_module_handle, register_class, show_window, register_shell_hook_window, register_window_messagew, set_win_event_hook, def_window_proc, set_window_long_ptr, post_quit_message, get_window_long_ptr}, + win32::{ + self, def_window_proc, get_module_handle, get_window_long_ptr, get_working_area, load_icon, + post_quit_message, register_class, register_shell_hook_window, register_window_messagew, + set_win_event_hook, set_window_long_ptr, show_window, + }, windowmanager::{ WindowManager, MSG_CLOAKED, MSG_MINIMIZEEND, MSG_MINIMIZESTART, MSG_MOVESIZEEND, MSG_UNCLOAKED, SHELL_HOOK_ID, }, }; +macro_rules! LOWORD { + ($w:expr) => { + $w & 0xFFFF + }; +} + +macro_rules! HIWORD { + ($w:expr) => { + ($w >> 16) & 0xFFFF + }; +} + static MY_HWND: OnceLock = OnceLock::new(); pub struct AppWindow { @@ -38,7 +61,6 @@ pub struct AppWindow { movesize_event_hook: HWINEVENTHOOK, } - impl AppWindow { pub fn new_window(wm: &mut WindowManager) -> Result { let instance = get_module_handle()?; @@ -68,8 +90,8 @@ impl AppWindow { None, None, instance, - Some(wm as *mut _ as *mut c_void) - ) + Some(wm as *mut _ as *mut c_void), + ) }; if hwnd.0 == 0 { error!("Could not create window"); @@ -78,7 +100,7 @@ impl AppWindow { let _ = MY_HWND.set(hwnd); Ok(Self { hwnd, - cloaked_event_hook: Default::default (), + cloaked_event_hook: Default::default(), minimized_event_hook: Default::default(), movesize_event_hook: Default::default(), }) @@ -106,17 +128,17 @@ impl AppWindow { EVENT_OBJECT_CLOAKED, EVENT_OBJECT_UNCLOAKED, Some(Self::wnd_event_proc), - ); + ); let minimized_event_hook = set_win_event_hook( EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MINIMIZEEND, Some(Self::wnd_event_proc), - ); + ); let movesize_event_hook = set_win_event_hook( EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, Some(Self::wnd_event_proc), - ); + ); Ok(Self { hwnd: self.hwnd, cloaked_event_hook, @@ -194,6 +216,16 @@ impl AppWindow { let create_struct = lparam.0 as *const CREATESTRUCTA; let wm = unsafe { (*create_struct).lpCreateParams as *mut WindowManager }; set_window_long_ptr(hwnd, GWLP_USERDATA, wm as _); + let _ = win32::dwm::set_window_attribute(hwnd, DWMWA_HAS_ICONIC_BITMAP); + let _ = win32::dwm::set_window_attribute(hwnd, DWMWA_FORCE_ICONIC_REPRESENTATION); + let _ = win32::dwm::invalidate_iconic_bitmaps(hwnd); + LRESULT(0) + } + WM_DWMSENDICONICTHUMBNAIL => { + debug!("WM_DWMSENDICONICTHUMBNAIL"); + let width = HIWORD!(lparam.0); + let height = LOWORD!(lparam.0); + let _ = set_screenshot_as_iconic_thumbnail(hwnd, width, height); LRESULT(0) } WM_SYSCOMMAND => { @@ -213,3 +245,68 @@ impl AppWindow { } } } + +fn set_screenshot_as_iconic_thumbnail(hwnd: HWND, thumb_w: isize, thumb_h: isize) -> Result<()> { + let working_area = get_working_area()?; + let w = working_area.right - working_area.left; + let h = working_area.bottom - working_area.top; + let hdc_mem = unsafe { windows::Win32::Graphics::Gdi::CreateCompatibleDC(None) }; + if !hdc_mem.is_invalid() { + let mut bmi: BITMAPINFO = unsafe { std::mem::zeroed() }; + bmi.bmiHeader.biSize = std::mem::size_of::() as u32; + bmi.bmiHeader.biWidth = thumb_w as i32; + bmi.bmiHeader.biHeight = thumb_h as i32; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + let mut pb_ds = std::ptr::null_mut::>(); + let hbm_res = unsafe { + windows::Win32::Graphics::Gdi::CreateDIBSection( + hdc_mem, + &bmi as *const _ as *const _, + windows::Win32::Graphics::Gdi::DIB_RGB_COLORS, + &mut pb_ds as *mut _ as *mut _, + None, + 0, + ) + }; + if let Ok(hbitmap) = hbm_res { + let hscreen = unsafe { windows::Win32::Graphics::Gdi::GetDC(None) }; + let hdc = unsafe { windows::Win32::Graphics::Gdi::CreateCompatibleDC(hscreen) }; + unsafe { + windows::Win32::Graphics::Gdi::SetStretchBltMode( + hdc, + windows::Win32::Graphics::Gdi::HALFTONE, + ) + }; + let old_obj = unsafe { windows::Win32::Graphics::Gdi::SelectObject(hdc, hbitmap) }; + let _bret = unsafe { + windows::Win32::Graphics::Gdi::StretchBlt( + hdc, + 0, + 0, + thumb_w as i32, + thumb_h as i32, + hscreen, + 0, + 0, + w, + h, + windows::Win32::Graphics::Gdi::SRCCOPY, + ) + }; + let dwm_res = + unsafe { windows::Win32::Graphics::Dwm::DwmSetIconicThumbnail(hwnd, hbitmap, 0) }; + if let Err(e) = dwm_res { + dbg!(e); + } + // cleanup + unsafe { + windows::Win32::Graphics::Gdi::SelectObject(hdc, old_obj); + windows::Win32::Graphics::Gdi::DeleteDC(hdc); + windows::Win32::Graphics::Gdi::ReleaseDC(None, hscreen); + windows::Win32::Graphics::Gdi::DeleteObject(hbitmap); + } + } + } + Ok(()) +} diff --git a/src/win32/dwm.rs b/src/win32/dwm.rs index e4db9e9..a2c51a0 100644 --- a/src/win32/dwm.rs +++ b/src/win32/dwm.rs @@ -1,10 +1,11 @@ use std::ffi::c_void; use std::mem::{size_of, zeroed}; use windows::Win32::{ - Foundation::{HWND, RECT}, + Foundation::{BOOL, HWND, RECT, TRUE}, Graphics::Dwm::{ - DwmGetWindowAttribute, DWMWA_CLOAKED, DWMWA_EXTENDED_FRAME_BOUNDS, DWM_CLOAKED_APP, - DWM_CLOAKED_INHERITED, DWM_CLOAKED_SHELL, + DwmGetWindowAttribute, DwmInvalidateIconicBitmaps, DwmSetWindowAttribute, DWMWA_CLOAKED, + DWMWA_EXTENDED_FRAME_BOUNDS, DWMWINDOWATTRIBUTE, DWM_CLOAKED_APP, DWM_CLOAKED_INHERITED, + DWM_CLOAKED_SHELL, }, UI::WindowsAndMessaging::GetWindowRect, }; @@ -47,3 +48,22 @@ pub fn is_cloaked(hwnd: HWND) -> bool { _ => false, } } + +pub fn set_window_attribute( + hwnd: HWND, + dwattribute: DWMWINDOWATTRIBUTE, +) -> windows::core::Result<()> { + let is_true: BOOL = TRUE; + unsafe { + DwmSetWindowAttribute( + hwnd, + dwattribute, + &is_true as *const BOOL as *const _, + size_of::() as u32, + ) + } +} + +pub fn invalidate_iconic_bitmaps(hwnd: HWND) -> windows::core::Result<()> { + unsafe { DwmInvalidateIconicBitmaps(hwnd) } +} From 6fe74e2207f43b304b7c6d18aeae7e8b5f1452eb Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sat, 15 Jul 2023 18:31:21 +0200 Subject: [PATCH 6/7] Run cargo fmt --- src/win32/virtualdesktop.rs | 6 ++---- src/windowmanager.rs | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/win32/virtualdesktop.rs b/src/win32/virtualdesktop.rs index 80351f5..2e124dd 100644 --- a/src/win32/virtualdesktop.rs +++ b/src/win32/virtualdesktop.rs @@ -1,10 +1,8 @@ +use log::info; use windows::Win32::{ Foundation::HWND, - UI::Shell::{ - IVirtualDesktopManager, VirtualDesktopManager as VirtualDesktopManager_ID - } + UI::Shell::{IVirtualDesktopManager, VirtualDesktopManager as VirtualDesktopManager_ID}, }; -use log::info; use grout_wm::Result; diff --git a/src/windowmanager.rs b/src/windowmanager.rs index 3eade0e..7bac244 100644 --- a/src/windowmanager.rs +++ b/src/windowmanager.rs @@ -4,18 +4,16 @@ use log::{debug, error, info}; use windows::Win32::{ Foundation::{BOOL, HWND, LPARAM, LRESULT, RECT, TRUE, WPARAM}, UI::WindowsAndMessaging::{ - GW_OWNER, HSHELL_WINDOWCREATED, HSHELL_WINDOWDESTROYED, WM_USER, WS_CHILD, WS_DISABLED, + GW_OWNER, HSHELL_WINDOWCREATED, HSHELL_WINDOWDESTROYED, WM_USER, WS_CHILD, WS_DISABLED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, }, }; +use crate::win32; use crate::{ - arrange::spiral_subdivide, - config::Config, - win32::{virtualdesktop::VirtualDesktopManager}, + arrange::spiral_subdivide, config::Config, win32::virtualdesktop::VirtualDesktopManager, window::Window, }; -use crate::win32; use grout_wm::{any, has_flag, Result}; pub const MSG_UNCLOAKED: u32 = WM_USER; From 39df1fc429d2d09472742c4e7dcb11030fd76cb0 Mon Sep 17 00:00:00 2001 From: Martin Askestad Date: Sun, 16 Jul 2023 06:09:04 +0200 Subject: [PATCH 7/7] Prevent appwindow from being restored from restored --- src/appwindow.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/appwindow.rs b/src/appwindow.rs index fb975d2..8d246ab 100644 --- a/src/appwindow.rs +++ b/src/appwindow.rs @@ -20,7 +20,7 @@ use windows::{ EVENT_SYSTEM_MINIMIZEEND, EVENT_SYSTEM_MINIMIZESTART, EVENT_SYSTEM_MOVESIZEEND, EVENT_SYSTEM_MOVESIZESTART, GWLP_USERDATA, OBJID_WINDOW, SC_RESTORE, WINDOW_EX_STYLE, WM_APP, WM_CREATE, WM_DESTROY, WM_DWMSENDICONICTHUMBNAIL, - WM_SYSCOMMAND, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, + WM_SYSCOMMAND, WM_USER, WNDCLASSW, WS_OVERLAPPEDWINDOW, WM_QUERYOPEN, }, }, }, @@ -235,6 +235,9 @@ impl AppWindow { } def_window_proc(hwnd, msg, wparam, lparam) } + WM_QUERYOPEN => { + LRESULT(0) + } _ => { let wm = get_window_long_ptr(hwnd, GWLP_USERDATA) as *mut WindowManager; if !wm.is_null() {