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 )