vcl/inc/osx/salframeview.h | 1 vcl/osx/salframe.cxx | 8 ++++++ vcl/osx/salframeview.mm | 18 ++++++++++++++- vcl/osx/salmenu.cxx | 52 +++++++++++++++++++++++++++++++++++++++++++++ vcl/osx/salnsmenu.mm | 38 ++++++++++++++++++++++++++++++++ vcl/osx/vclnsapp.mm | 32 +++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 2 deletions(-)
New commits: commit 98ca580e910d23bb7933fa39e6907900f9a4b651 Author: Patrick Luby <guibmac...@gmail.com> AuthorDate: Sun Apr 6 12:37:39 2025 -0400 Commit: Patrick Luby <guibomac...@gmail.com> CommitDate: Tue Apr 8 17:43:01 2025 +0200 tdf#165448 Allow macOS to add menu items in LibreOffice windows menu macOS will automatically insert menu items in NSApp's windows menu so set that menu to LibreOffice's windows menu. Note: while this native feature works with document windows, there are two cases where this feature is not available: - The Start Center has no windows menu so none of the menu items that macOS inserts will be inserted. - For some unkown reason, none of the menu items that macOS inserts into the windows menu work if the key window is a native child window of another window. Unfortunately, LibreOffice depends on a dialog window being a native child window of its parent window to mimic native modal dialogs so hide all the those menu items when a native child window has focus. Change-Id: Ie73711be479ef71d6aa62e6e8651c248afb8c252 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183762 Tested-by: Jenkins Reviewed-by: Patrick Luby <guibomac...@gmail.com> diff --git a/vcl/inc/osx/salframeview.h b/vcl/inc/osx/salframeview.h index db53b2195dee..420e8a25b324 100644 --- a/vcl/inc/osx/salframeview.h +++ b/vcl/inc/osx/salframeview.h @@ -30,6 +30,7 @@ enum class SalEvent; BOOL mbInWindowDidResize; NSTimer* mpLiveResizeTimer; NSTimer* mpResetParentWindowTimer; + BOOL mbInSetFrame; } -(id)initWithSalFrame: (AquaSalFrame*)pFrame; -(void)clearLiveResizeTimer; diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx index 20d1efd65b25..636a07a6a152 100644 --- a/vcl/osx/salframe.cxx +++ b/vcl/osx/salframe.cxx @@ -554,7 +554,13 @@ void AquaSalFrame::Show(bool bVisible, bool bNoActivate) // Ordering out a native full screen window would leave the // application in a state where there is no Desktop and both // the menubar and the Dock are hidden. - [mpNSWindow close]; + // Related: tdf#165448 delay closing the window + // When a floating window such as the dropdown list in the + // font combobox is open when selecting any of the menu items + // inserted by macOS in the windows menu, the parent window + // will be hidden. So delay closing the window until the next + // pass through the native event loop. + [mpNSWindow performSelector: @selector(close) withObject: nil afterDelay: 0.01f]; } } diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm index 6411714f182a..969a09771db3 100644 --- a/vcl/osx/salframeview.mm +++ b/vcl/osx/salframeview.mm @@ -346,6 +346,7 @@ static void updateWindowCollectionBehavior( const AquaSalFrame *pFrame ) mbInWindowDidResize = NO; mpLiveResizeTimer = nil; mpResetParentWindowTimer = nil; + mbInSetFrame = false; mpFrame = pFrame; const SalFrameGeometry rFrameGeometry = pFrame->GetUnmirroredGeometry(); NSRect aRect = { { static_cast<CGFloat>(rFrameGeometry.x()), static_cast<CGFloat>(rFrameGeometry.y()) }, @@ -999,7 +1000,15 @@ static void updateWindowCollectionBehavior( const AquaSalFrame *pFrame ) // -[super constrainFrameRect:toScreen:] shrinks the window frame to // allow room for the menubar if the window is on the main screen. So, // force the return value to match the frame that LibreOffice expects. - if( AquaSalFrame::isAlive( mpFrame) && mpFrame->mbInternalFullScreen && !NSIsEmptyRect( mpFrame->maInternalFullScreenExpectedRect ) ) + // Related: tdf#165448 skip fix for menu items inserted by macOS + // If the window is in LibreOffice's internal full screen mode and + // any of the menu items that macOS inserts into the windows menu + // is selected, the frame size will be changed without calling + // -[SalFrameWindow setFrame:display:]. So only use the fix for + // tdf#161623 when the LibreOffice code explicitly resizes the frame. + // Otherwise, selecting any of the menu items inserted by macOS will + // cause the window to snap back to full screen size. + if( mbInSetFrame && AquaSalFrame::isAlive( mpFrame ) && mpFrame->mbInternalFullScreen && !NSIsEmptyRect( mpFrame->maInternalFullScreenExpectedRect ) ) aRet = mpFrame->maInternalFullScreenExpectedRect; return aRet; @@ -1019,6 +1028,13 @@ static void updateWindowCollectionBehavior( const AquaSalFrame *pFrame ) return nil; } +-(void)setFrame: (NSRect)aFrameRect display: (BOOL)bFlag +{ + mbInSetFrame = true; + [super setFrame: aFrameRect display: bFlag]; + mbInSetFrame = false; +} + @end @implementation SalFrameView diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx index 8200af5663a9..3e688fef0038 100644 --- a/vcl/osx/salmenu.cxx +++ b/vcl/osx/salmenu.cxx @@ -336,9 +336,49 @@ int AquaSalMenu::getItemIndexByPos( sal_uInt16 nPos ) const { int nIndex = 0; if( nPos == MENU_APPEND ) + { nIndex = [mpMenu numberOfItems]; + } else + { nIndex = sal::static_int_cast<int>( mbMenuBar ? nPos+1 : nPos ); + + // Related: tdf#165448 adjust index for menu items inserted by macOS + if( mpMenu == [NSApp windowsMenu] ) + { + int nItems = [mpMenu numberOfItems]; + bool bLastItemIsNative = false; + for( int n = mbMenuBar ? 1 : 0; n < nItems; n++ ) + { + NSMenuItem* pItem = [mpMenu itemAtIndex: n]; + if( [pItem isKindOfClass: [SalNSMenuItem class]] ) + { + bLastItemIsNative = false; + if( n == nIndex ) + break; + } + else if( [pItem isSeparatorItem] ) + { + if ( bLastItemIsNative ) + { + // Assume that macOS does not insert more than one + // separater item in a row + bLastItemIsNative = false; + nIndex++; + } + else if( n == nIndex ) + { + break; + } + } + else + { + bLastItemIsNative = true; + nIndex++; + } + } + } + } return nIndex; } @@ -373,6 +413,18 @@ void AquaSalMenu::setMainMenu() { NSMenuItem* pItem = maItems[i]->mpMenuItem; [mpMenu insertItem: pItem atIndex: i+1]; + + // tdf#165448 Allow macOS to add menu items in LibreOffice windows menu + // macOS will automatically insert menu items in NSApp's + // windows menu so set that menu to LibreOffice's windows menu. + if( maItems[i]->mpVCLMenu && maItems[i]->mpVCLMenu->GetItemCommand( maItems[i]->mnId ) == u".uno:WindowList"_ustr ) + { + // Avoid macOS inserting duplicate menu items in the + // windows menu + NSMenu *pWindowsMenu = [pItem submenu]; + if( [NSApp windowsMenu] != pWindowsMenu ) + [NSApp setWindowsMenu: pWindowsMenu]; + } } pCurrentMenuBar = this; diff --git a/vcl/osx/salnsmenu.mm b/vcl/osx/salnsmenu.mm index e426d682acd2..19a91bf6ee96 100644 --- a/vcl/osx/salnsmenu.mm +++ b/vcl/osx/salnsmenu.mm @@ -95,6 +95,44 @@ if( mpMenu ) { + // Related: tdf#165448 hide menu items inserted by macOS if child window + // For some unkown reason, none of the menu items that macOS inserts + // into the windows menu work if the key window is a native child + // window of another window. Unfortunately, LibreOffice depends on + // a dialog window being a native child window of its parent window + // to mimic native modal dialogs so hide all the those menu items. + if( pMenu && pMenu == [NSApp windowsMenu] ) + { + NSWindow *pKeyWin = [NSApp keyWindow]; + bool bHidden = pKeyWin && [pKeyWin parentWindow]; + + int nItems = [pMenu numberOfItems]; + bool bLastItemIsNative = false; + for( int n = mpMenu->mbMenuBar ? 1 : 0; n < nItems; n++ ) + { + NSMenuItem* pItem = [pMenu itemAtIndex: n]; + if( [pItem isKindOfClass: [SalNSMenuItem class]] ) + { + bLastItemIsNative = false; + } + else if( [pItem isSeparatorItem] ) + { + if ( bLastItemIsNative ) + { + // Assume that macOS does not insert more than one + // separater item in a row + bLastItemIsNative = false; + [pItem setHidden: bHidden]; + } + } + else + { + bLastItemIsNative = true; + [pItem setHidden: bHidden]; + } + } + } + const AquaSalFrame* pFrame = mpMenu->getFrame(); if( pFrame && AquaSalFrame::isAlive( pFrame ) ) { diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm index c18391f468ac..399134a361e4 100644 --- a/vcl/osx/vclnsapp.mm +++ b/vcl/osx/vclnsapp.mm @@ -496,6 +496,38 @@ return nil; } +-(void)addWindowsItem: (NSWindow *)pWindow title: (NSString *)pString filename: (BOOL)bFilename +{ + // Related: tdf#165448 stop macOS from creating its own file list in the + // windows menu + (void)pWindow; + (void)pString; + (void)bFilename; +} + +-(void)changeWindowsItem: (NSWindow *)pWindow title: (NSString *)pString filename: (BOOL)bFilename +{ + // Related: tdf#165448 stop macOS from creating its own file list in the + // windows menu + (void)pWindow; + (void)pString; + (void)bFilename; +} + +-(void)removeWindowsItem: (NSWindow *)pWindow +{ + // Related: tdf#165448 stop macOS from creating its own file list in the + // windows menu + (void)pWindow; +} + +-(void)updateWindowsItem: (NSWindow *)pWindow +{ + // Related: tdf#165448 stop macOS from creating its own file list in the + // windows menu + (void)pWindow; +} + @end /* vim:set shiftwidth=4 softtabstop=4 expandtab: */