vcl/inc/osx/salframe.h     |    1 
 vcl/inc/osx/salframeview.h |    4 ++-
 vcl/osx/salframe.cxx       |   34 ++++++++++++++++++------------
 vcl/osx/salframeview.mm    |   50 +++++++++++++++++++++++++++++----------------
 vcl/osx/salinst.cxx        |   10 ++++++---
 5 files changed, 63 insertions(+), 36 deletions(-)

New commits:
commit 54da842381ccb554d3cadc876f23cf183d21bf1a
Author:     Patrick Luby <plub...@libreoffice.org>
AuthorDate: Wed Nov 22 18:21:53 2023 -0500
Commit:     Patrick Luby <plub...@neooffice.org>
CommitDate: Thu Nov 23 16:02:27 2023 +0100

    tdf#155092 use tracking areas instead of tracking rectangles
    
    Apparently, the older, tracking rectangles selectors cause
    unexpected window resizing upon the first mouse down after the
    window has been manually resized so switch to the newer,
    tracking areas selectors. Also, the NSTrackingInVisibleRect
    option allows us to create one single tracking area that
    resizes itself automatically over the lifetime of the view.
    
    Note: for some unknown reason, both NSTrackingMouseMoved and
    NSTrackingAssumeInside are necessary options for this fix
    to work.
    
    Change-Id: I1f771628d872166ff63a52990f671df053d144ca
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159845
    Tested-by: Jenkins
    Reviewed-by: Patrick Luby <plub...@neooffice.org>

diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h
index 2d9b9084fcbb..717e5f310178 100644
--- a/vcl/inc/osx/salframe.h
+++ b/vcl/inc/osx/salframe.h
@@ -78,7 +78,6 @@ public:
 
     PointerStyle                    mePointerStyle;         // currently 
active pointer style
 
-    NSTrackingRectTag               mnTrackingRectTag;      // used to get 
enter/leave messages
     NSRect                          maTrackingRect;
 
     CGMutablePathRef                mrClippingPath;         // used for 
"shaping"
diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h
index f9eca27e305c..1bc2b278d630 100644
--- a/vcl/inc/osx/salframeview.h
+++ b/vcl/inc/osx/salframeview.h
@@ -28,7 +28,6 @@ enum class SalEvent;
 {
     AquaSalFrame*       mpFrame;
     id mDraggingDestinationHandler;
-    BOOL                mbInLiveResize;
     BOOL                mbInWindowDidResize;
     NSTimer*            mpLiveResizeTimer;
 }
@@ -262,6 +261,9 @@ enum class SalEvent;
 -(NSArray *)accessibilityChildren;
 -(NSArray <id<NSAccessibilityElement>> 
*)accessibilityChildrenInNavigationOrder;
 
