godot_osx.mm 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*************************************************************************/
  2. /* godot_osx.mm */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include <sys/param.h> /* for MAXPATHLEN */
  30. #include <unistd.h>
  31. #include "godot_osx.h"
  32. /* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
  33. but the method still is there and works. To avoid warnings, we declare
  34. it ourselves here. */
  35. @interface NSApplication()
  36. - (void)setAppleMenu:(NSMenu *)menu;
  37. @end
  38. static int global_argc;
  39. static char **global_argv;
  40. static BOOL gCalledAppMainline = FALSE;
  41. static NSString *getApplicationName(void)
  42. {
  43. const NSDictionary *dict;
  44. NSString *appName = 0;
  45. /* Determine the application name */
  46. dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
  47. if (dict)
  48. appName = [dict objectForKey: @"CFBundleName"];
  49. if (![appName length])
  50. appName = [[NSProcessInfo processInfo] processName];
  51. return appName;
  52. }
  53. /* The main class of the application, the application's delegate */
  54. @implementation GodotMain
  55. static void setApplicationMenu(void)
  56. {
  57. /* warning: this code is very odd */
  58. NSMenu *appleMenu;
  59. NSMenuItem *menuItem;
  60. NSString *title;
  61. NSString *appName;
  62. appName = getApplicationName();
  63. appleMenu = [[NSMenu alloc] initWithTitle:@""];
  64. /* Add menu items */
  65. title = [@"About " stringByAppendingString:appName];
  66. [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
  67. [appleMenu addItem:[NSMenuItem separatorItem]];
  68. title = [@"Hide " stringByAppendingString:appName];
  69. [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
  70. menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
  71. [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
  72. [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
  73. [appleMenu addItem:[NSMenuItem separatorItem]];
  74. title = [@"Quit " stringByAppendingString:appName];
  75. [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
  76. /* Put menu into the menubar */
  77. menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
  78. [menuItem setSubmenu:appleMenu];
  79. [[NSApp mainMenu] addItem:menuItem];
  80. /* Tell the application object that this is now the application menu */
  81. [NSApp setAppleMenu:appleMenu];
  82. /* Finally give up our references to the objects */
  83. [appleMenu release];
  84. [menuItem release];
  85. }
  86. /* Create a window menu */
  87. static void setupWindowMenu(void)
  88. {
  89. NSMenu *windowMenu;
  90. NSMenuItem *windowMenuItem;
  91. NSMenuItem *menuItem;
  92. windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
  93. /* "Minimize" item */
  94. menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
  95. [windowMenu addItem:menuItem];
  96. [menuItem release];
  97. /* Put menu into the menubar */
  98. windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
  99. [windowMenuItem setSubmenu:windowMenu];
  100. [[NSApp mainMenu] addItem:windowMenuItem];
  101. /* Tell the application object that this is now the window menu */
  102. [NSApp setWindowsMenu:windowMenu];
  103. /* Finally give up our references to the objects */
  104. [windowMenu release];
  105. [windowMenuItem release];
  106. }
  107. /* Replacement for NSApplicationMain */
  108. static void CustomApplicationMain (int argc, char **argv)
  109. {
  110. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  111. GodotMain *main;
  112. /* Ensure the application object is initialised */
  113. [NSApplication sharedApplication];
  114. /* Set up the menubar */
  115. [NSApp setMainMenu:[[NSMenu alloc] init]];
  116. setApplicationMenu();
  117. setupWindowMenu();
  118. main = [[main alloc] init];
  119. [NSApp setDelegate:main];
  120. /* Start the main event loop */
  121. [NSApp run];
  122. [main release];
  123. [pool release];
  124. }
  125. extern int godot_main(int argc, char** argv);
  126. /* Called when the internal event loop has just started running */
  127. - (void) applicationDidFinishLaunching: (NSNotification *) note
  128. {
  129. int status;
  130. /* Hand off to main application code */
  131. gCalledAppMainline = TRUE;
  132. int ret = godot_main(global_argc, global_argv);
  133. exit(ret);
  134. }
  135. @end
  136. #ifdef main
  137. #undef main
  138. #endif
  139. int main (int argc, char **argv)
  140. {
  141. /* Copy the arguments into a global variable */
  142. /* This is passed if we are launched by double-clicking */
  143. if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
  144. global_argv = (char **) malloc(sizeof (char *) * 2);
  145. global_argv[0] = argv[0];
  146. global_argv[1] = NULL;
  147. global_argc = 1;
  148. // chdir to binary's dir when launched from finder
  149. int len = strlen(global_argv[0]);
  150. while (len--){
  151. if (global_argv[0][len] == '/') break;
  152. }
  153. if (len>=0) {
  154. char *path = (char *)malloc(len+1);
  155. memcpy(path, global_argv[0], len);
  156. path[len]=0;
  157. printf("Path: %s\n", path);
  158. chdir(path);
  159. }
  160. } else {
  161. int i;
  162. global_argc = argc;
  163. global_argv = (char **) malloc(sizeof (char *) * (argc+1));
  164. for (i = 0; i <= argc; i++)
  165. global_argv[i] = argv[i];
  166. }
  167. CustomApplicationMain (argc, argv);
  168. return 0;
  169. }