Added a userdata parameter for event filters. SDL-1.3
authorSam Lantinga <slouken@libsdl.org>
Fri, 30 Jun 2006 08:18:44 +0000
branchSDL-1.3
changeset 1722 5daa04d862f1
parent 1721 1cc762cafff8
child 1723 4bdbb9b2bd0a
Added a userdata parameter for event filters. Added a function to filter the existing queued events. Added explicit support for relative mouse mode to the API.
include/SDL_events.h
include/SDL_mouse.h
include/SDL_video.h
src/SDL_compat.c
src/audio/SDL_mixer_MMX_VC.c
src/events/SDL_events.c
src/events/SDL_events_c.h
src/events/SDL_keyboard.c
src/events/SDL_mouse.c
src/events/SDL_mouse_c.h
src/events/SDL_quit.c
src/events/SDL_windowevents.c
src/joystick/SDL_joystick.c
src/video/win32/SDL_win32events.c
src/video/win32/SDL_win32video.h
src/video/win32/SDL_win32window.c
src/video/win32/SDL_win32window.h
--- a/include/SDL_events.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/include/SDL_events.h	Fri Jun 30 08:18:44 2006 +0000
@@ -377,7 +377,7 @@
 
   The filter is protypted as:
 */
-typedef int (SDLCALL * SDL_EventFilter) (SDL_Event * event);
+typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
 /*
   If the filter returns 1, then the event will be added to the internal queue.
   If it returns 0, then the event will be dropped from the queue, but the 
@@ -394,13 +394,21 @@
   If the quit event is generated by an interrupt signal, it will bypass the
   internal queue and be delivered to the application at the next event poll.
 */
-extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter);
+extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter,
+                                                void *userdata);
 
 /*
   Return the current event filter - can be used to "chain" filters.
   If there is no event filter set, this function returns NULL.
 */
-extern DECLSPEC SDL_EventFilter SDLCALL SDL_GetEventFilter(void);
+extern DECLSPEC SDL_EventFilter SDLCALL SDL_GetEventFilter(void **userdata);
+
+/*
+  Run the filter function on the current event queue, removing any
+  events for which the filter returns 0.
+*/
+extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
+                                              void *userdata);
 
 /*
   This function allows you to set the state of processing certain events.
--- a/include/SDL_mouse.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/include/SDL_mouse.h	Fri Jun 30 08:18:44 2006 +0000
@@ -75,9 +75,38 @@
 extern DECLSPEC SDL_WindowID SDLCALL SDL_GetMouseFocusWindow(void);
 
 /**
+ * \fn int SDL_SetRelativeMouseMode(SDL_bool enabled)
+ *
+ * \brief Set relative mouse mode for the currently selected mouse.
+ *
+ * \param enabled Whether or not to enable relative mode
+ *
+ * \return 0 on success, or -1 if relative mode is not supported.
+ *
+ * While the mouse is in relative mode, the cursor is hidden, and the
+ * driver will try to report continuous motion in the current window.
+ * Only relative motion events will be delivered, the mouse position
+ * will not change.
+ *
+ * \note This function will flush any pending mouse motion.
+ *
+ * \sa SDL_GetRelativeMouseMode()
+ */
+extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
+
+/**
+ * \fn SDL_bool SDL_GetRelativeMouseMode()
+ *
+ * \brief Query whether relative mouse mode is enabled for the currently selected mouse.
+ *
+ * \sa SDL_SetRelativeMouseMode()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode();
+
+/**
  * \fn Uint8 SDL_GetMouseState(int *x, int *y)
  *
- * \brief Retrieve the current state of the mouse.
+ * \brief Retrieve the current state of the currently selected mouse.
  *
  * The current button state is returned as a button bitmask, which can
  * be tested using the SDL_BUTTON(X) macros, and x and y are set to the
@@ -89,7 +118,7 @@
 /**
  * \fn Uint8 SDL_GetRelativeMouseState(int *x, int *y)
  *
- * \brief Retrieve the current state of the mouse.
+ * \brief Retrieve the state of the currently selected mouse.
  *
  * The current button state is returned as a button bitmask, which can
  * be tested using the SDL_BUTTON(X) macros, and x and y are set to the
--- a/include/SDL_video.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/include/SDL_video.h	Fri Jun 30 08:18:44 2006 +0000
@@ -120,8 +120,8 @@
     SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */
     SDL_WINDOW_BORDERLESS = 0x00000008,         /**< no window decoration */
     SDL_WINDOW_RESIZABLE = 0x00000010,          /**< window can be resized */
