Cocoa: deal with mouse focus when warping the cursor from outside a window. Otherwise, you might not get appropriate mouse enter/leave events. Better fix for Bugzilla #2984.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m
index 9c37c47..3c0c478 100644
--- a/src/video/cocoa/SDL_cocoamouse.m
+++ b/src/video/cocoa/SDL_cocoamouse.m
@@ -195,6 +195,21 @@ Cocoa_ShowCursor(SDL_Cursor * cursor)
return 0;
}}
+static SDL_Window *
+SDL_FindWindowAtPoint(const int x, const int y)
+{
+ const SDL_Point pt = { x, y };
+ SDL_Window *i;
+ for (i = SDL_GetVideoDevice()->windows; i; i = i->next) {
+ const SDL_Rect r = { i->x, i->y, i->w, i->h };
+ if (SDL_PointInRect(&pt, &r)) {
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
static void
Cocoa_WarpMouseGlobal(int x, int y)
{
@@ -207,7 +222,7 @@ Cocoa_WarpMouseGlobal(int x, int y)
return;
}
}
- CGPoint point = CGPointMake((float)x, (float)y);
+ const CGPoint point = CGPointMake((float)x, (float)y);
Cocoa_HandleMouseWarp(point.x, point.y);
@@ -219,21 +234,22 @@ Cocoa_WarpMouseGlobal(int x, int y)
CGWarpMouseCursorPosition(point);
CGSetLocalEventsSuppressionInterval(0.25);
- if (!mouse->relative_mode && mouse->focus) {
- /* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
- * other implementations' APIs.
- */
- SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x - mouse->focus->x, y - mouse->focus->y);
+ /* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
+ * other implementations' APIs. Send what's appropriate.
+ */
+ if (!mouse->relative_mode) {
+ SDL_Window *win = SDL_FindWindowAtPoint(x, y);
+ SDL_SetMouseFocus(win);
+ if (win) {
+ SDL_assert(win == mouse->focus);
+ SDL_SendMouseMotion(win, mouse->mouseID, 0, x - win->x, y - win->y);
+ }
}
}
static void
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
{
- /* pretend we have the mouse focus, even if we don't, so
- Cocoa_WarpMouseGlobal() will properly fake a mouse motion event. */
- SDL_Mouse *mouse = SDL_GetMouse();
- mouse->focus = window;
Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
}