Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank page when minimizing a maximized frameless window with multi-monitor setup #2549

Closed
amrbashir opened this issue Jun 26, 2022 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@amrbashir
Copy link

amrbashir commented Jun 26, 2022

Description

In a multi-monitor setup, minimizing a maximized frameless Window (created by returning 0 to WM_NCCALCSIZE) will result in a blank window.

Version
SDK: 1.0.902.49
Runtime: 102.0.1245.44
Framework: win32
OS: noticed on win10 and win11

Repro Steps

  1. Clone the https://github.com/MicrosoftEdge/WebView2Samples repo
  2. apply the following diff
    diff --git a/GettingStartedGuides/Win32_GettingStarted/HelloWebView.cpp b/GettingStartedGuides/Win32_GettingStarted/HelloWebView.cpp
    index 4243c71..6cc5d40 100644
    --- a/GettingStartedGuides/Win32_GettingStarted/HelloWebView.cpp
    +++ b/GettingStartedGuides/Win32_GettingStarted/HelloWebView.cpp
    @@ -212,6 +212,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
     
        switch (message)
        {
    +	case WM_NCCALCSIZE:
    +	{
    +		WINDOWPLACEMENT placement = { 0 };
    +		placement.length = sizeof(WINDOWPLACEMENT);
    +		GetWindowPlacement(hWnd, &placement);
    +
    +		if (placement.showCmd == SW_MAXIMIZE) {
    +			HMONITOR hmonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
    +			MONITORINFOEXW mInfo = {};
    +			mInfo.cbSize = sizeof(MONITORINFOEXW);
    +			GetMonitorInfo(hmonitor, &mInfo);
    +			auto& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
    +			params.rgrc[0] = mInfo.rcWork;
    +
    +		}
    +		return 0;
    +	}
        case WM_SIZE:
      	  if (webviewController != nullptr) {
      		  RECT bounds;
  3. launch the sample on the main monitor (doesn't happen on the secondary monitor)
  4. maximize the window using Win + Arrow Up
  5. minimize the window by clicking the icon in the taskbar
  6. restore the window by clicking the icon in the taskbar
  7. The window is now either solid white or black, sometimes with other graphical issues
  8. Move the window using the invisible titlebar or otherwise alter the window size e.g. through Win + Arrow Down, this restores full functionality to the window. Nothing happens when you click within the window though.

Screenshots

WebView2_frameless_maximized_window_bug.mp4

Additional context
This was observed by multiple tauri users in tauri-apps/tao#471

@bradp0721
Copy link
Member

bradp0721 commented Jul 11, 2022

This appears to be an issue with the code snippet, not WebView2. When I swap the WebView2 out for other HWND controls (like buttons), they also disappear when using the provided code snippet.

From my debugging through Visual Studio, MonitorFromWindow is returning the wrong monitor when restoring the app to a maximized state. MonitorFromWindow actually can't find the monitor for the HWND, so it is using the MONITOR_DEFAULTTONEAREST default option (if I change the default option to MONITOR_DEFAULTTONULL then MonitorFromWindow returns null in the repro case). In the repro case, this doesn't match the monitor the HWND is on. I noticed MonitorFromWIndow also returns the wrong monitor when the window is maximized and you move the window to another monitor using Win + Shift + Arrow.

To fix this, you should use MonitorFromRect and use the provided RECT in the NCCALCSIZE_PARAMS to get the monitor that the HWND will be on. Then you can update the NCCALCSIZE_PARAMS rect with the correct monitor's rcWork.

    case WM_NCCALCSIZE:
    {
        WINDOWPLACEMENT placement = { 0 };
        placement.length = sizeof(WINDOWPLACEMENT);
        GetWindowPlacement(hWnd, &placement);

        if (placement.showCmd == SW_MAXIMIZE) {
            auto& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
            HMONITOR hmonitor = MonitorFromRect(&params.rgrc[0], MONITOR_DEFAULTTONULL);
            MONITORINFOEXW mInfo = { 0 };
            mInfo.cbSize = sizeof(MONITORINFOEXW);
            GetMonitorInfo(hmonitor, &mInfo);
            params.rgrc[0] = mInfo.rcWork;
        }
        return 0;
    }

@amrbashir
Copy link
Author

Never thought that MonitorFromWindow would have this behavior since it is not mentioned in MSDN. Thanks for the thorough explanation and debugging. Have a nice day.

amrbashir added a commit to tauri-apps/tao that referenced this issue Jul 11, 2022
`MonitorFromWindow` is unreliable with maximized Window, it either can't
find a monitor for the window and will default to nearest monitor or it
will find a wrong monitor, see
MicrosoftEdge/WebView2Feedback#2549 (comment).
wusyong pushed a commit to tauri-apps/tao that referenced this issue Jul 12, 2022
* fix(windows): get correct monitor in `WM_NCCALCSIZE`, closes #471

`MonitorFromWindow` is unreliable with maximized Window, it either can't
find a monitor for the window and will default to nearest monitor or it
will find a wrong monitor, see
MicrosoftEdge/WebView2Feedback#2549 (comment).

* changefile
stffabi added a commit to stffabi/wails that referenced this issue Nov 3, 2022
MonitorFromWindow is unreliable during a maximize, it might return
the wrong monitor for the window or can't find one.

MicrosoftEdge/WebView2Feedback#2549
stffabi added a commit to stffabi/wails that referenced this issue Nov 3, 2022
MonitorFromWindow is unreliable during a maximize, it might return
the wrong monitor for the window or can't find one.

MicrosoftEdge/WebView2Feedback#2549
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants