1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-15 00:24:19 +00:00

Direct2D: Fix flickery resizing when using an internal resizer

Resizing using window manager functionality (e.g. clicking and dragging
in the non-client area) will send WM_SIZING to the window, which in turn
will enable continuous repainting in the D2D renderer until the resize
operation ends.

Continuous repainting is required in order for the window to display
correctly during the resize. Without continuous repainting, some frames
may not be completely painted, and may display with black areas,
producing a flickery effect.

When a resize is controlled entirely by the client, e.g. using the
corner resizer in the AudioPluginDemo standalone, WM_SIZING is never
posted. Instead, we assume that if the window has captured the cursor
during a setBounds call then it is probably resizing. We enable
continuous repainting in this case, and stop repainting once the window
releases the mouse.

An alternative appropach would be to add some kind of start/stop resize
API to ComponentPeer. I'm currently reluctant to do that because the
ComponentPeer API is already so large.
This commit is contained in:
reuk 2024-05-28 18:44:47 +01:00
parent adc63cecb1
commit 659de5842f
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
3 changed files with 30 additions and 1 deletions

View file

@ -406,6 +406,11 @@ public:
resizing = x;
}
bool getResizing() const
{
return resizing;
}
void setSize (Rectangle<int> size)
{
if (size == frameSize || size.isEmpty())
@ -692,6 +697,11 @@ void Direct2DHwndContext::setResizing (bool x)
pimpl->setResizing (x);
}
bool Direct2DHwndContext::getResizing() const
{
return pimpl->getResizing();
}
void Direct2DHwndContext::setSize (int width, int height)
{
pimpl->setSize ({ width, height });

View file

@ -46,6 +46,7 @@ public:
void setWindowAlpha (float alpha);
void setResizing (bool);
bool getResizing() const;
void setSize (int width, int height);
void updateSize();

View file

@ -1457,6 +1457,7 @@ struct RenderContext
virtual void performAnyPendingRepaintsNow() = 0;
virtual void onVBlank() = 0;
virtual void setResizing (bool) = 0;
virtual bool getResizing() const = 0;
virtual void handleNcCalcSize (WPARAM wParam, LPARAM lParam) = 0;
virtual void handleShowWindow() = 0;
@ -1641,6 +1642,13 @@ public:
if (inHandlePositionChanged)
return;
// This is more of a guess than a certainty, but if we've captured the mouse and we're also
// updating the bounds, there's a good chance we're in a client-initiated resize.
// The resizing flag will be unset by WM_CAPTURECHANGED.
if (GetCapture() == hwnd)
if (renderContext != nullptr)
renderContext->setResizing (true);
const ScopedValueSetter<bool> scope (shouldIgnoreModalDismiss, true);
fullScreen = isNowFullScreen;
@ -2811,6 +2819,9 @@ private:
constrainerIsResizing = false;
}
if (renderContext != nullptr && renderContext->getResizing())
renderContext->setResizing (false);
if (isDragging)
doMouseUp (getCurrentMousePos(), (WPARAM) 0);
}
@ -4609,7 +4620,8 @@ public:
void onVBlank() override {}
void setResizing (bool) override {}
void setResizing (bool x) override { resizing = x; }
bool getResizing() const override { return resizing; }
void handleNcCalcSize (WPARAM, LPARAM) override {}
void handleShowWindow() override {}
@ -4780,6 +4792,7 @@ private:
TemporaryImage offscreenImageGenerator;
RectangleList<int> deferredRepaints;
uint8 layeredWindowAlpha = 255;
bool resizing = false;
};
class D2DContext : public RenderContext
@ -4870,6 +4883,11 @@ public:
direct2DContext->setResizing (x);
}
bool getResizing() const override
{
return direct2DContext->getResizing();
}
void handleNcCalcSize (WPARAM, LPARAM lParam) override
{
JUCE_TRACE_LOG_D2D_RESIZE (WM_NCCALCSIZE);