Browse Source

Merge pull request #41222 from bruvzg/2.1

Cherry-picks for the 2.1 branch (macOS)
Rémi Verschelde 5 years ago
parent
commit
4a8350bbe3
3 changed files with 56 additions and 12 deletions
  1. 8 0
      main/main.cpp
  2. 1 1
      platform/osx/godot_main_osx.mm
  3. 47 11
      platform/osx/os_osx.mm

+ 8 - 0
main/main.cpp

@@ -286,6 +286,14 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 #endif
 #endif
 
 
 	while (I) {
 	while (I) {
+#ifdef OSX_ENABLED
+		// Ignore the process serial number argument passed by macOS Gatekeeper.
+		// Otherwise, Godot would try to open a non-existent project on the first start and abort.
+		if (I->get().begins_with("-psn_")) {
+			I = I->next();
+			continue;
+		}
+#endif
 
 
 		List<String>::Element *N = I->next();
 		List<String>::Element *N = I->next();
 
 

+ 1 - 1
platform/osx/godot_main_osx.mm

@@ -84,5 +84,5 @@ int main(int argc, char **argv) {
 		os.run(); // it is actually the OS that decides how to run
 		os.run(); // it is actually the OS that decides how to run
 	Main::cleanup();
 	Main::cleanup();
 
 
-	return 0;
+	return os.get_exit_code();
 };
 };

+ 47 - 11
platform/osx/os_osx.mm

@@ -138,10 +138,44 @@ static bool mouse_down_control = false;
 @end
 @end
 
 
 @interface GodotApplicationDelegate : NSObject
 @interface GodotApplicationDelegate : NSObject
+- (void)forceUnbundledWindowActivationHackStep1;
+- (void)forceUnbundledWindowActivationHackStep2;
+- (void)forceUnbundledWindowActivationHackStep3;
 @end
 @end
 
 
 @implementation GodotApplicationDelegate
 @implementation GodotApplicationDelegate
 
 
+- (void)forceUnbundledWindowActivationHackStep1 {
+	// Step1: Switch focus to macOS Dock.
+	// Required to perform step 2, TransformProcessType will fail if app is already the in focus.
+	for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
+		[app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+		break;
+	}
+	[self performSelector:@selector(forceUnbundledWindowActivationHackStep2) withObject:nil afterDelay:0.02];
+}
+
+- (void)forceUnbundledWindowActivationHackStep2 {
+	// Step 2: Register app as foreground process.
+	ProcessSerialNumber psn = { 0, kCurrentProcess };
+	(void)TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+
+	[self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02];
+}
+
+- (void)forceUnbundledWindowActivationHackStep3 {
+	// Step 3: Switch focus back to app window.
+	[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notice {
+	NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+	if (nsappname == nil) {
+		// If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
+		[self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
+	}
+}
+
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
 	if (OS_OSX::singleton->get_main_loop())
 	if (OS_OSX::singleton->get_main_loop())
 		OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
 		OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
@@ -221,12 +255,8 @@ static bool mouse_down_control = false;
 
 
 		//Update context
 		//Update context
 		if (OS_OSX::singleton->main_loop) {
 		if (OS_OSX::singleton->main_loop) {
-			[OS_OSX::singleton->context update];
-
-			//Force window resize ???
-			NSRect frame = [OS_OSX::singleton->window_object frame];
-			[OS_OSX::singleton->window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES];
-			[OS_OSX::singleton->window_object setFrame:frame display:YES];
+			//Force window resize event
+			[self windowDidResize:notification];
 		}
 		}
 	}
 	}
 }
 }
@@ -1423,13 +1453,18 @@ void OS_OSX::make_rendering_thread() {
 }
 }
 
 
 Error OS_OSX::shell_open(String p_uri) {
 Error OS_OSX::shell_open(String p_uri) {
-
-	[[NSWorkspace sharedWorkspace] openURL:[[NSURL alloc] initWithString:[NSString stringWithUTF8String:p_uri.utf8().get_data()]]];
+	NSString *string = [NSString stringWithUTF8String:p_uri.utf8().get_data()];
+	NSURL *uri = [[NSURL alloc] initWithString:string];
+	// Escape special characters in filenames
+	if (!uri || !uri.scheme || [uri.scheme isEqual:@"file"]) {
+		uri = [[NSURL alloc] initWithString:[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]];
+	}
+	[[NSWorkspace sharedWorkspace] openURL:uri];
 	return OK;
 	return OK;
 }
 }
 
 
 String OS_OSX::get_locale() const {
 String OS_OSX::get_locale() const {
-	NSString *locale_code = [[NSLocale currentLocale] localeIdentifier];
+	NSString *locale_code = [[NSLocale preferredLanguages] objectAtIndex:0];
 	return [locale_code UTF8String];
 	return [locale_code UTF8String];
 }
 }
 
 
@@ -1738,7 +1773,8 @@ bool OS_OSX::is_window_maximized() const {
 
 
 void OS_OSX::move_window_to_foreground() {
 void OS_OSX::move_window_to_foreground() {
 
 
-	[window_object orderFrontRegardless];
+	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
+	[window_object makeKeyAndOrderFront:nil];
 }
 }
 
 
 void OS_OSX::set_window_always_on_top(bool p_enabled) {
 void OS_OSX::set_window_always_on_top(bool p_enabled) {
@@ -2041,7 +2077,7 @@ OS_OSX::OS_OSX() {
 	NSMenuItem *menu_item;
 	NSMenuItem *menu_item;
 	NSString *title;
 	NSString *title;
 
 
-	NSString *nsappname = [[[NSBundle mainBundle] performSelector:@selector(localizedInfoDictionary)] objectForKey:@"CFBundleName"];
+	NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
 	if (nsappname == nil)
 	if (nsappname == nil)
 		nsappname = [[NSProcessInfo processInfo] processName];
 		nsappname = [[NSProcessInfo processInfo] processName];