D2D bug: WM_GETMINMAXINFO not handled

I noticed weird mouse behaviour and sudden disappearance of the native Windows title bar, when using the D2D renderer. This problem only happened, when my app window was considerably wider than my monitor/display. I have a small monitor, only 1280 pixels wide. And the standalone plugin window was 1440 pixels wide. The problem starts once you move around the window.

After talking to Claude for a few hours, I came to the following conclusion: the file juce_Windowing_windows.cpp does not handle the WM_GETMINMAXINFO case.

Therefore Windows applies its default “ptMaxTrackSize”, which in my case was smaller than the my JUCE application window. Which means the window shrinks while moving it. And for some reason that confuses the D2D renderer a lot and it paints the UI above the native windows title bar. And that means the mouse position no longer matches the UI. So, when you click on a button, nothing happens. Instead you have to click a bit below the button to trigger it.

Note that the missing WM_GETMINMAXINFO is not strictly a D2D problem. But the software renderer can handle it gracefully. Because its just “painting a bitmap” as far as I understand. Whereas the D2D renderer presents a DXGI flip-swapchain through DirectComposition (CreateSwapChainForComposition +CreateTargetForHwnd + visual SetContent), where the swapchain buffer size and the composition placement must stay in sync.

Suggested fix:

In the window proc switch (alongside the other sizing messages) add the following:

case WM_GETMINMAXINFO:
    if (handleGetMinMaxInfo (*(MINMAXINFO*) lParam))
        return 0;

    break;

And the handleGetMinMaxInfo() function looks like this:

LRESULT handleGetMinMaxInfo (MINMAXINFO& mmi)
{
    if (isConstrainedNativeWindow() && ! isFullScreen())
    {
        // Windows defaults ptMaxTrackSize to roughly the monitor size, so when the user grabs
        // the title bar of a window that is wider/taller than the screen, the modal move/size
        // loop clamps it down to fit the monitor. On the Direct2D renderer that clamp resizes
        // the swapchain and desyncs the DirectComposition compositing - content then paints
        // one title-bar height too high and mouse clicks miss. Raise the user-drag size cap so
        // an oversized window keeps its size while being moved. Maximize is unaffected
        // (ptMaxSize/ptMaxPosition are left untouched) and the minimum size is still enforced
        // by the constrainer via WM_SIZING/WM_MOVING/WM_WINDOWPOSCHANGING.
        mmi.ptMaxTrackSize.x = jmax (mmi.ptMaxTrackSize.x, (LONG) 32767);
        mmi.ptMaxTrackSize.y = jmax (mmi.ptMaxTrackSize.y, (LONG) 32767);
        return 1;
    }

    return 0;
}

I have attached the full patch file (see below).

The above fixes the problem on my end. I should note that I tested on JUCE 8.0.12. But I saw that latest develop is not handling WM_GETMINMAXINFO either, so pretty sure it has the same bug.

Environment:

Standalone plugin under Juce 8.0.12, Windows 10 (22H2), single monitor, 100% display scaling, per-monitor-DPI-aware.

windowing-wm-getminmaxinfo.patch (2 KB)

Thanks for the report.

It would be helpful for us to be able to reproduce the problem locally, so that we can debug it and verify the fix.

Have you tested this behaviour in any of the JUCE example apps, such as the DemoRunner? What do you mean by “The problem starts once you move around the window”; are you referring to dragging the window’s titlebar, or moving the mouse or keyboard focus inside the window, or something else?

I’m also wondering whether the proposed solution is a good idea. The system probably constrains the maximum size of the window for a good reason, so it feels like it would be better to make sure that the D2D content gets positioned correctly (under the titlebar) after the system constrains the window, instead of removing the system constraint altogether.

I failed to repro this issue either on Windows 11 or Windows 10. I can resize the window to be larger than the screen using setSize() but any interaction with the titlebar immediately snaps it back to the maximum user area, and I observe not glitching. This is expected behaviour.

I agree that the suggested change looks questionable, and this issue is difficult to address without a repro.

Sorry for late reply.
I am currently on vacation. I’ll check about a minimal test case, when I am back.