diff options
author | Patrick Luby <plubius@neooffice.org> | 2023-01-04 16:22:46 -0500 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-01-05 18:32:49 +0000 |
commit | 2d1a0d86d2d0c00fcfee61c39f2221e786e4245b (patch) | |
tree | f671e5a75ad294942a359daadf5bcbaa7dc52666 | |
parent | e5b5d9c8d33b1dd87e5a50856ad02f21df59dc5b (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.mm | 74 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 5 |
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()))) |