From bd044d7d4472dc87163dd2a08c43cfeb146db030 Mon Sep 17 00:00:00 2001 From: msiglreith Date: Tue, 6 Dec 2022 18:29:38 +0100 Subject: [PATCH 1/4] On Windows, fix window size for maximized, undecorated windows Co-authored-by: Amr Bashir --- CHANGELOG.md | 1 + src/platform_impl/windows/event_loop.rs | 34 +++++++++++++++---------- src/platform_impl/windows/util.rs | 18 ++++++++++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea246d45b4..559bcd1a1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased +- On Windows, fix window size for maximized, undecorated windows. - **Breaking:** Removed `Window::set_always_on_top` and related APIs in favor of `Window::set_window_level`. - On Windows, MacOS and X11, add always on bottom APIs. - On Windows, fix the value in `MouseButton::Other`. diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 15ff475c7c..b177d86255 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -978,19 +978,27 @@ unsafe fn public_window_callback_inner( return DefWindowProcW(window, msg, wparam, lparam); } - // Extend the client area to cover the whole non-client area. - // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize#remarks - // - // HACK(msiglreith): To add the drop shadow we slightly tweak the non-client area. - // This leads to a small black 1px border on the top. Adding a margin manually - // on all 4 borders would result in the caption getting drawn by the DWM. - // - // Another option would be to allow the DWM to paint inside the client area. - // Unfortunately this results in janky resize behavior, where the compositor is - // ahead of the window surface. Currently, there seems no option to achieve this - // with the Windows API. - if window_flags.contains(WindowFlags::MARKER_UNDECORATED_SHADOW) { - let params = &mut *(lparam as *mut NCCALCSIZE_PARAMS); + let params = &mut *(lparam as *mut NCCALCSIZE_PARAMS); + + if util::is_maximized(window) { + // Limit the window size when maximized to the current monitor. + // Otherwise it would include the non-existent decorations. + let monitor = monitor::current_monitor(window); + if let Ok(monitor_info) = monitor::get_monitor_info(monitor.hmonitor()) { + params.rgrc[0] = monitor_info.monitorInfo.rcWork; + } + } else if window_flags.contains(WindowFlags::MARKER_UNDECORATED_SHADOW) { + // Extend the client area to cover the whole non-client area. + // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize#remarks + // + // HACK(msiglreith): To add the drop shadow we slightly tweak the non-client area. + // This leads to a small black 1px border on the top. Adding a margin manually + // on all 4 borders would result in the caption getting drawn by the DWM. + // + // Another option would be to allow the DWM to paint inside the client area. + // Unfortunately this results in janky resize behavior, where the compositor is + // ahead of the window surface. Currently, there seems no option to achieve this + // with the Windows API. params.rgrc[0].top += 1; params.rgrc[0].bottom += 1; } diff --git a/src/platform_impl/windows/util.rs b/src/platform_impl/windows/util.rs index 5f09bee64e..4196f253ca 100644 --- a/src/platform_impl/windows/util.rs +++ b/src/platform_impl/windows/util.rs @@ -23,10 +23,11 @@ use windows_sys::{ HiDpi::{DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS}, Input::KeyboardAndMouse::GetActiveWindow, WindowsAndMessaging::{ - ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowRect, - ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, - IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT, - SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN, + ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowPlacement, + GetWindowRect, ShowCursor, IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, + IDC_HELP, IDC_IBEAM, IDC_NO, IDC_SIZEALL, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, + IDC_SIZEWE, IDC_WAIT, SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN, SM_XVIRTUALSCREEN, + SM_YVIRTUALSCREEN, SW_MAXIMIZE, WINDOWPLACEMENT, }, }, }, @@ -90,6 +91,15 @@ impl WindowArea { } } +pub fn is_maximized(window: HWND) -> bool { + unsafe { + let mut placement: WINDOWPLACEMENT = mem::zeroed(); + placement.length = mem::size_of::() as u32; + GetWindowPlacement(window, &mut placement); + placement.showCmd == SW_MAXIMIZE + } +} + pub fn set_cursor_hidden(hidden: bool) { static HIDDEN: AtomicBool = AtomicBool::new(false); let changed = HIDDEN.swap(hidden, Ordering::SeqCst) ^ hidden; From ba8711444e3e2fd5b0ae0d6c71bc15a7429d4993 Mon Sep 17 00:00:00 2001 From: msiglreith Date: Fri, 27 Jan 2023 23:04:18 +0100 Subject: [PATCH 2/4] Use `MonitorFromRect` instead of `MonitorFromWindow` --- src/platform_impl/windows/event_loop.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index d2658084cd..59af9a9b55 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -983,8 +983,11 @@ unsafe fn public_window_callback_inner( if util::is_maximized(window) { // Limit the window size when maximized to the current monitor. // Otherwise it would include the non-existent decorations. - let monitor = monitor::current_monitor(window); - if let Ok(monitor_info) = monitor::get_monitor_info(monitor.hmonitor()) { + // + // Use `MonitorFromRect` instead of `MonitorFromWindow` to achieve correct selsection. + // See https://github.com/MicrosoftEdge/WebView2Feedback/issues/2549 + let monitor = MonitorFromRect(¶ms.rgrc[0], MONITOR_DEFAULTTONULL); + if let Ok(monitor_info) = monitor::get_monitor_info(monitor) { params.rgrc[0] = monitor_info.monitorInfo.rcWork; } } else if window_flags.contains(WindowFlags::MARKER_UNDECORATED_SHADOW) { From aa57a32b56b3bb2eaaa8f945cece6eaef504f5e4 Mon Sep 17 00:00:00 2001 From: msiglreith Date: Fri, 27 Jan 2023 23:06:51 +0100 Subject: [PATCH 3/4] fix docs --- src/platform_impl/windows/event_loop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 59af9a9b55..469115d0a1 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -984,7 +984,8 @@ unsafe fn public_window_callback_inner( // Limit the window size when maximized to the current monitor. // Otherwise it would include the non-existent decorations. // - // Use `MonitorFromRect` instead of `MonitorFromWindow` to achieve correct selsection. + // Use `MonitorFromRect` instead of `MonitorFromWindow` to select + // the correct monitor here. // See https://github.com/MicrosoftEdge/WebView2Feedback/issues/2549 let monitor = MonitorFromRect(¶ms.rgrc[0], MONITOR_DEFAULTTONULL); if let Ok(monitor_info) = monitor::get_monitor_info(monitor) { From 8e6d88ad2a730fcad1bce22b6685c35bac98dfb5 Mon Sep 17 00:00:00 2001 From: msiglreith Date: Fri, 27 Jan 2023 23:25:29 +0100 Subject: [PATCH 4/4] remove debug stuff .. --- src/platform_impl/windows/event_loop.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 9bed9ccf37..dbce31e8b2 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -1006,10 +1006,6 @@ unsafe fn public_window_callback_inner( params.rgrc[0].bottom += 1; } - println!("0: {}:{}:{}:{}", params.rgrc[0].top, params.rgrc[0].bottom, params.rgrc[0].left, params.rgrc[0].right); - println!("1: {}:{}:{}:{}", params.rgrc[1].top, params.rgrc[1].bottom, params.rgrc[1].left, params.rgrc[1].right); - println!("2: {}:{}:{}:{}", params.rgrc[2].top, params.rgrc[2].bottom, params.rgrc[2].left, params.rgrc[2].right); - 0 }