Просмотр исходного кода

win32: Use the current cursor coordinates when processing WM_NCACTIVATE

The event coordinates returned by GetMessagePos() for WM_NCACTIVATE are out of date if the cursor moved while an overlay was active, and may indicate that the cursor is still in the window when it is not. Always use the current cursor coordinates when processing this message to avoid incorrectly setting mouse focus if the cursor is no longer within the window.
Frank Praznik 20 часов назад
Родитель
Сommit
0a8ccb11eb
1 измененных файлов с 19 добавлено и 8 удалено
  1. 19 8
      src/video/windows/SDL_windowsevents.c

+ 19 - 8
src/video/windows/SDL_windowsevents.c

@@ -329,7 +329,7 @@ static void WIN_CheckAsyncMouseRelease(Uint64 timestamp, SDL_WindowData *data)
     data->mouse_button_flags = (WPARAM)-1;
 }
 
-static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus, DWORD pos)
+static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus, LPPOINT pos)
 {
     SDL_WindowData *data = window->internal;
     HWND hwnd = data->hwnd;
@@ -366,8 +366,8 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus, DWORD pos)
 
         // In relative mode we are guaranteed to have mouse focus if we have keyboard focus
         if (!SDL_GetMouse()->relative_mode) {
-            cursorPos.x = (LONG)GET_X_LPARAM(pos);
-            cursorPos.y = (LONG)GET_Y_LPARAM(pos);
+            cursorPos.x = pos->x;
+            cursorPos.y = pos->y;
             ScreenToClient(hwnd, &cursorPos);
             SDL_SendMouseMotion(WIN_GetEventTimestamp(), window, SDL_GLOBAL_MOUSE_ID, false, (float)cursorPos.x, (float)cursorPos.y);
         }
@@ -1221,8 +1221,13 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
 
         /* 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, !!wParam, GetMessagePos());
+           the global foreground window changes to and from this window.
+
+           The current cursor position is needed here, as the message position contains old
+           coordinates if the pointer moved while an overlay was active. */
+        POINT pos = { 0, 0 };
+        GetCursorPos(&pos);
+        WIN_UpdateFocus(data->window, !!wParam, &pos);
 
         /* Handle borderless windows; this event is intended for drawing the titlebar, so we need
            to stop that from happening. */
@@ -1246,7 +1251,9 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
     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, !!LOWORD(wParam), GetMessagePos());
+        const DWORD msgPos = GetMessagePos();
+        POINT pos = { GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos) };
+        WIN_UpdateFocus(data->window, !!LOWORD(wParam), &pos);
     } break;
 
     case WM_MOUSEACTIVATE:
@@ -1269,14 +1276,18 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
     case WM_SETFOCUS:
     {
         // Update the focus in case it's changing between top-level windows in the same application
-        WIN_UpdateFocus(data->window, true, GetMessagePos());
+        const DWORD msgPos = GetMessagePos();
+        POINT pos = { GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos) };
+        WIN_UpdateFocus(data->window, true, &pos);
     } 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, false, GetMessagePos());
+        const DWORD msgPos = GetMessagePos();
+        POINT pos = { GET_X_LPARAM(msgPos), GET_Y_LPARAM(msgPos) };
+        WIN_UpdateFocus(data->window, false, &pos);
     } break;
 
     case WM_POINTERENTER: