tdf#152703 Force relayout during live resizing of window

During a live resize, macOS floods the application with windowDidResize:
notifications so sending a paint event does not trigger redrawing with
the new size. Instead, force relayout by dispatching all pending internal
events and firing any pending timers.

Also, force a repaint of the window after live resizing ends by reposting
this notification so that [self windowDidResize:] will be called at least
once after live resizing ends.

Change-Id: I9d93108c989418bab6d80c7f6afaccc1daaa746e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145042
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h
index 2fcff0d..7ec995b 100644
--- a/vcl/inc/osx/salframeview.h
+++ b/vcl/inc/osx/salframeview.h
@@ -28,6 +28,7 @@ enum class SalEvent;
{
    AquaSalFrame*       mpFrame;
    id mDraggingDestinationHandler;
    BOOL                mbInLiveResize;
}
-(id)initWithSalFrame: (AquaSalFrame*)pFrame;
-(BOOL)canBecomeKeyWindow;
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index 5a28f64..6106125 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -169,6 +169,7 @@ static AquaSalFrame* getMouseContainerFrame()
-(id)initWithSalFrame: (AquaSalFrame*)pFrame
{
    mDraggingDestinationHandler = nil;
    mbInLiveResize = NO;
    mpFrame = pFrame;
    NSRect aRect = { { static_cast<CGFloat>(pFrame->maGeometry.x()), static_cast<CGFloat>(pFrame->maGeometry.y()) },
                     { static_cast<CGFloat>(pFrame->maGeometry.width()), static_cast<CGFloat>(pFrame->maGeometry.height()) } };
@@ -226,6 +227,7 @@ static AquaSalFrame* getMouseContainerFrame()
        // 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;
@@ -337,16 +339,35 @@ static AquaSalFrame* getMouseContainerFrame()
        mpFrame->UpdateFrameGeometry();
        mpFrame->CallCallback( SalEvent::Resize, nullptr );

        // Related: tdf#152703 Stop flicker with Skia/Metal while resizing
        // When Skia/Metal is enabled, rapidly resizing a window has a
        // noticeable amount of flicker so don't send any paint events during
        // live resizing.
        // Also, it appears that most of the LibreOffice layouts do not change
        // their layout much during live resizing so apply this change when
        // Skia is not enabled to ensure consistent behavior whether Skia is
        // enabled or not.
        if ( ![self inLiveResize] )
        if ( [self inLiveResize] )
        {
            mbInLiveResize = YES;

            // tdf#152703 Force relayout during live resizing of window
            // During a live resize, macOS floods the application with
            // windowDidResize: notifications so sending a paint event does
            // not trigger redrawing with the new size.
            // Instead, force relayout by dispatching all pending internal
            // events and firing any pending timers.
            Application::Reschedule( true );

            // 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;
                [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(windowDidResize:) object:nil];
            }

            mpFrame->SendPaintEvent();
        }
    }
}