Cocoa: Handle more cases of lost focus when Key window closes (thanks, Alex!). Sort of fixes Bugzilla #1825 a little more. It's an ongoing effort. :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m
index 5102034..925f05b 100644
--- a/src/video/cocoa/SDL_cocoaevents.m
+++ b/src/video/cocoa/SDL_cocoaevents.m
@@ -66,11 +66,19 @@
{
self = [super init];
if (self) {
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
seenFirstActivate = NO;
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(focusSomeWindow:)
- name:NSApplicationDidBecomeActiveNotification
- object:nil];
+
+ [center addObserver:self
+ selector:@selector(windowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:nil];
+
+ [center addObserver:self
+ selector:@selector(focusSomeWindow:)
+ name:NSApplicationDidBecomeActiveNotification
+ object:nil];
}
return self;
@@ -78,16 +86,65 @@
- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ [center removeObserver:self name:NSWindowWillCloseNotification object:nil];
+ [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
+
[super dealloc];
}
+- (void)windowWillClose:(NSNotification *)notification;
+{
+ NSWindow *win = (NSWindow*)[notification object];
+
+ if (![win isKeyWindow]) {
+ return;
+ }
+
+ /* HACK: Make the next window in the z-order key when the key window is
+ * closed. The custom event loop and/or windowing code we have seems to
+ * prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825
+ */
+
+ /* +[NSApp orderedWindows] never includes the 'About' window, but we still
+ * want to try its list first since the behavior in other apps is to only
+ * make the 'About' window key if no other windows are on-screen.
+ */
+ for (NSWindow *window in [NSApp orderedWindows]) {
+ if (window != win && [window canBecomeKeyWindow]) {
+ if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
+ if (![window isOnActiveSpace]) {
+ continue;
+ }
+ }
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+
+ /* If a window wasn't found above, iterate through all visible windows
+ * (including the 'About' window, if it's shown) and make the first one key.
+ * Note that +[NSWindow windowNumbersWithOptions:] was added in 10.6.
+ */
+ if ([NSWindow respondsToSelector:@selector(windowNumbersWithOptions:)]) {
+ /* Get all visible windows in the active Space, in z-order. */
+ for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
+ NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
+ if (window && window != win && [window canBecomeKeyWindow]) {
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+ }
+}
+
- (void)focusSomeWindow:(NSNotification *)aNotification
{
/* HACK: Ignore the first call. The application gets a
* applicationDidBecomeActive: a little bit after the first window is
* created, and if we don't ignore it, a window that has been created with
- * SDL_WINDOW_MINIZED will ~immediately be restored.
+ * SDL_WINDOW_MINIMIZED will ~immediately be restored.
*/
if (!seenFirstActivate) {
seenFirstActivate = YES;
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index d545529..068c59e 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -374,7 +374,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
NSNotificationCenter *center;
NSWindow *window = _data->nswindow;
NSView *view = [window contentView];
- NSArray *windows = nil;
center = [NSNotificationCenter defaultCenter];
@@ -402,25 +401,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
if ([view nextResponder] == self) {
[view setNextResponder:nil];
}
-
- /* Make the next window in the z-order Key. If we weren't the foreground
- when closed, this is a no-op.
- !!! FIXME: Note that this is a hack, and there are corner cases where
- !!! FIXME: this fails (such as the About box). The typical nib+RunLoop
- !!! FIXME: handles this for Cocoa apps, but we bypass all that in SDL.
- !!! FIXME: We should remove this code when we find a better way to
- !!! FIXME: have the system do this for us. See discussion in
- !!! FIXME: http://bugzilla.libsdl.org/show_bug.cgi?id=1825
- */
- windows = [NSApp orderedWindows];
- for (NSWindow *win in windows) {
- if (win == window) {
- continue;
- }
-
- [win makeKeyAndOrderFront:self];
- break;
- }
}
- (BOOL)isMoving