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
 static void
-WIN_UpdateFocus(SDL_Window *window)
+WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus)
 {
 {
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
     HWND hwnd = data->hwnd;
     HWND hwnd = data->hwnd;
     SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
     SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
     SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? 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;
         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
             /* 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
                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. */
                the global foreground window changes to and from this window. */
-            WIN_UpdateFocus(data->window);
+            WIN_UpdateFocus(data->window, !!wParam);
             WIN_CheckICMProfileChanged(data->window);
             WIN_CheckICMProfileChanged(data->window);
         }
         }
         break;
         break;
@@ -694,16 +694,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     case WM_ACTIVATE:
     case WM_ACTIVATE:
         {
         {
             /* Update the focus in case we changed focus to a child window and then away from the application */
             /* 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;
         break;
 
 
     case WM_SETFOCUS:
     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_KILLFOCUS:
     case WM_ENTERIDLE:
     case WM_ENTERIDLE:
         {
         {
             /* Update the focus in case it's changing between top-level windows in the same application */
             /* 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;
         break;