From 819c7c0911be05cd1cbfcc3f172888ebe2ad3c0f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 30 Jun 2006 08:18:44 +0000 Subject: [PATCH] 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 | 14 +- include/SDL_mouse.h | 33 ++- include/SDL_video.h | 4 +- src/SDL_compat.c | 15 +- src/audio/SDL_mixer_MMX_VC.c | 2 + src/events/SDL_events.c | 30 ++- src/events/SDL_events_c.h | 1 + src/events/SDL_keyboard.c | 5 +- src/events/SDL_mouse.c | 69 +++++- src/events/SDL_mouse_c.h | 2 + src/events/SDL_quit.c | 3 +- src/events/SDL_windowevents.c | 66 +++++- src/joystick/SDL_joystick.c | 12 +- src/video/win32/SDL_win32events.c | 346 +++++++++++++++++++++++++++++- src/video/win32/SDL_win32video.h | 2 +- src/video/win32/SDL_win32window.c | 3 +- src/video/win32/SDL_win32window.h | 3 +- 17 files changed, 574 insertions(+), 36 deletions(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index dd6032093..669648165 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -377,7 +377,7 @@ extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event); 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 @@ typedef int (SDLCALL * SDL_EventFilter) (SDL_Event * event); 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. diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h index 92236ab4c..2525e5d80 100644 --- a/include/SDL_mouse.h +++ b/include/SDL_mouse.h @@ -74,10 +74,39 @@ extern DECLSPEC int SDLCALL SDL_SelectMouse(int index); */ 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 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetMouseState(int *x, int *y); /** * \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 diff --git a/include/SDL_video.h b/include/SDL_video.h index 2dcf07e2b..5de849499 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -120,8 +120,8 @@ typedef enum 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 */ diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 04ec3e89a..51936df8b 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -153,10 +153,11 @@ SDL_ListModes(SDL_PixelFormat * format, Uint32 flags) 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 @@ SDL_CompatEventFilter(SDL_Event * event) } } if (orig_eventfilter) { - return orig_eventfilter(event); + return orig_eventfilter(orig_eventfilterparam, event); } else { return 1; } @@ -251,7 +252,8 @@ SDL_VideoPaletteChanged(void *userdata, SDL_Palette * palette) 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_SetVideoMode(int width, int height, int bpp, Uint32 flags) 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; diff --git a/src/audio/SDL_mixer_MMX_VC.c b/src/audio/SDL_mixer_MMX_VC.c index 5611df1e4..cb7f3e39c 100644 --- a/src/audio/SDL_mixer_MMX_VC.c +++ b/src/audio/SDL_mixer_MMX_VC.c @@ -184,3 +184,5 @@ SDL_MixAudio_MMX_S8_VC(char *dst, char *src, unsigned int nSize, int volume) } #endif /* SDL_ASSEMBLY_ROUTINES */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index a89ec9175..2093b6b59 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -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,21 +435,43 @@ SDL_PushEvent(SDL_Event * event) } 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) +{ + 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 SDL_EventState(Uint8 type, int state) { @@ -507,7 +530,8 @@ SDL_PrivateSysWMEvent(SDL_SysWMmsg * message) 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); } diff --git a/src/events/SDL_events_c.h b/src/events/SDL_events_c.h index 65ea64738..bcf61e38b 100644 --- a/src/events/SDL_events_c.h +++ b/src/events/SDL_events_c.h @@ -41,6 +41,7 @@ extern void SDL_QuitQuit(void); /* 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]; diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 686698cb3..3ef6d5683 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -632,7 +632,7 @@ SDL_SendKeyboardKey(int index, SDL_WindowID windowID, Uint8 state, 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 @@ SDL_CheckKeyRepeat(void) 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); } } diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index d01af5cb7..c75c81363 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -165,6 +165,56 @@ SDL_GetMouseFocusWindow() 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 @@ SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, int x, int xrel; int yrel; - if (!mouse) { + if (!mouse || mouse->flush_motion) { return 0; } @@ -252,13 +302,16 @@ SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, int x, } /* 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 @@ SDL_SendMouseMotion(int index, SDL_WindowID windowID, int relative, int x, 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 @@ SDL_SendMouseButton(int index, SDL_WindowID windowID, Uint8 state, 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 @@ SDL_SetCursor(SDL_Cursor * cursor) cursor = mouse->cur_cursor; } - if (cursor && mouse->cursor_shown) { + if (cursor && mouse->cursor_shown && !mouse->relative_mode) { if (mouse->ShowCursor) { mouse->ShowCursor(cursor); } diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index a02a14ef2..f0b5ca927 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -63,6 +63,8 @@ struct SDL_Mouse int xdelta; int ydelta; Uint8 buttonstate; + SDL_bool relative_mode; + SDL_bool flush_motion; SDL_Cursor *cursors; SDL_Cursor *def_cursor; diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index e8fe56abd..5fca3d367 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -88,7 +88,8 @@ SDL_SendQuit(void) 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); } diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c index fd898fdf8..f4153388c 100644 --- a/src/events/SDL_windowevents.c +++ b/src/events/SDL_windowevents.c @@ -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 @@ SDL_PrivateWindowEvent(SDL_WindowID windowID, Uint8 windowevent, int data1, 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); } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index a5afd69d5..c230da858 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -448,7 +448,8 @@ SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value) 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 @@ SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value) 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 @@ SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, 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 @@ SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state) 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); } diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index d16adf31f..af0c65e2f 100644 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -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, ¢er); + 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); } diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index 3bebc5ed2..21e4a1984 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -45,7 +45,7 @@ /* Private display data */ -typedef struct +typedef struct SDL_VideoData { int mouse; int keyboard; diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index 773bad14f..ef1392113 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -40,9 +40,10 @@ SetupWindowData(SDL_Window * window, HWND hwnd, BOOL created) 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)) { diff --git a/src/video/win32/SDL_win32window.h b/src/video/win32/SDL_win32window.h index 70b861c6b..4e3a7e993 100644 --- a/src/video/win32/SDL_win32window.h +++ b/src/video/win32/SDL_win32window.h @@ -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);