Browse Source

Merge pull request #17187 from bruvzg/macos_unbundled_app_focus_hack

[macOS] Hack to force window activation for non-bundled app.
Rémi Verschelde 7 years ago
parent
commit
26d42cd9a4
1 changed files with 35 additions and 1 deletions
  1. 35 1
      platform/osx/os_osx.mm

+ 35 - 1
platform/osx/os_osx.mm

@@ -150,10 +150,44 @@ static Vector2 get_mouse_pos(NSEvent *event) {
 @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];
+	}
+}
+
 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
 - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
 	// Note: called before main loop init!
 	// Note: called before main loop init!
 	char *utfs = strdup([filename UTF8String]);
 	char *utfs = strdup([filename UTF8String]);
@@ -2340,7 +2374,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];