summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Luby <plubius@neooffice.org>2023-01-04 16:22:46 -0500
committerNoel Grandin <noel.grandin@collabora.co.uk>2023-01-05 18:32:49 +0000
commit2d1a0d86d2d0c00fcfee61c39f2221e786e4245b (patch)
treef671e5a75ad294942a359daadf5bcbaa7dc52666
parente5b5d9c8d33b1dd87e5a50856ad02f21df59dc5b (diff)
Related: tdf#152703 Prevent possible hang when live resizing a window
Application::Reschedule() can potentially display a modal dialog which will cause a hang so temporarily disable live resize by clampiing the window's minimum and maximum sizes to the current frame size which in Application::Reschedule(). Also, eliminate flickering during live resizing of a window when using Skia/Metal. When in live resize, the SkiaSalGraphicsImpl class does not detect that the window size has changed until after the flush has been called so call checkSurface() to recreate the SkSurface if needed before flushing. Flushing had to be moved during [self windowDidResize:] to eliminate flicker. Flushing in [self displayIfNeeded] does not eliminate flicker so apparently [self windowDidResize:] is called earlier. Change-Id: Id3de838d2e17fee85cb583b6c4e862b571d47142 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145053 Tested-by: Jenkins Reviewed-by: Michael Meeks <michael.meeks@collabora.com> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r--vcl/osx/salframeview.mm74
-rw-r--r--vcl/skia/gdiimpl.cxx5
2 files changed, 50 insertions, 29 deletions
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index 61061253a2da..43260a7d5077 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -220,22 +220,6 @@ static AquaSalFrame* getMouseContainerFrame()
if( GetSalData() && GetSalData()->mpInstance )
{
SolarMutexGuard aGuard;
-
-#if HAVE_FEATURE_SKIA
- // Related: tdf#152703 Eliminate empty window with Skia/Metal while resizing
- // The window will clear its background so when Skia/Metal is enabled,
- // explicitly flush the Skia graphics to the window during live
- // resizing or else nothing will be drawn until after live resizing
- // has ended.
- // TODO: See if flickering when flushing can be eliminated somehow.
- if ( [self inLiveResize] && SkiaHelper::isVCLSkiaEnabled() && mpFrame && AquaSalFrame::isAlive( mpFrame ) )
- {
- AquaSalGraphics* pGraphics = mpFrame->mpGraphics;
- if ( pGraphics )
- pGraphics->Flush();
- }
-#endif
-
[super displayIfNeeded];
}
}
@@ -339,9 +323,29 @@ static AquaSalFrame* getMouseContainerFrame()
mpFrame->UpdateFrameGeometry();
mpFrame->CallCallback( SalEvent::Resize, nullptr );
- if ( [self inLiveResize] )
+ BOOL bInLiveResize = [self inLiveResize];
+ if ( bInLiveResize || mbInLiveResize )
{
- mbInLiveResize = YES;
+ mbInLiveResize = bInLiveResize;
+
+#if HAVE_FEATURE_SKIA
+ // Related: tdf#152703 Eliminate empty window with Skia/Metal while resizing
+ // The window will clear its background so when Skia/Metal is
+ // enabled, explicitly flush the Skia graphics to the window
+ // during live resizing or else nothing will be drawn until after
+ // live resizing has ended.
+ // Also, flushing during [self windowDidResize:] eliminates flicker
+ // by forcing this window's SkSurface to recreate its underlying
+ // CAMetalLayer with the new size. Flushing in
+ // [self displayIfNeeded] does not eliminate flicker so apparently
+ // [self windowDidResize:] is called earlier.
+ if ( SkiaHelper::isVCLSkiaEnabled() )
+ {
+ AquaSalGraphics* pGraphics = mpFrame->mpGraphics;
+ if ( pGraphics )
+ pGraphics->Flush();
+ }
+#endif
// tdf#152703 Force relayout during live resizing of window
// During a live resize, macOS floods the application with
@@ -349,23 +353,35 @@ static AquaSalFrame* getMouseContainerFrame()
// not trigger redrawing with the new size.
// Instead, force relayout by dispatching all pending internal
// events and firing any pending timers.
+ // Also, Application::Reschedule() can potentially display a
+ // modal dialog which will cause a hang so temporarily disable
+ // live resize by clampiing the window's minimum and maximum sizes
+ // to the current frame size which in Application::Reschedule().
+ NSRect aFrame = [self frame];
+ NSSize aMinSize = [self minSize];
+ NSSize aMaxSize = [self maxSize];
+ [self setMinSize:aFrame.size];
+ [self setMaxSize:aFrame.size];
Application::Reschedule( true );
+ [self setMinSize:aMinSize];
+ [self setMaxSize:aMaxSize];
- // tdf#152703 Force repaint after live resizing ends
- // Repost this notification so that this selector will be called
- // at least once after live resizing ends. Pass nil for withObject:
- // since it is unused and makes it easier to cancel all pending
- // selector execution when live resizing ends.
- [self performSelector:@selector(windowDidResize:) withObject:nil afterDelay:0.1f];
- }
- else
- {
if ( mbInLiveResize )
{
- mbInLiveResize = NO;
+ // tdf#152703 Force repaint after live resizing ends
+ // Repost this notification so that this selector will be called
+ // at least once after live resizing ends. Pass nil for
+ // withObject: since it is unused and makes it easier to cancel
+ // all pending selector execution when live resizing ends.
+ [self performSelector:@selector(windowDidResize:) withObject:nil afterDelay:0.1f];
+ }
+ else
+ {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(windowDidResize:) object:nil];
}
-
+ }
+ else
+ {
mpFrame->SendPaintEvent();
}
}
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index c2c22430dd5a..55f803217bb0 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -372,6 +372,11 @@ void SkiaSalGraphicsImpl::performFlush()
{
SkiaZone zone;
flushDrawing();
+ // Related: tdf#152703 Eliminate flickering during live resizing of a window
+ // When in live resize, the SkiaSalGraphicsImpl class does not detect that
+ // the window size has changed until after the flush has been called so
+ // call checkSurface() to recreate the SkSurface if needed before flushing.
+ checkSurface();
if (mSurface)
{
if (mDirtyRect.intersect(SkIRect::MakeWH(GetWidth(), GetHeight())))