Skip to content

Commit

Permalink
On Windows, fix window size for maximized, undecorated windows (#2584)
Browse files Browse the repository at this point in the history
Co-authored-by: Amr Bashir <[email protected]>
  • Loading branch information
msiglreith and amrbashir authored Jan 28, 2023
1 parent c984476 commit 23b8212
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
- On Windows and macOS, add `WindowBuilder::with_active`.
- Add `Window::is_minimized`.
- On X11, fix errors handled during `register_xlib_error_hook` invocation bleeding into winit.
Expand Down
38 changes: 25 additions & 13 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,19 +977,31 @@ unsafe fn public_window_callback_inner<T: 'static>(
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.
//
// Use `MonitorFromRect` instead of `MonitorFromWindow` to select
// the correct monitor here.
// See https://github.com/MicrosoftEdge/WebView2Feedback/issues/2549
let monitor = MonitorFromRect(&params.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) {
// 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;
}
Expand Down
19 changes: 14 additions & 5 deletions src/platform_impl/windows/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ use windows_sys::{
HiDpi::{DPI_AWARENESS_CONTEXT, MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS},
Input::KeyboardAndMouse::GetActiveWindow,
WindowsAndMessaging::{
ClipCursor, GetClientRect, GetClipCursor, GetSystemMetrics, GetWindowRect,
IsIconic, 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, IsIconic, 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,
},
},
},
Expand Down Expand Up @@ -91,6 +91,15 @@ impl WindowArea {
}
}

pub fn is_maximized(window: HWND) -> bool {
unsafe {
let mut placement: WINDOWPLACEMENT = mem::zeroed();
placement.length = mem::size_of::<WINDOWPLACEMENT>() 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;
Expand Down

0 comments on commit 23b8212

Please sign in to comment.