Mercurial > sdl-ios-xcode
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 |