Skip to content

Commit

Permalink
Ignore focus change messages that contradict GetForegroundWindow.
Browse files Browse the repository at this point in the history
On Wine, when a window is programmatically minimized in response
to losing focus, we receive a WM_ACTIVATE for the deactivation,
but GetForegroundWindow still indicates that our window is focused.
This causes an incorrect SDL_WINDOWEVENT_FOCUS_GAINED.

This is probably a Wine bug, but it may take a while to fix and
then for the fix to make its way to users.
  • Loading branch information
Esme Povirk authored and slouken committed Apr 6, 2022
1 parent ff5b67e commit def2726
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/video/windows/SDL_windowsevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,14 +378,14 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
}

static void
WIN_UpdateFocus(SDL_Window *window)
WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
HWND hwnd = data->hwnd;
SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? SDL_TRUE : SDL_FALSE;

if (had_focus == has_focus) {
if (had_focus == has_focus || has_focus != expect_focus) {
return;
}

Expand Down Expand Up @@ -686,24 +686,30 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
actually being the foreground window, but this appears to get called in all cases where
the global foreground window changes to and from this window. */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, !!wParam);
WIN_CheckICMProfileChanged(data->window);
}
break;

case WM_ACTIVATE:
{
/* Update the focus in case we changed focus to a child window and then away from the application */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, !!LOWORD(wParam));
}
break;

case WM_SETFOCUS:
{
/* Update the focus in case it's changing between top-level windows in the same application */
WIN_UpdateFocus(data->window, SDL_TRUE);
}
break;

case WM_KILLFOCUS:
case WM_ENTERIDLE:
{
/* Update the focus in case it's changing between top-level windows in the same application */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, SDL_FALSE);
}
break;

Expand Down

0 comments on commit def2726

Please sign in to comment.