https://bugs.winehq.org/show_bug.cgi?id=51194
Bug ID: 51194 Summary: Unity games on Mac are not correctly foregrounded on launch Product: Wine Version: 6.9 Hardware: x86-64 OS: Mac OS X Status: UNCONFIRMED Severity: normal Priority: P2 Component: winemac.drv Assignee: wine-bugs@winehq.org Reporter: bshanks@codeweavers.com
When Unity games launch, they roughly do this:
(create normal window)
SetWindowPos(hWnd, HWND_NOTOPMOST, 200, 200, 640, 480, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); Sleep(100); SetFocus(hWnd); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);
(they actually call SetWindowPos again with the same parameters instead of a Sleep call, but the only effect that matters is that the call takes a small amount of time).
On Mac, this ends up with the window focused and foreground, but GetForegroundWindow() returns the desktop's HWND, not the correct hWnd. This results in the window not receiving raw input messages, and a typical FPS is not controllable. But in the example, if I call SetForegroundWindow() instead of SetFocus(), the foreground window is correctly set.
On Linux/X11, it works correctly for both cases.
The difference appears to be that SetForegroundWindow() directly sets the foreground window (set_foreground_window() in dlls/user32/focus.c), but SetFocus() does not. It sets focus through the driver (X11DRV/macdrv_SetFocus()), and then once the window system reports the window is focused (WM_TAKE_FOCUS / windowDidBecomeKey:), SetForegroundWindow() is called.
However, the Mac driver has logic added that prevents this from working the same way as on X11. The first is 4e0e9ca84a89d1ac2b548ee4a6224b764af2d23d. makeKeyWindow: is the OS call to focus the window, and windowDidBecomeKey: is eventually called by it. Since causing_becomeKeyWindow is == self, the important part of windowDidBecomeKey: (calling windowGotFocus:) is skipped.
But even if I comment out that early return in windowDidBecomeKey:, so that windowGotFocus: is called and a WINDOW_GOT_FOCUS event is posted, makeFocused: then discards all GOT_FOCUS/LOST_FOCUS events. This is from commit 4f9de6bcdf1722a258413ce99c26f2ee5b36dbf2, and apparently fixed the game Syberia II.
Both of these commits need to be relaxed/reverted to some degree. I'll also upload a sample Unity app for testing, and a simple Win32 app to reproduce.
https://bugs.winehq.org/show_bug.cgi?id=51194
--- Comment #1 from Brendan Shanks bshanks@codeweavers.com --- Additionally, the window does get correctly foregrounded without a Sleep() or additional SetWindowPos() call.
This appears to be luck: without any extra time after the SetWindowPos() call, the window has not had any time to be shown (and the applicationWill/DidBecomeActive / APP_ACTIVATED events sent). When SetFocus() is called, the app isn't active, so makeKeyWindow: doesn't take effect immediately. windowDidBecomeKey: is called later, not under the call stack of makeFocused: / makeKeyWindow:, so the logic in those commits doesn't apply.