vcl/inc/osx/salframeview.h | 4 +++ vcl/osx/salframeview.mm | 53 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
New commits: commit 633fad32611e39620218319327428050405a6b1a Author: Patrick Luby <guibmac...@gmail.com> AuthorDate: Mon Oct 14 18:26:27 2024 -0400 Commit: Patrick Luby <guibomac...@gmail.com> CommitDate: Tue Oct 15 13:32:13 2024 +0200 Stop hiding of child windows when dragged to a different screen LibreOffice sets all dialog windows as a native child window of its related document window in order to force the dialog windows to always remain in front of their releated document window. However, for some unknown reason, if a native child window is dragged to a different screen than its native parent window, macOS will hide the native child window when the drag has ended. So, once the current drag has finished, unattach and reattach the native child window to its native parent window. This should cause macOS to force the native child window to jump back to the same screen as its native parent window. Change-Id: Ic859a44f4a0e113146f06cc5d311faf15b9c38dc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174914 Reviewed-by: Patrick Luby <guibomac...@gmail.com> Tested-by: Jenkins diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h index 2b1a3f9baaed..dec2f03a42f3 100644 --- a/vcl/inc/osx/salframeview.h +++ b/vcl/inc/osx/salframeview.h @@ -30,9 +30,11 @@ enum class SalEvent; id mDraggingDestinationHandler; BOOL mbInWindowDidResize; NSTimer* mpLiveResizeTimer; + NSTimer* mpResetParentWindowTimer; } -(id)initWithSalFrame: (AquaSalFrame*)pFrame; -(void)clearLiveResizeTimer; +-(void)clearResetParentWindowTimer; -(void)dealloc; -(BOOL)canBecomeKeyWindow; -(void)displayIfNeeded; @@ -80,6 +82,8 @@ enum class SalEvent; -(BOOL)accessibilityIsIgnored; -(BOOL)isAccessibilityElement; +-(void)resetParentWindow; + @end @interface SalFrameView : NSView <NSTextInputClient> diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm index c96a71e1f2af..8345500ffff9 100644 --- a/vcl/osx/salframeview.mm +++ b/vcl/osx/salframeview.mm @@ -222,6 +222,7 @@ static void updateWinDataInLiveResize(bool bInLiveResize) mDraggingDestinationHandler = nil; mbInWindowDidResize = NO; mpLiveResizeTimer = nil; + mpResetParentWindowTimer = nil; mpFrame = pFrame; const SalFrameGeometry& rFrameGeometry = pFrame->GetUnmirroredGeometry(); NSRect aRect = { { static_cast<CGFloat>(rFrameGeometry.x()), static_cast<CGFloat>(rFrameGeometry.y()) }, @@ -273,9 +274,20 @@ static void updateWinDataInLiveResize(bool bInLiveResize) } } +-(void)clearResetParentWindowTimer +{ + if ( mpResetParentWindowTimer ) + { + [mpResetParentWindowTimer invalidate]; + [mpResetParentWindowTimer release]; + mpResetParentWindowTimer = nil; + } +} + -(void)dealloc { [self clearLiveResizeTimer]; + [self clearResetParentWindowTimer]; [super dealloc]; } @@ -374,6 +386,18 @@ static void updateWinDataInLiveResize(bool bInLiveResize) if( mpFrame && AquaSalFrame::isAlive( mpFrame ) ) mpFrame->screenParametersChanged(); + + // Start timer to handle hiding of native child windows that have been + // dragged to a different screen. + if( !mpResetParentWindowTimer ) + { + mpResetParentWindowTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1f target: self selector: @selector(resetParentWindow) userInfo: nil repeats: YES]; + if( mpResetParentWindowTimer ) + { + [mpResetParentWindowTimer retain]; + [[NSRunLoop currentRunLoop] addTimer: mpResetParentWindowTimer forMode: NSEventTrackingRunLoopMode]; + } + } } -(void)windowDidMove: (NSNotification*)pNotification @@ -693,6 +717,35 @@ static void updateWinDataInLiveResize(bool bInLiveResize) [self windowDidResize:[pTimer userInfo]]; } +-(void)resetParentWindow +{ + // Wait until the left mouse button has been released. Otherwise + // the code below will cause native child windows to flicker while + // dragging the window in a different screen than its parent window. + if( [NSEvent pressedMouseButtons] & 0x1 ) + return; + + // Stop hiding of child windows when dragged to a different screen + // LibreOffice sets all dialog windows as a native child window of + // its related document window in order to force the dialog windows + // to always remain in front of their releated document window. + // However, for some unknown reason, if a native child window is + // dragged to a different screen than its native parent window, + // macOS will hide the native child window when the drag has ended. + // So, once the current drag has finished, unattach and reattach + // the native child window to its native parent window. This should + // cause macOS to force the native child window to jump back to the + // same screen as its native parent window. + NSWindow *pParentWindow = [self parentWindow]; + if( pParentWindow && [pParentWindow screen] != [self screen] ) + { + [pParentWindow removeChildWindow: self]; + [pParentWindow addChildWindow: self ordered: NSWindowAbove]; + } + + [self clearResetParentWindowTimer]; +} + @end @implementation SalFrameView