summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Luby <plubius@libreoffice.org>2023-11-28 09:34:07 -0500
committerXisco Fauli <xiscofauli@libreoffice.org>2023-11-30 13:08:31 +0100
commitfcccf586ba405008e4e3507f04fcd57bb2f18719 (patch)
tree7b810b77d489a55dd48321c6ee767674c827dae2
parent7d79afebef281657a58cba065af0c5ba79a4e9e1 (diff)
tdf#155092 don't dispatch left mouse up events during live resizing
If this is a left mouse up event, dispatching this event will trigger tdf#155092 to occur in the next mouse down event. So do not dispatch this event and push it back onto the front of the event queue so no more events will be dispatched until live resizing ends. Surprisingly, live resizing appears to end in the next mouse down event. Also, include commit 54da842381ccb554d3cadc876f23cf183d21bf1a which, while it failed to fix tdf#155092, the switch to using the newer tracking areas selectors instead of the older tracking rectangles selectors still gives more control over mouse entered, mouse exited, and mouse moved events. Lastly, include commit 3b942f6efa8ffd11374031e4af8dbcb48a8962d1 which fixes some vertical shifing of the window's content while live resizing with Skia disabled. Change-Id: Ie93ed496e1f0e2a1711284ab205c6b245f71647c Reviewed-by: Patrick Luby <plubius@libreoffice.org> (cherry picked from commit 8a5da079592377cf69735973d922fc19e8ac763d) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160029 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--vcl/inc/osx/salframe.h1
-rw-r--r--vcl/inc/osx/salframeview.h3
-rw-r--r--vcl/osx/salframe.cxx34
-rw-r--r--vcl/osx/salframeview.mm58
-rw-r--r--vcl/osx/salgdiutils.cxx16
-rw-r--r--vcl/osx/salinst.cxx26
6 files changed, 89 insertions, 49 deletions
diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h
index 950c8d6345e1..806b75178683 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..2b1a3f9baaed 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;
}
@@ -46,6 +45,8 @@ enum class SalEvent;
-(void)windowDidDeminiaturize: (NSNotification*)pNotification;
-(BOOL)windowShouldClose: (NSNotification*)pNotification;
-(void)windowDidChangeBackingProperties:(NSNotification *)pNotification;
+-(void)windowWillStartLiveResize:(NSNotification *)pNotification;
+-(void)windowDidEndLiveResize:(NSNotification *)pNotification;
//-(void)willEncodeRestorableState:(NSCoder*)pCoderState;
//-(void)didDecodeRestorableState:(NSCoder*)pCoderState;
//-(void)windowWillEnterVersionBrowser:(NSNotification*)pNotification;
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index 028e10cfb70d..1d7f0af10b60 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;
@@ -1831,7 +1843,6 @@ void AquaSalFrame::SetParent( SalFrame* pNewParent )
void AquaSalFrame::UpdateFrameGeometry()
{
- bool bFirstTime = (mnTrackingRectTag == 0);
mbGeometryDidChange = false;
if ( !mpNSWindow )
@@ -1847,7 +1858,7 @@ void AquaSalFrame::UpdateFrameGeometry()
if( pScreen )
{
NSRect aNewScreenRect = [pScreen frame];
- if (bFirstTime || !NSEqualRects(maScreenRect, aNewScreenRect))
+ if (!NSEqualRects(maScreenRect, aNewScreenRect))
{
mbGeometryDidChange = true;
maScreenRect = aNewScreenRect;
@@ -1856,7 +1867,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);
@@ -1869,22 +1880,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 68681ba495c0..5cf9fb96ca13 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -194,6 +194,21 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
return pRet;
}
+// Update ImplGetSVData()->mpWinData->mbIsLiveResize
+static void updateWinDataInLiveResize(bool bInLiveResize)
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ assert( pSVData );
+ if ( pSVData )
+ {
+ if ( pSVData->mpWinData->mbIsLiveResize != bInLiveResize )
+ {
+ pSVData->mpWinData->mbIsLiveResize = bInLiveResize;
+ Scheduler::Wakeup();
+ }
+ }
+}
+
@interface NSResponder (SalFrameWindow)
-(BOOL)accessibilityIsIgnored;
@end
@@ -202,7 +217,6 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
-(id)initWithSalFrame: (AquaSalFrame*)pFrame
{
mDraggingDestinationHandler = nil;
- mbInLiveResize = NO;
mbInWindowDidResize = NO;
mpLiveResizeTimer = nil;
mpFrame = pFrame;
@@ -384,23 +398,9 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
mpFrame->UpdateFrameGeometry();
mpFrame->CallCallback( SalEvent::Resize, nullptr );
- bool bInLiveResize = [self inLiveResize];
- ImplSVData* pSVData = ImplGetSVData();
- assert( pSVData );
- if ( pSVData )
- {
- const bool bWasLiveResize = pSVData->mpWinData->mbIsLiveResize;
- if ( bWasLiveResize != bInLiveResize )
- {
- pSVData->mpWinData->mbIsLiveResize = bInLiveResize;
- Scheduler::Wakeup();
- }
- }
-
- if ( bInLiveResize || mbInLiveResize )
+ updateWinDataInLiveResize( [self inLiveResize] );
+ if ( ImplGetSVData()->mpWinData->mbIsLiveResize )
{
- 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
@@ -439,7 +439,7 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
[self setMinSize:aMinSize];
[self setMaxSize:aMaxSize];
- if ( mbInLiveResize )
+ if ( ImplGetSVData()->mpWinData->mbIsLiveResize )
{
// tdf#152703 Force repaint after live resizing ends
// Repost this notification so that this selector will be called
@@ -560,6 +560,20 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
#endif
}
+-(void)windowWillStartLiveResize:(NSNotification *)pNotification
+{
+ SolarMutexGuard aGuard;
+
+ updateWinDataInLiveResize(true);
+}
+
+-(void)windowDidEndLiveResize:(NSNotification *)pNotification
+{
+ SolarMutexGuard aGuard;
+
+ updateWinDataInLiveResize(false);
+}
+
-(void)dockMenuItemTriggered: (id)sender
{
(void)sender;
@@ -761,13 +775,7 @@ static NSArray *getMergedAccessibilityChildren(NSArray *pDefaultChildren, NSArra
if (!mpFrame || !AquaSalFrame::isAlive(mpFrame))
return;
- const bool bIsLiveResize = [self inLiveResize];
- const bool bWasLiveResize = pSVData->mpWinData->mbIsLiveResize;
- if (bWasLiveResize != bIsLiveResize)
- {
- pSVData->mpWinData->mbIsLiveResize = bIsLiveResize;
- Scheduler::Wakeup();
- }
+ updateWinDataInLiveResize([self inLiveResize]);
AquaSalGraphics* pGraphics = mpFrame->mpGraphics;
if (pGraphics)
diff --git a/vcl/osx/salgdiutils.cxx b/vcl/osx/salgdiutils.cxx
index 7e4bd23baac9..a9445293211c 100644
--- a/vcl/osx/salgdiutils.cxx
+++ b/vcl/osx/salgdiutils.cxx
@@ -311,6 +311,22 @@ void AquaSalGraphics::UpdateWindow( NSRect& )
rCGContextHolder.saveState();
+ // Related: tdf#155092 translate Y coordinate for height differences
+ // When in live resize, the NSView's height may have changed before
+ // the CGLayer has been resized. This causes the CGLayer's content
+ // to be drawn just above or below the top left corner of the view
+ // so translate the Y coordinate by any difference between the
+ // NSView's height and the CGLayer's height.
+ NSView *pView = maShared.mpFrame->mpNSView;
+ if (pView)
+ {
+ // Use the NSView's bounds, not its frame, to properly handle
+ // any rotation and/or scaling that might have been already
+ // applied to the view
+ CGFloat fTranslateY = [pView bounds].size.height - maShared.maLayer.getSizePoints().height;
+ CGContextTranslateCTM(rCGContextHolder.get(), 0, fTranslateY);
+ }
+
CGMutablePathRef rClip = maShared.mpFrame->getClipPath();
if (rClip)
{
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index be33e8ac9902..d7b85b1c23f6 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -555,13 +555,6 @@ static bool isWakeupEvent( NSEvent *pEvent )
bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
{
- // Related: tdf#152703 Eliminate potential blocking during live resize
- // Some events and timers call Application::Reschedule() or
- // Application::Yield() so don't block and wait for events when a
- // window is in live resize
- if ( ImplGetSVData()->mpWinData->mbIsLiveResize )
- bWait = false;
-
// ensure that the per thread autorelease pool is top level and
// will therefore not be destroyed by cocoa implicitly
SalData::ensureThreadAutoreleasePool();
@@ -598,6 +591,19 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
dequeue: YES];
if( pEvent )
{
+ // tdf#155092 don't dispatch left mouse up events during live resizing
+ // If this is a left mouse up event, dispatching this event
+ // will trigger tdf#155092 to occur in the next mouse down
+ // event. So do not dispatch this event and push it back onto
+ // the front of the event queue so no more events will be
+ // dispatched until live resizing ends. Surprisingly, live
+ // resizing appears to end in the next mouse down event.
+ if ( ImplGetSVData()->mpWinData->mbIsLiveResize && [pEvent type] == NSEventTypeLeftMouseUp )
+ {
+ [NSApp postEvent: pEvent atStart: YES];
+ return false;
+ }
+
[NSApp sendEvent: pEvent];
if ( isWakeupEvent( pEvent ) )
continue;
@@ -619,7 +625,11 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents)
}
// if we had no event yet, wait for one if requested
- if( bWait && ! bHadEvent )
+ // Related: tdf#152703 Eliminate potential blocking during live resize
+ // Some events and timers call Application::Reschedule() or
+ // Application::Yield() so don't block and wait for events when a
+ // window is in live resize
+ if( bWait && ! bHadEvent && !ImplGetSVData()->mpWinData->mbIsLiveResize )
{
SolarMutexReleaser aReleaser;