Commit 7a3ae590377a3991ff83e43308853e4171ec08e0

Sam Lantinga 2019-12-03T07:12:55

Fixed bug 4877 - Add support for loading menus from a nib/xib instead of building a hardcoded minimum set Eric Shepherd Currently, SDL on Cocoa macOS creates a rudimentary menu bar programmatically if none is already present when the app is registered during setup. SDL could be much more easily and flexibly used on macOS if upon finding that no menus are currently in place, it first looked for the application's main menu nib or xib file and, if found, loaded that instead of programmatically building the menus. This would then let developers simply drop in a nib file with a menu bar defined in it and it would be installed and used automatically. Attached is a patch that does just this. It changes the SDL_cocoaevents.m file to: * In Cocoa_RegisterApp(), before calling CreateApplicationMenus(), it calls a new function, LoadMainMenuNibIfAvailable(), which attempts to load and install the main menu nib file, using the nib name fetched from the Info.plist file. If that succeeds, LoadMainMenuNibIfAvailable() returns true; otherwise false. * If LMMNIA() returns false, CreateApplicationMenus() is called to programmatically build the menus as before. * Otherwise, we're done, and using the menus from the nib/xib file! I made these changes to support a project I'm working on, and felt they were useful enough to be worth offering them for uplift. They should have zero impact on existing projects' behavior, but make Cocoa SDL development miles easier.

diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m
index 1b76474..a33bbce 100644
--- a/src/video/cocoa/SDL_cocoaevents.m
+++ b/src/video/cocoa/SDL_cocoaevents.m
@@ -267,6 +267,25 @@ GetApplicationName(void)
     return appName;
 }
 
+static bool
+LoadMainMenuNibIfAvailable(void)
+{
+    NSDictionary *infoDict;
+    NSString *mainNibFileName;
+    bool success = false;
+    
+    infoDict = [[NSBundle mainBundle] infoDictionary];
+    if (infoDict) {
+        mainNibFileName = [infoDict valueForKey:@"NSMainNibFile"];
+        
+        if (mainNibFileName) {
+            success = [[NSBundle mainBundle] loadNibNamed:mainNibFileName owner:[NSApplication sharedApplication] topLevelObjects:nil];
+        }
+    }
+    
+    return success;
+}
+
 static void
 CreateApplicationMenus(void)
 {
@@ -281,7 +300,7 @@ CreateApplicationMenus(void)
     if (NSApp == nil) {
         return;
     }
-
+    
     mainMenu = [[NSMenu alloc] init];
 
     /* Create the main menu bar */
@@ -385,8 +404,17 @@ Cocoa_RegisterApp(void)
             [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
         }
 
+        /* If there aren't already menus in place, look to see if there's
+         * a nib we should use. If not, then manually create the basic
+         * menus we meed.
+         */
         if ([NSApp mainMenu] == nil) {
-            CreateApplicationMenus();
+            bool nibLoaded;
+            
+            nibLoaded = LoadMainMenuNibIfAvailable();
+            if (!nibLoaded) {
+                CreateApplicationMenus();
+            }
         }
         [NSApp finishLaunching];
         if ([NSApp delegate]) {