We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5432 - Switching to a multi-window SDL application on macOS (especially in fullscreen) always shows the last window created, and not the last focused window
Summary: Switching to a multi-window SDL application on macOS (especially in fullscree...
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.12
Hardware: x86_64 macOS 10.15
: P2 normal
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-01 19:52 UTC by jackmacwindowslinux
Modified: 2021-01-02 18:12 UTC (History)
0 users

See Also:


Attachments
Recording of the focus bug (1.42 MB, video/mp4)
2021-01-01 19:52 UTC, jackmacwindowslinux
Details

Note You need to log in before you can comment on or make changes to this bug.
Description jackmacwindowslinux 2021-01-01 19:52:43 UTC
Created attachment 4624 [details]
Recording of the focus bug

When switching between apps using Command-Tab or the Dock on macOS, SDL will always raise the last window created, instead of whichever window was last selected or input grabbed.

To reproduce, compile this code:

#include <SDL2/SDL.h>

int main() {
    SDL_Window * win1 = SDL_CreateWindow("Window 1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 300, 200, SDL_WINDOW_RESIZABLE);
    SDL_Window * win2 = SDL_CreateWindow("Window 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 300, 200, SDL_WINDOW_RESIZABLE);
    SDL_RaiseWindow(win1);
    SDL_Event e;
    while (1) if (SDL_WaitEvent(&e) && e.type == SDL_QUIT) break;
    SDL_DestroyWindow(win2);
    SDL_DestroyWindow(win1);
    return 0;
}

Then run the program, notice that Window 1 is raised, Command-Tab out to another application, and switch back via either Command-Tab or the Dock. I expect Window 1 to remain on top, but instead it raises Window 2 to the top.

I've attached a demonstration video of an app in fullscreen. I'm using the trackpad to go to the next space, but switching to the first one makes it automatically go to the second one (I'm not moving it manually). The last window being focused each time is the window with green text; however, it always switches to the one with yellow text.

I have found the source of the problem in SDL_cocoaevents.m, on lines 216-235. Currently, when the app delegate receives a focus event, it reads from SDL_GetVideoDevice()->windows, which is only set when a window is created or destroyed. Thus, the last window created and pushed to the "stack" is focused. 

My proposed solution would be to either a) have a dedicated lastFocusedWindow field in SDL_VideoDevice that is set for every SDL_RaiseWindow/focus event, and then use that in the application activation event, or b) reorder the windows list on SDL_RaiseWindow/focus to move the window to the top, which could potentially be as simple as this:

win->prev->next = win->next;
win->next->prev = win->prev;
win->prev = NULL;
win->next = _this->windows;
_this->windows = win;

I imagine there'd be more to it than that, but that should be the gist of it.

This bug may also affect other systems, but I have yet to try it out. (However, I do recall something like this possibly happening on Windows.)