Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac: closing a window doesn't transfer focus to the next one #850

Closed
SDLBugzilla opened this issue Feb 10, 2021 · 0 comments
Closed

Mac: closing a window doesn't transfer focus to the next one #850

SDLBugzilla opened this issue Feb 10, 2021 · 0 comments

Comments

@SDLBugzilla
Copy link
Collaborator

SDLBugzilla commented Feb 10, 2021

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: HG 2.0
Reported for operating system, platform: Mac OS X 10.8, x86

Comments on the original bug report:

On 2013-04-25 22:36:17 +0000, Alex Szpakowski wrote:

When closing an SDL MessageBox, the expected behaviour is for the previously-focused SDL window from that app to regain focus, however that doesn't happen; the user has to manually click on the SDL window after closing the MessageBox. This behaviour also occurs when the "About this App" window is opened and closed.

Tested on Mac OS 10.8.3.

On 2013-06-07 23:39:32 +0000, Alex Szpakowski wrote:

This bug also appears when closing a regular SDL window (via SDL_DestroyWindow), if there are more SDL windows open in the same program.

Input focus will not be transferred to the next window when one is destroyed, and cmd-` (which normally works in SDL2 programs in OS X to switch between windows) doesn't function until a window gains focus again.

On 2013-06-08 00:16:04 +0000, Alex Szpakowski wrote:

Created attachment 1185
Test case demonstrating the issue when a window is closed

On 2013-07-12 22:16:04 +0000, Ryan C. Gordon wrote:

(Sorry if you get a lot of copies of this email, we're touching dozens of bug reports right now.)

Tagging a bunch of bugs as target-2.0.0, Priority 2.

This means we're in the final stretch for an official SDL 2.0.0 release! These are the bugs we really want to fix before shipping if humanly possible.

That being said, we don't promise to fix them because of this tag, we just want to make sure we don't forget to deal with them before we bless a final 2.0.0 release, and generally be organized about what we're aiming to ship.

Hopefully you'll hear more about this bug soon. If you have more information (including "this got fixed at some point, nevermind"), we would love to have you come add more information to the bug report when you have a moment.

Thanks!
--ryan.

On 2013-07-14 12:49:51 +0000, Ryan C. Gordon wrote:

Hmm, is there some way to make Cocoa handle this, or do we need to track our own windows' z-order and make the next-highest window Key when the Key window closes?

(I couldn't find a way to get the current z-order of an NSWindow from Cocoa, either...)

We could just pick another window in our internal list of SDL_Windows, but ideally the next highest window gets focus when the focused window closes.

As a separate issue, Bug # 1970 notes that our Cocoa message box code ignores requests to assign a parent to the message box, which would also partially solve this problem.

--ryan.

On 2013-07-14 15:04:02 +0000, Alex Szpakowski wrote:

My gut feeling is that SDL's cocoa code is unintentionally preventing the normal behaviour from working correctly, or not activating it somehow - the standard 'about' window (which SDL just gets from Cocoa rather than creating the entire thing itself) has the same focus issues in SDL2 apps but not other ones (it works fine in SDL 1.2 as well.)

On 2013-07-14 16:12:44 +0000, Jiang Jiang wrote:

Ryan, according to http://www.cocoabuilder.com/archive/cocoa/202993-nswindow-depth.html and http://stackoverflow.com/questions/3087193/how-to-access-windows-hierarchy-for-my-application-on-mac, NSWindowListForContext can be used.

On 2013-07-14 16:33:10 +0000, Sam Lantinga wrote:

Fixed!
http://hg.libsdl.org/SDL/rev/8e6dfbc8ac6b

On 2013-07-14 16:34:43 +0000, Sam Lantinga wrote:

Er, actually, just the messagebox portion of this is fixed.

On 2013-07-14 16:43:18 +0000, Sam Lantinga wrote:

It's pretty easy to pick a different window to focus when one is destroyed, but I'm not sure how to solve the about box issue.

No other application has this problem as far as I can tell, so we must be missing something simple.

On 2013-07-15 00:53:21 +0000, Ryan C. Gordon wrote:

I'm sure this is something simple, but hours of research haven't exposed it. Try googling for "Cocoa window focus" to find a stunning lack of information on how this works behind the scenes. :)

Since every other multi-window Mac thing I've seen always makes the next window in the z-order focused when you close something, and there don't appear to be any serious APIs for figuring out the z-order, and there doesn't seem to be anyone on the internet that's talked about having this problem or how to build your app to handle it, it's got to be something we're turning off instead of something we had to opt into, though, right? Presumably figuring this out fixes the About box issue without adding specific code for it, too.

Where do we go for more info at this point? Anyone have an Apple contact? Hope for the best on Stack Overflow or a mailing list?

--ryan.

On 2013-07-21 21:31:49 +0000, Eric wing wrote:

I took a look at this. I believe the problem is SDL is missing something (probably a private API) in its recreation of the run loop.

At first, I thought maybe something was not setup correctly in the responder chain. Most of the work you do to set the nextResponder is typically not needed for what you are doing. (Incidentally, everybody uses NIBs which is the other reason nobody asks these kinds of questions or has these problems.)

But digging deeper into it and recreating a simple nibless project and runloop, I discovered the problem is the absence of [NSApp run]; Basically, if I use [NSApp run], things work. If I reinvent the runloop, it does not.

SDL is missing [NSApp updateWindows], but adding it didn't help. Unfortunately, we're getting into private implementation details of the Cocoa runloop and I don't know the solution. I do know that this problem is not new. From time-to-time, certain Apple APIs don't work correctly if you don't use their run-loop. I remember reports that Game Center didn't work correctly without the default runloop a few years ago.

Unless somebody can figure out the missing magic stuff in the Cocoa run-loop (and those APIs are public for App Store review purposes), I think my ultimate long-term recommendation is to use the standard run-loop. This will avoid a lot of these subtle problems like this and Game Center. But I haven't fully thought about how to do this in a way that is compatible with SDL's polling model (or even if this is possible).

I will attach my test program for you to play with.

-Eric

P.S. The code you have to look for the current screen is also probably excessive. In my experience, it is best to let Cocoa do what it wants without trying to set everything. I have seen a lot of broken-ness due to this kind of code when people have multi-monitor configurations and constantly disconnect and plug into different monitors (typical on laptops nowadays). Also, Apple keeps changing the behaviors (like OS X 10.9 will change things again).

On 2013-07-21 21:32:44 +0000, Eric wing wrote:

Created attachment 1246
Standalone test program for nib-less multiple windows and custom run-loop demonstrating the window focus bug

clang minimalcocoa2.m -framework Cocoa
./a.out

On 2013-07-22 01:26:58 +0000, Jiang Jiang wrote:

I think the trick is to call [NSApp run] once to setup things, then go back to your own runloop.

Right before calling [NSApp run], you can set a timer to immediately quit the runloop.

If I remember correctly, app modal dialogs also require the standard runloop.

On 2013-07-22 02:15:35 +0000, Sam Lantinga wrote:

Jiang, can you post a patch?

On 2013-07-22 07:38:51 +0000, Jiang Jiang wrote:

Just tried, unfortunately that trick didn't work. I will try finding another solution.

On 2013-07-22 18:04:10 +0000, Jiang Jiang wrote:

Created attachment 1249
Assembly used in NSWindow

I tried doing some assembly level debugging but still not quite sure what went wrong.

With Eric's test case, when using [NSApp run], we call this backtrace on window close:

0 mc 0x000000010837a802 -[TestWindowDelegate windowDidBecomeKey:] + 82
1 CoreFoundation 0x00007fff94990723 _CFXNotificationPost + 3203
2 Foundation 0x00007fff92d9412a -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
3 AppKit 0x00007fff98144404 -[NSWindow becomeKeyWindow] + 1417
4 AppKit 0x00007fff98143886 -[NSWindow _changeKeyAndMainLimitedOK:] + 803
5 AppKit 0x00007fff982152db -[NSWindow _orderOutAndCalcKeyWithCounter:stillVisible:docWindow:] + 1189
6 AppKit 0x00007fff9814bcbd -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 2916
7 AppKit 0x00007fff9814abe0 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 786
8 AppKit 0x00007fff9814a85d -[NSWindow orderWindow:relativeTo:] + 162
9 AppKit 0x00007fff9869c8bb __18-[NSWindow _close]_block_invoke + 443
10 AppKit 0x00007fff98214b56 -[NSWindow _close] + 370
11 AppKit 0x00007fff9829fa78 -[NSWindow __close] + 251
12 AppKit 0x00007fff9829f955 -[NSWindow _close:] + 146
13 AppKit 0x00007fff981799da -[NSApplication sendAction:to:from:] + 327
14 AppKit 0x00007fff98179853 -[NSControl sendAction:to:] + 86
15 AppKit 0x00007fff9817978d -[NSCell _sendActionFrom:] + 128
16 AppKit 0x00007fff98178015 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2316
17 AppKit 0x00007fff98177697 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 487
18 AppKit 0x00007fff98176db6 -[NSControl mouseDown:] + 706
19 AppKit 0x00007fff9862c061 -[_NSThemeWidget mouseDown:] + 304
20 AppKit 0x00007fff98170471 -[NSWindow sendEvent:] + 11296
21 AppKit 0x00007fff9816aa98 -[NSApplication sendEvent:] + 2021
22 AppKit 0x00007fff9808baf9 -[NSApplication run] + 646
23 mc 0x000000010837b09a main + 1898
24 libdyld.dylib 0x00007fff8d4005fd start + 1

(I set a breakpoint at windowDidBecomeKey: of the window delegate.)

However with custom runloop, we only get to the point -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] but not -[NSWindow _orderOutAndCalcKeyWithCounter:stillVisible:docWindow:].

I disassembled the whole -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] function and found out that we jump to the end of the function after a check for [NSApp _batchOrdering]. Attached the assembly in case anyone is interested.

On 2013-07-27 01:12:43 +0000, Ryan C. Gordon wrote:

Created attachment 1261
Workaround for most use cases.

For 2.0.0, let's just go with my quick-and-dirty patch to fix this well enough. We'll rip it out when we have a better solution ready.

This fixes everything but the About box.

--ryan.

On 2013-07-27 03:59:32 +0000, Sam Lantinga wrote:

Okay, go for it. Please add a comment to the code referencing this bug and that it's a bandaid with (hopefully) a real fix incoming.

Jorgen was going to investigate more as well, but this should be good for now.

On 2013-07-27 13:10:53 +0000, Ryan C. Gordon wrote:

My patch is now http://hg.libsdl.org/SDL/rev/f0f5143b27cf, and a FIXME comment explaining it is now http://hg.libsdl.org/SDL/rev/c515121a3df7.

We'll leave this bug open for now until a better solution arises, but I'll remove the target-2.0.0 keyword, since we're good enough for this release.

--ryan.

On 2015-01-29 00:15:00 +0000, Alex Szpakowski wrote:

Created attachment 2009
Improved workaround

I made an improved workaround which also handles the 'About' window and other windows that aren't created by SDL. It uses a similar idea to Ryan's workaround so it doesn't really fix the underlying cause of the issue, but it seems to work well for me.

On 2015-02-19 05:22:17 +0000, Ryan C. Gordon wrote:

Marking a large number of bugs with the "triage-2.0.4" keyword at once. Sorry if you got a lot of email from this. This is to help me sort through some bugs in regards to a 2.0.4 release. We may or may not fix this bug for 2.0.4, though!

On 2015-02-19 06:35:30 +0000, Alex Szpakowski wrote:

I should mention, none of the workarounds so far handle focus transfer when SDL message boxes (NSAlerts) are closed – they have the same issue.

The newer workaround patch I posted does still cover more cases than the existing workaround though.

On 2015-03-22 05:27:08 +0000, Ryan C. Gordon wrote:

(In reply to Alex Szpakowski from comment # 22)

I should mention, none of the workarounds so far handle focus transfer when
SDL message boxes (NSAlerts) are closed – they have the same issue.

The newer workaround patch I posted does still cover more cases than the
existing workaround though.

This patch is now https://hg.libsdl.org/SDL/rev/9763f689bced, thanks!

I'm leaving this bug open, but removing the triage-2.0.4 keyword for now, since this is as far as I intend to go with this bug before 2.0.4, but ideally we still find the perfect solution at some point.

--ryan.

On 2016-09-25 19:13:49 +0000, Alex Szpakowski wrote:

Maybe I'm not testing the right things, but this seems to no longer be an issue in macOS 10.12 (with the current workarounds in place). Can anyone else verify?

@slouken slouken removed the bug label May 11, 2022
@slouken slouken closed this as completed Nov 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants