Send mouse leave updates for Windows and X11.
authorJørgen P. Tjernø <jorgen@valvesoftware.com>
Mon, 22 Apr 2013 18:14:55 -0700
changeset 7089 257fc4e541e1
parent 7088 664d8532219b
child 7090 c4ac8be0065b
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
src/events/SDL_windowevents.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/windows/SDL_windowsevents.c
src/video/windows/SDL_windowsvideo.c
src/video/windows/SDL_windowswindow.c
src/video/windows/SDL_windowswindow.h
src/video/x11/SDL_x11events.c
--- a/src/events/SDL_mouse.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/events/SDL_mouse.c	Mon Apr 22 18:14:55 2013 -0700
@@ -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 @@
 #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 @@
 int
 SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y)
 {
+    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;
 
-    if (window && !relative) {
-        if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) {
-            return 0;
-        }
-    }
-
     /* relative motion is calculated regarding the system cursor last position */
     if (relative) {
         xrel = x;
@@ -676,4 +686,4 @@
     return shown;
 }
 
-/* vi: set ts=4 sw=4 expandtab: */
+/* vi: set ts=4 sw=4 expandtab: */
\ No newline at end of file
--- a/src/events/SDL_windowevents.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/events/SDL_windowevents.c	Mon Apr 22 18:14:55 2013 -0700
@@ -148,12 +148,14 @@
             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) {
--- a/src/video/SDL_sysvideo.h	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/SDL_sysvideo.h	Mon Apr 22 18:14:55 2013 -0700
@@ -201,6 +201,7 @@
     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_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);
--- a/src/video/SDL_video.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/SDL_video.c	Mon Apr 22 18:14:55 2013 -0700
@@ -2029,6 +2029,19 @@
 }
 
 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)
 {
     if (window->gamma && _this->SetWindowGammaRamp) {
--- a/src/video/windows/SDL_windowsevents.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/windows/SDL_windowsevents.c	Mon Apr 22 18:14:55 2013 -0700
@@ -445,10 +445,16 @@
         }
 
 #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;
--- a/src/video/windows/SDL_windowsvideo.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/windows/SDL_windowsvideo.c	Mon Apr 22 18:14:55 2013 -0700
@@ -121,6 +121,7 @@
     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;
--- a/src/video/windows/SDL_windowswindow.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/windows/SDL_windowswindow.c	Mon Apr 22 18:14:55 2013 -0700
@@ -678,6 +678,25 @@
     }
 }
 
+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: */
--- a/src/video/windows/SDL_windowswindow.h	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/windows/SDL_windowswindow.h	Mon Apr 22 18:14:55 2013 -0700
@@ -56,6 +56,7 @@
 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 */
 
--- a/src/video/x11/SDL_x11events.c	Mon Apr 22 18:14:32 2013 -0700
+++ b/src/video/x11/SDL_x11events.c	Mon Apr 22 18:14:55 2013 -0700
@@ -324,6 +324,10 @@
             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) {