-    SDL_WINDOW_MAXIMIZED = 0x00000020,          /**< maximized */
-    SDL_WINDOW_MINIMIZED = 0x00000040,          /**< minimized */
+    SDL_WINDOW_MINIMIZED = 0x00000020,          /**< minimized */
+    SDL_WINDOW_MAXIMIZED = 0x00000040,          /**< maximized */
     SDL_WINDOW_INPUT_GRABBED = 0x00000100,      /**< window has grabbed input focus */
     SDL_WINDOW_KEYBOARD_FOCUS = 0x00000200,     /**< window has keyboard focus */
     SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */
--- a/src/SDL_compat.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/SDL_compat.c	Fri Jun 30 08:18:44 2006 +0000
@@ -153,10 +153,11 @@
     return modes;
 }
 
-static int (*orig_eventfilter) (SDL_Event * event);
+static SDL_EventFilter orig_eventfilter;
+static void *orig_eventfilterparam;
 
 static int
-SDL_CompatEventFilter(SDL_Event * event)
+SDL_CompatEventFilter(void *userdata, SDL_Event * event)
 {
     SDL_Event fake;
 
@@ -227,7 +228,7 @@
         }
     }
     if (orig_eventfilter) {
-        return orig_eventfilter(event);
+        return orig_eventfilter(orig_eventfilterparam, event);
     } else {
         return 1;
     }
@@ -251,7 +252,8 @@
 SDL_Surface *
 SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
 {
-    int (*filter) (SDL_Event * event);
+    SDL_EventFilter filter;
+    void *filterparam;
     const SDL_DisplayMode *desktop_mode;
     SDL_DisplayMode mode;
     Uint32 window_flags;
@@ -280,11 +282,12 @@
     SDL_DestroyWindow(SDL_VideoWindow);
 
     /* Set up the event filter */
-    filter = SDL_GetEventFilter();
+    filter = SDL_GetEventFilter(&filterparam);
     if (filter != SDL_CompatEventFilter) {
         orig_eventfilter = filter;
+        orig_eventfilterparam = filterparam;
     }
-    SDL_SetEventFilter(SDL_CompatEventFilter);
+    SDL_SetEventFilter(SDL_CompatEventFilter, NULL);
 
     /* Create a new window */
     window_flags = SDL_WINDOW_SHOWN;
--- a/src/audio/SDL_mixer_MMX_VC.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/audio/SDL_mixer_MMX_VC.c	Fri Jun 30 08:18:44 2006 +0000
@@ -184,3 +184,5 @@
 }
 
 #endif /* SDL_ASSEMBLY_ROUTINES */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/events/SDL_events.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_events.c	Fri Jun 30 08:18:44 2006 +0000
@@ -34,6 +34,7 @@
 
 /* Public data -- the event filter */
 SDL_EventFilter SDL_EventOK = NULL;
+void *SDL_EventOKParam;
 Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
 static Uint32 SDL_eventstate = 0;
 
@@ -434,19 +435,41 @@
 }
 
 void
-SDL_SetEventFilter(SDL_EventFilter filter)
+SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
 {
     SDL_Event bitbucket;
 
     /* Set filter and discard pending events */
     SDL_EventOK = filter;
+    SDL_EventOKParam = userdata;
     while (SDL_PollEvent(&bitbucket) > 0);
 }
 
 SDL_EventFilter
-SDL_GetEventFilter(void)
+SDL_GetEventFilter(void **userdata)
+{
+    if (userdata) {
+        *userdata = SDL_EventOKParam;
+    }
+    return (SDL_EventOK);
+}
+
+void
+SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
 {
-    return (SDL_EventOK);
+    if (SDL_mutexP(SDL_EventQ.lock) == 0) {
+        int spot;
+
+        spot = SDL_EventQ.head;
+        while (spot != SDL_EventQ.tail) {
+            if (filter(userdata, &SDL_EventQ.event[spot])) {
+                spot = (spot + 1) % MAXEVENTS;
+            } else {
+                spot = SDL_CutEvent(spot);
+            }
+        }
+    }
+    SDL_mutexV(SDL_EventQ.lock);
 }
 
 Uint8
