comparison src/main/macosx/SDLMain.m @ 957:217f119a19a0

Date: Thu, 2 Sep 2004 19:35:51 +0200 From: Max Horn Subject: [Patch]: Improved menu code for SDLMain.m the attached patch improves the menu setup for SDL apps built without a .nib file. On 10.3, the application menus are empty with the current SDL CVS version; after this patch, a proper app & window menu, with "About", "Hide", "Quit", "Minimize" etc. entries are visible, just like with the .nib enabled applications. This *should* work on 10.2 and even 10.1, but I can't guarantee it, so somebody should test there, ideally. I also changed the way setupWorkingDirectory works by making use of the Bundle APIs, that results in (IMO) less hackish code. Finally, I added some "static" keywords to ensure that certain local functions are not exported (that's just a paranoia change, I guess: never pollute linker namespaces if you can avoid it).
author Sam Lantinga <slouken@libsdl.org>
date Fri, 17 Sep 2004 13:28:12 +0000
parents a7129c0083f4
children d390f9bd6b1c
comparison
equal deleted inserted replaced
956:4263beff9e38 957:217f119a19a0
31 31
32 static int gArgc; 32 static int gArgc;
33 static char **gArgv; 33 static char **gArgv;
34 static BOOL gFinderLaunch; 34 static BOOL gFinderLaunch;
35 35
36 static NSString *getApplicationName(void)
37 {
38 NSDictionary *dict;
39 NSString *appName = 0;
40
41 /* Determine the application name */
42 dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
43 if (dict)
44 appName = [dict objectForKey: @"CFBundleName"];
45
46 if (![appName length])
47 appName = [[NSProcessInfo processInfo] processName];
48
49 return appName;
50 }
51
36 #if SDL_USE_NIB_FILE 52 #if SDL_USE_NIB_FILE
37 /* A helper category for NSString */ 53 /* A helper category for NSString */
38 @interface NSString (ReplaceSubString) 54 @interface NSString (ReplaceSubString)
39 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; 55 - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString;
40 @end 56 @end
41 #else
42 /* An internal Apple class used to setup Apple menus */
43 @interface NSAppleMenuController:NSObject {}
44 - (void)controlMenu:(NSMenu *)aMenu;
45 @end
46 #endif 57 #endif
47 58
48 @interface SDLApplication : NSApplication 59 @interface SDLApplication : NSApplication
49 @end 60 @end
50 61
57 event.type = SDL_QUIT; 68 event.type = SDL_QUIT;
58 SDL_PushEvent(&event); 69 SDL_PushEvent(&event);
59 } 70 }
60 @end 71 @end
61 72
62
63 /* The main class of the application, the application's delegate */ 73 /* The main class of the application, the application's delegate */
64 @implementation SDLMain 74 @implementation SDLMain
65 75
66 /* Set the working directory to the .app's parent directory */ 76 /* Set the working directory to the .app's parent directory */
67 - (void) setupWorkingDirectory:(BOOL)shouldChdir 77 - (void) setupWorkingDirectory:(BOOL)shouldChdir
68 { 78 {
69
70 if (shouldChdir) 79 if (shouldChdir)
71 { 80 {
72 char parentdir[MAXPATHLEN]; 81 char parentdir[MAXPATHLEN];
73 char *c; 82 CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
74 83 CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
75 strncpy ( parentdir, gArgv[0], sizeof(parentdir) ); 84 if (CFURLGetFileSystemRepresentation(url2, true, parentdir, MAXPATHLEN)) {
76 c = (char*) parentdir; 85 assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
77 86 }
78 while (*c != '\0') /* go to end */ 87 CFRelease(url);
79 c++; 88 CFRelease(url2);
80 89 }
81 while (*c != '/') /* back up to parent */ 90
82 c--;
83
84 *c++ = '\0'; /* cut off last part (binary name) */
85
86 assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
87 assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
88 }
89 } 91 }
90 92
91 #if SDL_USE_NIB_FILE 93 #if SDL_USE_NIB_FILE
92 94
93 /* Fix menu to contain the real app name instead of "SDL App" */ 95 /* Fix menu to contain the real app name instead of "SDL App" */
113 [ aMenu sizeToFit ]; 115 [ aMenu sizeToFit ];
114 } 116 }
115 117
116 #else 118 #else
117 119
118 void setupAppleMenu(void) 120 static void setApplicationMenu(void)
119 { 121 {
120 /* warning: this code is very odd */ 122 /* warning: this code is very odd */
121 NSAppleMenuController *appleMenuController;
122 NSMenu *appleMenu; 123 NSMenu *appleMenu;
123 NSMenuItem *appleMenuItem; 124 NSMenuItem *menuItem;
124 125 NSString *title;
125 appleMenuController = [[NSAppleMenuController alloc] init]; 126 NSString *appName;
127
128 appName = getApplicationName();
126 appleMenu = [[NSMenu alloc] initWithTitle:@""]; 129 appleMenu = [[NSMenu alloc] initWithTitle:@""];
127 appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; 130
128 131 /* Add menu items */
129 [appleMenuItem setSubmenu:appleMenu]; 132 title = [@"About " stringByAppendingString:appName];
130 133 [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
131 /* yes, we do need to add it and then remove it -- 134
132 if you don't add it, it doesn't get displayed 135 [appleMenu addItem:[NSMenuItem separatorItem]];
133 if you don't remove it, you have an extra, titleless item in the menubar 136
134 when you remove it, it appears to stick around 137 title = [@"Hide " stringByAppendingString:appName];
135 very, very odd */ 138 [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
136 [[NSApp mainMenu] addItem:appleMenuItem]; 139
137 [appleMenuController controlMenu:appleMenu]; 140 menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
138 [[NSApp mainMenu] removeItem:appleMenuItem]; 141 [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
142
143 [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
144
145 [appleMenu addItem:[NSMenuItem separatorItem]];
146
147 title = [@"Quit " stringByAppendingString:appName];
148 [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
149
150
151 /* Put menu into the menubar */
152 menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
153 [menuItem setSubmenu:appleMenu];
154 [[NSApp mainMenu] addItem:menuItem];
155
156 /* Tell the application object that this is now the application menu */
157 [NSApp setAppleMenu:appleMenu];
158
159 /* Finally give up our references to the objects */
139 [appleMenu release]; 160 [appleMenu release];
140 [appleMenuItem release]; 161 [menuItem release];
141 } 162 }
142 163
143 /* Create a window menu */ 164 /* Create a window menu */
144 void setupWindowMenu(void) 165 static void setupWindowMenu(void)
145 { 166 {
146 NSMenu *windowMenu; 167 NSMenu *windowMenu;
147 NSMenuItem *windowMenuItem; 168 NSMenuItem *windowMenuItem;
148 NSMenuItem *menuItem; 169 NSMenuItem *menuItem;
149
150 170
151 windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; 171 windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
152 172
153 /* "Minimize" item */ 173 /* "Minimize" item */
154 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; 174 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
167 [windowMenu release]; 187 [windowMenu release];
168 [windowMenuItem release]; 188 [windowMenuItem release];
169 } 189 }
170 190
171 /* Replacement for NSApplicationMain */ 191 /* Replacement for NSApplicationMain */
172 void CustomApplicationMain (argc, argv) 192 static void CustomApplicationMain (argc, argv)
173 { 193 {
174 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 194 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
175 SDLMain *sdlMain; 195 SDLMain *sdlMain;
176 196
177 /* Ensure the application object is initialised */ 197 /* Ensure the application object is initialised */
188 } 208 }
189 #endif /* SDL_USE_CPS */ 209 #endif /* SDL_USE_CPS */
190 210
191 /* Set up the menubar */ 211 /* Set up the menubar */
192 [NSApp setMainMenu:[[NSMenu alloc] init]]; 212 [NSApp setMainMenu:[[NSMenu alloc] init]];
193 setupAppleMenu(); 213 setApplicationMenu();
194 setupWindowMenu(); 214 setupWindowMenu();
195 215
196 /* Create SDLMain and make it the app delegate */ 216 /* Create SDLMain and make it the app delegate */
197 sdlMain = [[SDLMain alloc] init]; 217 sdlMain = [[SDLMain alloc] init];
198 [NSApp setDelegate:sdlMain]; 218 [NSApp setDelegate:sdlMain];
199 219
200 /* Start the main event loop */ 220 /* Start the main event loop */
214 /* Set the working directory to the .app's parent directory */ 234 /* Set the working directory to the .app's parent directory */
215 [self setupWorkingDirectory:gFinderLaunch]; 235 [self setupWorkingDirectory:gFinderLaunch];
216 236
217 #if SDL_USE_NIB_FILE 237 #if SDL_USE_NIB_FILE
218 /* Set the main menu to contain the real app name instead of "SDL App" */ 238 /* Set the main menu to contain the real app name instead of "SDL App" */
219 [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]]; 239 [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()];
220 #endif 240 #endif
221 241
222 /* Hand off to main application code */ 242 /* Hand off to main application code */
223 status = SDL_main (gArgc, gArgv); 243 status = SDL_main (gArgc, gArgv);
224 244
282 int i; 302 int i;
283 303
284 /* This is passed if we are launched by double-clicking */ 304 /* This is passed if we are launched by double-clicking */
285 if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { 305 if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
286 gArgc = 1; 306 gArgc = 1;
287 gFinderLaunch = YES; 307 gFinderLaunch = YES;
288 } else { 308 } else {
289 gArgc = argc; 309 gArgc = argc;
290 gFinderLaunch = NO; 310 gFinderLaunch = NO;
291 } 311 }
292 gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1)); 312 gArgv = argv;
293 assert (gArgv != NULL);
294 for (i = 0; i < gArgc; i++)
295 gArgv[i] = argv[i];
296 gArgv[i] = NULL;
297 313
298 #if SDL_USE_NIB_FILE 314 #if SDL_USE_NIB_FILE
299 [SDLApplication poseAsClass:[NSApplication class]]; 315 [SDLApplication poseAsClass:[NSApplication class]];
300 NSApplicationMain (argc, argv); 316 NSApplicationMain (argc, argv);
301 #else 317 #else