Browse Source

Ignore focus change messages that contradict GetForegroundWindow.

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.
Esme Povirk 3 years ago
parent
commit
def27267b5
1 changed files with 11 additions and 5 deletions
  1. 11 5
      src/video/windows/SDL_windowsevents.c

+ 11 - 5
src/video/windows/SDL_windowsevents.c

@@ -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;
     }
 
@@ -686,7 +686,7 @@ 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;
@@ -694,16 +694,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     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;