@@ -507,7 +530,8 @@
         SDL_memset(&event, 0, sizeof(event));
         event.type = SDL_SYSWMEVENT;
         event.syswm.msg = message;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
--- a/src/events/SDL_events_c.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_events_c.h	Fri Jun 30 08:18:44 2006 +0000
@@ -41,6 +41,7 @@
 
 /* The event filter function */
 extern SDL_EventFilter SDL_EventOK;
+extern void *SDL_EventOKParam;
 
 /* The array of event processing states */
 extern Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
--- a/src/events/SDL_keyboard.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_keyboard.c	Fri Jun 30 08:18:44 2006 +0000
@@ -632,7 +632,7 @@
             keyboard->repeat.firsttime = 1;
             keyboard->repeat.timestamp = 1;
         }
-        if ((SDL_EventOK == NULL) || SDL_EventOK(&event)) {
+        if ((SDL_EventOK == NULL) || SDL_EventOK(SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -669,7 +669,8 @@
                 if (interval > (Uint32) keyboard->repeat.interval) {
                     keyboard->repeat.timestamp = now;
                     if ((SDL_EventOK == NULL)
-                        || SDL_EventOK(&keyboard->repeat.evt)) {
+                        || SDL_EventOK(SDL_EventOKParam,
+                                       &keyboard->repeat.evt)) {
                         SDL_PushEvent(&keyboard->repeat.evt);
                     }
                 }
--- a/src/events/SDL_mouse.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_mouse.c	Fri Jun 30 08:18:44 2006 +0000
@@ -165,6 +165,56 @@
     return mouse->focus;
 }
 
+static int
+FlushMouseMotion(void *param, SDL_Event * event)
+{
+    if (event->type == SDL_MOUSEMOTION
+        && event->motion.which == (Uint8) SDL_current_mouse) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+int
+SDL_SetRelativeMouseMode(SDL_bool enabled)
+{
+    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+
+    if (!mouse) {
+        return -1;
+    }
+
+    /* Flush pending mouse motion */
+    mouse->flush_motion = SDL_TRUE;
+    SDL_PumpEvents();
+    mouse->flush_motion = SDL_FALSE;
+    SDL_FilterEvents(FlushMouseMotion, mouse);
+
+    /* Set the relative mode */
+    mouse->relative_mode = enabled;
+
+    /* Update cursor visibility */
+    SDL_SetCursor(NULL);
+
+    if (!enabled) {
+        /* Restore the expected mouse position */
+        SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
+    }
+    return 0;
+}
+
+SDL_bool
+SDL_GetRelativeMouseMode()
+{
+    SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse);
+
+    if (!mouse) {
+        return SDL_FALSE;
+    }
+    return mouse->relative_mode;
+}
+
 Uint8
 SDL_GetMouseState(int *x, int *y)
 {
@@ -224,7 +274,7 @@
     int xrel;
     int yrel;
 
-    if (!mouse) {
+    if (!mouse || mouse->flush_motion) {
         return 0;
     }
 
@@ -252,13 +302,16 @@
     }
 
     /* Update internal mouse state */
-    mouse->x = x;
-    mouse->y = y;
+    if (!mouse->relative_mode) {
+        mouse->x = x;
+        mouse->y = y;
+    }
     mouse->xdelta += xrel;
     mouse->ydelta += yrel;
 
     /* Move the mouse cursor, if needed */
-    if (mouse->MoveCursor && mouse->cur_cursor) {
+    if (mouse->cursor_shown && !mouse->relative_mode &&
+        mouse->MoveCursor && mouse->cur_cursor) {
         mouse->MoveCursor(mouse->cur_cursor);
     }
 
@@ -274,7 +327,8 @@
         event.motion.xrel = xrel;
         event.motion.yrel = yrel;
         event.motion.windowID = mouse->focus;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -332,7 +386,8 @@
         event.button.x = mouse->x;
         event.button.y = mouse->y;
         event.button.windowID = mouse->focus;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -457,7 +512,7 @@
         cursor = mouse->cur_cursor;
     }
 
-    if (cursor && mouse->cursor_shown) {
+    if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
         if (mouse->ShowCursor) {
             mouse->ShowCursor(cursor);
         }
--- a/src/events/SDL_mouse_c.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_mouse_c.h	Fri Jun 30 08:18:44 2006 +0000
@@ -63,6 +63,8 @@
     int xdelta;
     int ydelta;
     Uint8 buttonstate;
+    SDL_bool relative_mode;
+    SDL_bool flush_motion;
 
     SDL_Cursor *cursors;
     SDL_Cursor *def_cursor;
--- a/src/events/SDL_quit.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_quit.c	Fri Jun 30 08:18:44 2006 +0000
@@ -88,7 +88,8 @@
     if (SDL_ProcessEvents[SDL_QUIT] == SDL_ENABLE) {
         SDL_Event event;
         event.type = SDL_QUIT;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
--- a/src/events/SDL_windowevents.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/events/SDL_windowevents.c	Fri Jun 30 08:18:44 2006 +0000
@@ -25,12 +25,75 @@
 
 #include "SDL_events.h"
 #include "SDL_events_c.h"
+#include "../video/SDL_sysvideo.h"
 
 int
 SDL_PrivateWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1,
                        int data2)
 {
     int posted;
+    SDL_Window *window;
+
+    window = SDL_GetWindowFromID(windowID);
+    if (!window) {
+        return 0;
+    }
+    switch (windowevent) {
+    case SDL_WINDOWEVENT_SHOWN:
+        if (window->flags & SDL_WINDOW_SHOWN) {
+            return 0;
+        }
+        window->flags |= SDL_WINDOW_SHOWN;
+        break;
+    case SDL_WINDOWEVENT_HIDDEN:
+        if (!(window->flags & SDL_WINDOW_SHOWN)) {
+            return 0;
+        }
+        window->flags &= ~SDL_WINDOW_SHOWN;
+        break;
+    case SDL_WINDOWEVENT_MINIMIZED:
+        if (window->flags & SDL_WINDOW_MINIMIZED) {
+            return 0;
+        }
+        window->flags |= SDL_WINDOW_MINIMIZED;
+        break;
+    case SDL_WINDOWEVENT_MAXIMIZED:
+        if (window->flags & SDL_WINDOW_MAXIMIZED) {
+            return 0;
+        }
+        window->flags |= SDL_WINDOW_MAXIMIZED;
+        break;
+    case SDL_WINDOWEVENT_RESTORED:
+        if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
+            return 0;
+        }
+        window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
+        break;
+    case SDL_WINDOWEVENT_ENTER:
+        if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
+            return 0;
+        }
+        window->flags |= SDL_WINDOW_MOUSE_FOCUS;
+        break;
+    case SDL_WINDOWEVENT_LEAVE:
+        if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
+            return 0;
+        }
+        window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
+        break;
+    case SDL_WINDOWEVENT_FOCUS_GAINED:
+        if (window->flags & SDL_WINDOW_KEYBOARD_FOCUS) {
+            return 0;
+        }
+        window->flags |= SDL_WINDOW_KEYBOARD_FOCUS;
+        break;
+    case SDL_WINDOWEVENT_FOCUS_LOST:
+        if (!(window->flags & SDL_WINDOW_KEYBOARD_FOCUS)) {
+            return 0;
+        }
+        window->flags &= ~SDL_WINDOW_KEYBOARD_FOCUS;
+        break;
+    }
 
     /* Post the event, if desired */
     posted = 0;
@@ -41,7 +104,8 @@
         event.window.data1 = data1;
         event.window.data2 = data2;
         event.window.windowID = windowID;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
--- a/src/joystick/SDL_joystick.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/joystick/SDL_joystick.c	Fri Jun 30 08:18:44 2006 +0000
@@ -448,7 +448,8 @@
         event.jaxis.which = joystick->index;
         event.jaxis.axis = axis;
         event.jaxis.value = value;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -474,7 +475,8 @@
         event.jhat.which = joystick->index;
         event.jhat.hat = hat;
         event.jhat.value = value;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -503,7 +505,8 @@
         event.jball.ball = ball;
         event.jball.xrel = xrel;
         event.jball.yrel = yrel;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
@@ -542,7 +545,8 @@
         event.jbutton.which = joystick->index;
         event.jbutton.button = button;
         event.jbutton.state = state;
-        if ((SDL_EventOK == NULL) || (*SDL_EventOK) (&event)) {
+        if ((SDL_EventOK == NULL)
+            || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
             posted = 1;
             SDL_PushEvent(&event);
         }
--- a/src/video/win32/SDL_win32events.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/video/win32/SDL_win32events.c	Fri Jun 30 08:18:44 2006 +0000
@@ -22,21 +22,363 @@
 #include "SDL_config.h"
 
 #include "SDL_win32video.h"
+#include "../../events/SDL_events_c.h"
 
 
 LRESULT CALLBACK
 WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     SDL_WindowData *data;
-    SDL_Window *window;
 
     /* Get the window data for the window */
     data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
     if (!data) {
         return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
     }
-    window = data->window;
+#if 0
+    switch (msg) {
+
+    case WM_ACTIVATE:
+        {
+            BOOL minimized;
+
+            minimized = HIWORD(wParam);
+            if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
+                SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN,
+                                       0, 0);
+                SDL_PrivateWindowEvent(data->windowID,
+                                       SDL_WINDOWEVENT_RESTORED, 0, 0);
+                if (IsZoomed(hwnd)) {
+                    SDL_PrivateWindowEvent(data->windowID,
+                                           SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+                }
+                SDL_PrivateWindowEvent(data->windowID,
+                                       SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
+                /* FIXME: Restore mode state (mode, gamma, grab) */
+                /* FIXME: Update keyboard state */
+            } else {
+                SDL_PrivateWindowEvent(data->windowID,
+                                       SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
+                if (minimized) {
+                    SDL_PrivateWindowEvent(data->windowID,
+                                           SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+                }
+                /* FIXME: Restore desktop state (mode, gamma, grab) */
+            }
+            return (0);
+        }
+        break;
+
+    case WM_MOUSEMOVE:
+        {
+            int index;
+            SDL_Mouse *mouse;
+
+            if (!
+                (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_MOUSE_FOCUS))
+            {
+                /* mouse has entered the window */
+                TRACKMOUSEEVENT tme;
+
+                tme.cbSize = sizeof(tme);
+                tme.dwFlags = TME_LEAVE;
+                tme.hwndTrack = hwnd;
+                TrackMouseEvent(&tme);
+
+                SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_ENTER,
+                                       0, 0);
+            }
+
+            index = data->videodata->mouse;
+            mouse = SDL_GetMouse(index);
+            if (mouse) {
+                int x, y;
+                /* mouse has moved within the window */
+                x = LOWORD(lParam);
+                y = HIWORD(lParam);
+                if (mouse->relative_mode) {
+                    int w, h;
+                    POINT center;
+                    SDL_GetWindowSize(data->windowID, &w, &h);
+                    center.x = (w / 2);
+                    center.y = (h / 2);
+                    x -= center.x;
+                    y -= center.y;
+                    if (x || y) {
+                        ClientToScreen(SDL_Window, &center);
+                        SetCursorPos(center.x, center.y);
+                        SDL_SendMouseMotion(index, data->windowID, 1, x, y);
+                    }
+                } else {
+                    SDL_SendMouseMotion(index, data->windowID, 0, x, y);
+                }
+            }
+        }
+        return (0);
+
+    case WM_MOUSELEAVE:
+        {
+            SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_LEAVE, 0,
+                                   0);
+        }
+        return (0);
+
+    case WM_LBUTTONDOWN:
+    case WM_LBUTTONUP:
+    case WM_MBUTTONDOWN:
+    case WM_MBUTTONUP:
+    case WM_RBUTTONDOWN:
+    case WM_RBUTTONUP:
+        {
+            int x, y;
+            Uint8 button, state;
+
+            /* DJM:
+               We want the SDL window to take focus so that
+               it acts like a normal windows "component"
+               (e.g. gains keyboard focus on a mouse click).
+             */
+            SetFocus(SDL_Window);
+
+            /* Figure out which button to use */
+            switch (msg) {
+            case WM_LBUTTONDOWN:
+                button = SDL_BUTTON_LEFT;
+                state = SDL_PRESSED;
+                break;
+            case WM_LBUTTONUP:
+                button = SDL_BUTTON_LEFT;
+                state = SDL_RELEASED;
+                break;
+            case WM_MBUTTONDOWN:
+                button = SDL_BUTTON_MIDDLE;
+                state = SDL_PRESSED;
+                break;
+            case WM_MBUTTONUP:
+                button = SDL_BUTTON_MIDDLE;
+                state = SDL_RELEASED;
+                break;
+            case WM_RBUTTONDOWN:
+                button = SDL_BUTTON_RIGHT;
+                state = SDL_PRESSED;
+                break;
+            case WM_RBUTTONUP:
+                button = SDL_BUTTON_RIGHT;
+                state = SDL_RELEASED;
+                break;
+            default:
+                /* Eh? Unknown button? */
+                return (0);
+            }
+            if (state == SDL_PRESSED) {
+                /* Grab mouse so we get up events */
+                if (++mouse_pressed > 0) {
+                    SetCapture(hwnd);
+                }
+            } else {
+                /* Release mouse after all up events */
+                if (--mouse_pressed <= 0) {
+                    ReleaseCapture();
+                    mouse_pressed = 0;
+                }
+            }
+            x = LOWORD(lParam);
+            y = HIWORD(lParam);
+#ifdef _WIN32_WCE
+            if (SDL_VideoSurface)
+                GapiTransform(this->hidden->userOrientation,
+                              this->hidden->hiresFix, &x, &y);
+#endif
+            posted = SDL_PrivateMouseButton(state, button, x, y);
+        }
+
+        return (0);
+
 
+#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
+    case WM_MOUSEWHEEL:
+        if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) {
+            int move = (short) HIWORD(wParam);
+            if (move) {
+                Uint8 button;
+                if (move > 0)
+                    button = SDL_BUTTON_WHEELUP;
+                else
+                    button = SDL_BUTTON_WHEELDOWN;
+                posted = SDL_PrivateMouseButton(SDL_PRESSED, button, 0, 0);
+                posted |= SDL_PrivateMouseButton(SDL_RELEASED, button, 0, 0);
+            }
+        }
+        return (0);
+#endif
+
+#ifdef WM_GETMINMAXINFO
+        /* This message is sent as a way for us to "check" the values
+         * of a position change.  If we don't like it, we can adjust
+         * the values before they are changed.
+         */
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO *info;
+            RECT size;
+            int x, y;
+            int style;
+            int width;
+            int height;
+
+            /* We don't want to clobber an internal resize */
+            if (SDL_resizing)
+                return (0);
+
+            /* We allow resizing with the SDL_RESIZABLE flag */
+            if (SDL_PublicSurface
+                && (SDL_PublicSurface->flags & SDL_RESIZABLE)) {
+                return (0);
+            }
+
+            /* Get the current position of our window */
+            GetWindowRect(SDL_Window, &size);
+            x = size.left;
+            y = size.top;
+
+            /* Calculate current width and height of our window */
+            size.top = 0;
+            size.left = 0;
+            if (SDL_PublicSurface != NULL) {
+                size.bottom = SDL_PublicSurface->h;
+                size.right = SDL_PublicSurface->w;
+            } else {
+                size.bottom = 0;
+                size.right = 0;
+            }
+
+            /* DJM - according to the docs for GetMenu(), the
+               return value is undefined if hwnd is a child window.
+               Aparently it's too difficult for MS to check
+               inside their function, so I have to do it here.
+             */
+            style = GetWindowLong(hwnd, GWL_STYLE);
+            AdjustWindowRect(&size,
+                             style,
+                             style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) !=
+                             NULL);
+
+            width = size.right - size.left;
+            height = size.bottom - size.top;
+
+            /* Fix our size to the current size */
+            info = (MINMAXINFO *) lParam;
+            info->ptMaxSize.x = width;
+            info->ptMaxSize.y = height;
+            info->ptMaxPosition.x = x;
+            info->ptMaxPosition.y = y;
+            info->ptMinTrackSize.x = width;
+            info->ptMinTrackSize.y = height;
+            info->ptMaxTrackSize.x = width;
+            info->ptMaxTrackSize.y = height;
+        }
+
+        return (0);
+#endif /* WM_GETMINMAXINFO */
+
+    case WM_WINDOWPOSCHANGED:
+        {
+            SDL_VideoDevice *this = current_video;
+            int w, h;
+
+            GetClientRect(SDL_Window, &SDL_bounds);
+            ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds);
+            ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds + 1);
+            if (!SDL_resizing && !IsZoomed(SDL_Window) &&
+                SDL_PublicSurface
+                && !(SDL_PublicSurface->flags & SDL_FULLSCREEN)) {
+                SDL_windowX = SDL_bounds.left;
+                SDL_windowY = SDL_bounds.top;
+            }
+            w = SDL_bounds.right - SDL_bounds.left;
+            h = SDL_bounds.bottom - SDL_bounds.top;
+            if (this->input_grab != SDL_GRAB_OFF) {
+                ClipCursor(&SDL_bounds);
+            }
+            if (SDL_PublicSurface
+                && (SDL_PublicSurface->flags & SDL_RESIZABLE)) {
+                SDL_PrivateResize(w, h);
+            }
+        }
+
+        break;
+
+        /* We need to set the cursor */
+    case WM_SETCURSOR:
+        {
+            Uint16 hittest;
+
+            hittest = LOWORD(lParam);
+            if (hittest == HTCLIENT) {
+                SetCursor(SDL_hcursor);
+                return (TRUE);
+            }
+        }
+
+        break;
+
+        /* We are about to get palette focus! */
+    case WM_QUERYNEWPALETTE:
+        {
+            WIN_RealizePalette(current_video);
+            return (TRUE);
+        }
+
+        break;
+
+        /* Another application changed the palette */
+    case WM_PALETTECHANGED:
+        {
+            WIN_PaletteChanged(current_video, (HWND) wParam);
+        }
+
+        break;
+
+        /* We were occluded, refresh our display */
+    case WM_PAINT:
+        {
+            HDC hdc;
+            PAINTSTRUCT ps;
+
+            hdc = BeginPaint(SDL_Window, &ps);
+            if (current_video->screen &&
+                !(current_video->screen->flags & SDL_INTERNALOPENGL)) {
+                WIN_WinPAINT(current_video, hdc);
+            }
+            EndPaint(SDL_Window, &ps);
+        }
+
+        return (0);
+
+        /* DJM: Send an expose event in this case */
+    case WM_ERASEBKGND:
+        {
+            posted = SDL_PrivateExpose();
+        }
+
+        return (0);
+
+    case WM_CLOSE:
+        {
+            if ((posted = SDL_PrivateQuit()))
+                PostQuitMessage(0);
+        }
+
+        return (0);
+
+    case WM_DESTROY:
+        {
+            PostQuitMessage(0);
+        }
+
+        return (0);
+    }
+#endif
     return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
 }
 
