From b28bd7c5a4c6fa66f6e54ffb9f186617f2d5a533 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 17 Mar 2019 12:14:09 +0100 Subject: Cocoa: Fix missing key window after closing "About" The cause of this issue goes deeper inside of the custom nature of the event loop. In short, when not using [NSApp run] closing "About" window does not make previous key window a key again. The solution is quite similar to other projects, but we only force key window from handler when closing one appears to be "About" window. In all other cases we leave it up to Blender's window manager to make decision and do not interfere with it. Test plan: - Open Blender application - Go to Blender -> About Blender menu item - Close About window - Note that Blender's window does not become active again. Reviewers: brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D4534 --- intern/ghost/intern/GHOST_SystemCocoa.mm | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index b7495873386..52031e77cc7 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -282,6 +282,9 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) GHOST_SystemCocoa *systemCocoa; } + +- (id)init; +- (void)dealloc; - (void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification; - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; @@ -289,9 +292,28 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) - (void)applicationWillTerminate:(NSNotification *)aNotification; - (void)applicationWillBecomeActive:(NSNotification *)aNotification; - (void)toggleFullScreen:(NSNotification *)notification; +- (void)windowWillClose:(NSNotification*)notification; @end @implementation CocoaAppDelegate : NSObject +- (id)init { + self = [super init]; + if (self) { + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(windowWillClose:) + name:NSWindowWillCloseNotification + object:nil]; + } + return self; +} + +- (void)dealloc { + NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self name:NSWindowWillCloseNotification object:nil]; + [super dealloc]; +} + -(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa { systemCocoa = sysCocoa; @@ -341,6 +363,53 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { } +// The purpose of this function is to make sure closing "About" window does not +// leave Blender with no key windows. This is needed due to a custom event loop +// nature of the application: for some reason only using [NSApp run] will ensure +// correct behavior in this case. +// +// This is similar to an issue solved in SDL: +// https://bugzilla.libsdl.org/show_bug.cgi?id=1825 +// +// Our solution is different, since we want Blender to keep track of what is +// the key window during normal operation. In order to do so we exploit the +// fact that "About" window is never in the orderedWindows array: we only force +// key window from here if the closing one is not in the orderedWindows. This +// saves lack of key windows when closing "About", but does not interfere with +// Blender's window manager when closing Blender's windows. +- (void)windowWillClose:(NSNotification*)notification { + NSWindow* closing_window = (NSWindow*)[notification object]; + NSInteger index = [[NSApp orderedWindows] indexOfObject:closing_window]; + if (index != NSNotFound) { + return; + } + // Find first suitable window from the current space. + for (NSWindow* current_window in [NSApp orderedWindows]) { + if (current_window == closing_window) { + continue; + } + if ([current_window isOnActiveSpace] && + [current_window canBecomeKeyWindow]) + { + [current_window makeKeyAndOrderFront:nil]; + return; + } + } + // If that didn't find any windows, we try to find any suitable window of + // the application. + for (NSNumber* window_number in [NSWindow windowNumbersWithOptions:0]) { + NSWindow* current_window = + [NSApp windowWithWindowNumber:[window_number integerValue]]; + if (current_window == closing_window) { + continue; + } + if ([current_window canBecomeKeyWindow]) { + [current_window makeKeyAndOrderFront:nil]; + return; + } + } +} + @end -- cgit v1.2.3