+-(void)viewWillStartLiveResize;
+-(void)viewDidEndLiveResize;
+
 @end
 
 @interface SalFrameViewA11yWrapper : AquaA11yWrapper
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index a8616c4fedc4..2240de319860 100644
--- a/vcl/osx/salframe.cxx
+++ b/vcl/osx/salframe.cxx
@@ -84,7 +84,6 @@ AquaSalFrame::AquaSalFrame( SalFrame* pParent, 
SalFrameStyleFlags salFrameStyle
     mpMenu( nullptr ),
     mnExtStyle( 0 ),
     mePointerStyle( PointerStyle::Arrow ),
-    mnTrackingRectTag( 0 ),
     mrClippingPath( nullptr ),
     mnICOptions( InputContextFlags::NONE ),
     mnBlinkCursorDelay( nMinBlinkCursorDelay ),
@@ -237,14 +236,27 @@ void AquaSalFrame::initWindowAndView()
     if( mnStyle & SalFrameStyleFlags::TOOLTIP )
         [mpNSWindow setIgnoresMouseEvents: YES];
     else
-        [mpNSWindow setAcceptsMouseMovedEvents: YES];
+        // Related: tdf#155092 mouse events are now handled by tracking areas
+        [mpNSWindow setAcceptsMouseMovedEvents: NO];
     [mpNSWindow setHasShadow: YES];
 
     [mpNSWindow setDelegate: static_cast<id<NSWindowDelegate> >(mpNSWindow)];
 
     [mpNSWindow setRestorable:NO];
-    const NSRect aRect = { NSZeroPoint, NSMakeSize(maGeometry.width(), 
maGeometry.height()) };
-    mnTrackingRectTag = [mpNSView addTrackingRect: aRect owner: mpNSView 
userData: nil assumeInside: NO];
+
+    // tdf#155092 use tracking areas instead of tracking rectangles
+    // Apparently, the older, tracking rectangles selectors cause
+    // unexpected window resizing upon the first mouse down after the
+    // window has been manually resized so switch to the newer,
+    // tracking areas selectors. Also, the NSTrackingInVisibleRect
+    // option allows us to create one single tracking area that
+    // resizes itself automatically over the lifetime of the view.
+    // Note: for some unknown reason, both NSTrackingMouseMoved and
+    // NSTrackingAssumeInside are necessary options for this fix
+    // to work.
+    NSTrackingArea *pTrackingArea = [[NSTrackingArea alloc] initWithRect: 
[mpNSView bounds] options: ( NSTrackingMouseEnteredAndExited | 
NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingAssumeInside | 
NSTrackingInVisibleRect ) owner: mpNSView userInfo: nil];
+    [mpNSView addTrackingArea: pTrackingArea];
+    [pTrackingArea release];
 
     maSysData.mpNSView = mpNSView;
 
@@ -1832,7 +1844,6 @@ void AquaSalFrame::SetParent( SalFrame* pNewParent )
 
 void AquaSalFrame::UpdateFrameGeometry()
 {
-    bool bFirstTime = (mnTrackingRectTag == 0);
     mbGeometryDidChange = false;
 
     if ( !mpNSWindow )
@@ -1848,7 +1859,7 @@ void AquaSalFrame::UpdateFrameGeometry()
     if( pScreen )
     {
         NSRect aNewScreenRect = [pScreen frame];
-        if (bFirstTime || !NSEqualRects(maScreenRect, aNewScreenRect))
+        if (!NSEqualRects(maScreenRect, aNewScreenRect))
         {
             mbGeometryDidChange = true;
             maScreenRect = aNewScreenRect;
@@ -1857,7 +1868,7 @@ void AquaSalFrame::UpdateFrameGeometry()
         if( pScreens )
         {
             unsigned int nNewDisplayScreenNumber = [pScreens indexOfObject: 
pScreen];
-            if (bFirstTime || maGeometry.screen() != nNewDisplayScreenNumber)
+            if (maGeometry.screen() != nNewDisplayScreenNumber)
             {
                 mbGeometryDidChange = true;
                 maGeometry.setScreen(nNewDisplayScreenNumber);
@@ -1870,22 +1881,17 @@ void AquaSalFrame::UpdateFrameGeometry()
 
     NSRect aTrackRect = { NSZeroPoint, aContentRect.size };
 
-    if (bFirstTime || !NSEqualRects(maTrackingRect, aTrackRect))
+    if (!NSEqualRects(maTrackingRect, aTrackRect))
     {
         mbGeometryDidChange = true;
         maTrackingRect = aTrackRect;
-
-        // release old track rect
-        [mpNSView removeTrackingRect: mnTrackingRectTag];
-        // install the new track rect
-        mnTrackingRectTag = [mpNSView addTrackingRect: aTrackRect owner: 
mpNSView userData: nil assumeInside: NO];
     }
 
     // convert to vcl convention
     CocoaToVCL( aFrameRect );
     CocoaToVCL( aContentRect );
 
-    if (bFirstTime || !NSEqualRects(maContentRect, aContentRect) || 
!NSEqualRects(maFrameRect, aFrameRect))
+    if (!NSEqualRects(maContentRect, aContentRect) || 
!NSEqualRects(maFrameRect, aFrameRect))
     {
         mbGeometryDidChange = true;
 
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index 27c9e773ec4c..c58320558013 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -196,6 +196,26 @@ static NSArray *getMergedAccessibilityChildren(NSArray 
*pDefaultChildren, NSArra
     return pRet;
 }
 
+// Update ImplGetSVData()->mpWinData->mbIsLiveResize and return the old value
+static bool updateWinDataInLiveResize(bool bInLiveResize)
+{
+    bool bRet = false;
+
+    ImplSVData* pSVData = ImplGetSVData();
+    assert( pSVData );
+    if ( pSVData )
+    {
+        bRet = pSVData->mpWinData->mbIsLiveResize;
+        if ( bRet != bInLiveResize )
+        {
+            pSVData->mpWinData->mbIsLiveResize = bInLiveResize;
+            Scheduler::Wakeup();
+        }
+    }
+
+    return bRet;
+}
+
 @interface NSResponder (SalFrameWindow)
 -(BOOL)accessibilityIsIgnored;
 @end
@@ -204,7 +224,6 @@ static NSArray *getMergedAccessibilityChildren(NSArray 
*pDefaultChildren, NSArra
 -(id)initWithSalFrame: (AquaSalFrame*)pFrame
 {
     mDraggingDestinationHandler = nil;
-    mbInLiveResize = NO;
     mbInWindowDidResize = NO;
     mpLiveResizeTimer = nil;
     mpFrame = pFrame;
@@ -387,22 +406,9 @@ static NSArray *getMergedAccessibilityChildren(NSArray 
*pDefaultChildren, NSArra
         mpFrame->CallCallback( SalEvent::Resize, nullptr );
 
         bool bInLiveResize = [self inLiveResize];
-        ImplSVData* pSVData = ImplGetSVData();
-        assert( pSVData );
-        if ( pSVData )
+        bool bOldInLiveResize = updateWinDataInLiveResize(bInLiveResize);
+        if ( bInLiveResize || bOldInLiveResize )
         {
-            const bool bWasLiveResize = pSVData->mpWinData->mbIsLiveResize;
-            if ( bWasLiveResize != bInLiveResize )
-            {
-                pSVData->mpWinData->mbIsLiveResize = bInLiveResize;
-                Scheduler::Wakeup();
-            }
-        }
-
-        if ( bInLiveResize || mbInLiveResize )
-        {
-            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
@@ -441,7 +447,7 @@ static NSArray *getMergedAccessibilityChildren(NSArray 
*pDefaultChildren, NSArra
             [self setMinSize:aMinSize];
             [self setMaxSize:aMaxSize];
 
-            if ( mbInLiveResize )
+            if ( bInLiveResize )
             {
                 // tdf#152703 Force repaint after live resizing ends
                 // Repost this notification so that this selector will be 
called
@@ -2512,6 +2518,16 @@ static NSArray *getMergedAccessibilityChildren(NSArray 
*pDefaultChildren, NSArra
     return [self accessibilityChildren];
 }
 
+-(void)viewWillStartLiveResize
+{
+    updateWinDataInLiveResize(true);
+}
+
+-(void)viewDidEndLiveResize
+{
+    updateWinDataInLiveResize(false);
+}
+
 @end
 
 @implementation SalFrameViewA11yWrapper
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index bf1b11a94ba5..3c98e4f988d2 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -607,7 +607,9 @@ bool AquaSalInstance::DoYield(bool bWait, bool 
bHandleAllCurrentEvents)
 
             [NSApp updateWindows];
 
-            if ( !bHandleAllCurrentEvents || !pEvent || now < [pEvent 
timestamp] )
+            // Related: tdf#155092 keep LibreOffice state closely synched to
+            // the dispatched native event state during live resize.
+            if ( !bHandleAllCurrentEvents || !pEvent || now < [pEvent 
timestamp] || ImplGetSVData()->mpWinData->mbIsLiveResize )
                 break;
             // noelgrandin: I see sporadic hangs on the macos jenkins boxes, 
and the backtrace
             // points to the this loop - let us see if breaking out of here 
after too many
@@ -630,14 +632,16 @@ bool AquaSalInstance::DoYield(bool bWait, bool 
bHandleAllCurrentEvents)
         {
             SolarMutexReleaser aReleaser;
 
-            // attempt to fix macos jenkins hangs - part 3
+            // Related: tdf#155092 don't block during a live resize.
+            // Also, attempt to fix macos jenkins hangs - part 3
             // oox::xls::WorkbookFragment::finalizeImport() calls
             // AquaSalInstance::DoYield() with bWait set to true. But
             // since unit tests generally have no expected user generated
             // events, we can end up blocking and waiting forever so
             // don't block and wait when running unit tests.
+            NSDate *pDate = ( ImplGetSVData()->mpWinData->mbIsLiveResize || 
SalInstance::IsRunningUnitTest() ) ? [NSDate distantPast] : [NSDate 
distantFuture];
             pEvent = [NSApp nextEventMatchingMask: NSEventMaskAny
-                            untilDate: SalInstance::IsRunningUnitTest() ? 
[NSDate distantPast] : [NSDate distantFuture]
+                            untilDate: pDate
                             inMode: NSDefaultRunLoopMode
                             dequeue: YES];
             if( pEvent )

Reply via email to