--- a/src/video/win32/SDL_win32video.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/video/win32/SDL_win32video.h	Fri Jun 30 08:18:44 2006 +0000
@@ -45,7 +45,7 @@
 
 /* Private display data */
 
-typedef struct
+typedef struct SDL_VideoData
 {
     int mouse;
     int keyboard;
--- a/src/video/win32/SDL_win32window.c	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/video/win32/SDL_win32window.c	Fri Jun 30 08:18:44 2006 +0000
@@ -40,9 +40,10 @@
         SDL_OutOfMemory();
         return -1;
     }
-    data->window = window;
+    data->windowID = window->id;
     data->hwnd = hwnd;
     data->created = created;
+    data->videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
 
     /* Associate the data with the window */
     if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
--- a/src/video/win32/SDL_win32window.h	Fri Jun 30 05:50:35 2006 +0000
+++ b/src/video/win32/SDL_win32window.h	Fri Jun 30 08:18:44 2006 +0000
@@ -29,10 +29,11 @@
 
 typedef struct
 {
-    SDL_Window *window;
+    SDL_WindowID windowID;
     HWND hwnd;
     WNDPROC wndproc;
     BOOL created;
+    struct SDL_VideoData *videodata;
 } SDL_WindowData;
 
 extern int WIN_CreateWindow(_THIS, SDL_Window * window);