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: */

Reply via email to