From a61a2d5a5a687982a001c26aca0de5a4f9f7e7c0 Mon Sep 17 00:00:00 2001 From: "J?rgen P. Tjern?" Date: Mon, 22 Apr 2013 18:14:55 -0700 Subject: [PATCH] Send mouse leave updates for Windows and X11. We now generate a final SDL_MOUSEMOTION before the cursor leaves the window, followed by a SDL_WINDOWEVENT_LEAVE. --- src/events/SDL_mouse.c | 26 ++++++++++++++++++-------- src/events/SDL_windowevents.c | 2 ++ src/video/SDL_sysvideo.h | 3 +++ src/video/SDL_video.c | 13 +++++++++++++ src/video/windows/SDL_windowsevents.c | 10 ++++++++-- src/video/windows/SDL_windowsvideo.c | 1 + src/video/windows/SDL_windowswindow.c | 19 +++++++++++++++++++ src/video/windows/SDL_windowswindow.h | 1 + src/video/x11/SDL_x11events.c | 4 ++++ 9 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index d467d0791..d8d811bba 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -33,6 +33,8 @@ /* The mouse state */ static SDL_Mouse SDL_mouse; +static int +SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y); /* Public functions */ int @@ -154,8 +156,9 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) #endif if (window == mouse->focus) { #ifdef DEBUG_MOUSE - printf("Mouse left window, synthesizing focus lost event\n"); + printf("Mouse left window, synthesizing move & focus lost event\n"); #endif + SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); SDL_SetMouseFocus(NULL); } return SDL_FALSE; @@ -176,18 +179,25 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { - SDL_Mouse *mouse = SDL_GetMouse(); - int posted; - int xrel; - int yrel; - int x_max = 0, y_max = 0; - if (window && !relative) { + SDL_Mouse *mouse = SDL_GetMouse(); if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { return 0; } } + return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); +} + +static int +SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + int posted; + int xrel; + int yrel; + int x_max = 0, y_max = 0; + /* relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; @@ -676,4 +686,4 @@ SDL_ShowCursor(int toggle) return shown; } -/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */ \ No newline at end of file diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index 0e8c27c77..60d65ae57 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -148,12 +148,14 @@ SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1, return 0; } window->flags |= SDL_WINDOW_MOUSE_FOCUS; + SDL_OnWindowEnter(window); break; case SDL_WINDOWEVENT_LEAVE: if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) { return 0; } window->flags &= ~SDL_WINDOW_MOUSE_FOCUS; + SDL_OnWindowLeave(window); break; case SDL_WINDOWEVENT_FOCUS_GAINED: if (window->flags & SDL_WINDOW_INPUT_FOCUS) { diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 4874014d7..2de5b83d1 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -201,6 +201,7 @@ struct SDL_VideoDevice int (*CreateWindowFramebuffer) (_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); int (*UpdateWindowFramebuffer) (_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); void (*DestroyWindowFramebuffer) (_THIS, SDL_Window * window); + void (*OnWindowEnter) (_THIS, SDL_Window * window); /* * * */ /* @@ -367,6 +368,8 @@ extern void SDL_OnWindowHidden(SDL_Window * window); extern void SDL_OnWindowResized(SDL_Window * window); extern void SDL_OnWindowMinimized(SDL_Window * window); extern void SDL_OnWindowRestored(SDL_Window * window); +extern void SDL_OnWindowEnter(SDL_Window * window); +extern void SDL_OnWindowLeave(SDL_Window * window); extern void SDL_OnWindowFocusGained(SDL_Window * window); extern void SDL_OnWindowFocusLost(SDL_Window * window); extern void SDL_UpdateWindowGrab(SDL_Window * window); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 1e40ec2cf..8e21579d6 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2028,6 +2028,19 @@ SDL_OnWindowRestored(SDL_Window * window) } } +void +SDL_OnWindowEnter(SDL_Window * window) +{ + if (_this->OnWindowEnter) { + _this->OnWindowEnter(_this, window); + } +} + +void +SDL_OnWindowLeave(SDL_Window * window) +{ +} + void SDL_OnWindowFocusGained(SDL_Window * window) { diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index fc85e4493..f38429532 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -445,10 +445,16 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } #ifdef WM_MOUSELEAVE - /* FIXME: Do we need the SDL 1.2 hack to generate WM_MOUSELEAVE now? */ case WM_MOUSELEAVE: if (SDL_GetMouseFocus() == data->window) { - SDL_SetMouseFocus(NULL); + if (!SDL_GetMouse()->relative_mode) { + POINT cursorPos; + GetCursorPos(&cursorPos); + ScreenToClient(hwnd, &cursorPos); + SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y); + } + + SDL_SetMouseFocus(NULL); } returnCode = 0; break; diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index c64749f4f..7b46d2751 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -121,6 +121,7 @@ WIN_CreateDevice(int devindex) device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer; + device->OnWindowEnter = WIN_OnWindowEnter; device->shape_driver.CreateShaper = Win32_CreateShaper; device->shape_driver.SetWindowShape = Win32_SetWindowShape; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 800349235..97db15fb2 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -678,6 +678,25 @@ SDL_HelperWindowDestroy(void) } } +void WIN_OnWindowEnter(_THIS, SDL_Window * window) +{ +#ifdef WM_MOUSELEAVE + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + TRACKMOUSEEVENT trackMouseEvent; + + if (!data || !data->hwnd) { + /* The window wasn't fully initialized */ + return; + } + + trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + trackMouseEvent.dwFlags = TME_LEAVE; + trackMouseEvent.hwndTrack = data->hwnd; + + TrackMouseEvent(&trackMouseEvent); +#endif /* WM_MOUSELEAVE */ +} + #endif /* SDL_VIDEO_DRIVER_WINDOWS */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 7339d7812..e85c20181 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -56,6 +56,7 @@ extern void WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed); extern void WIN_DestroyWindow(_THIS, SDL_Window * window); extern SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info); +extern void WIN_OnWindowEnter(_THIS, SDL_Window * window); #endif /* _SDL_windowswindow_h */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 6c54e9dc9..dac11bb0f 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -324,6 +324,10 @@ X11_DispatchEvent(_THIS) if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif + if (!SDL_GetMouse()->relative_mode) { + SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y); + } + if (xevent.xcrossing.mode != NotifyGrab && xevent.xcrossing.mode != NotifyUngrab && xevent.xcrossing.detail != NotifyInferior) {