diff --git a/misc/sdl-win32-mouse-fixes.diff b/misc/sdl-win32-mouse-fixes.diff index 225e0309..817971ef 100644 --- a/misc/sdl-win32-mouse-fixes.diff +++ b/misc/sdl-win32-mouse-fixes.diff @@ -1,15 +1,36 @@ Index: src/video/wincommon/SDL_lowvideo.h =================================================================== ---- src/video/wincommon/SDL_lowvideo.h (revision 3927) +--- src/video/wincommon/SDL_lowvideo.h (revision 4067) +++ src/video/wincommon/SDL_lowvideo.h (working copy) -@@ -67,8 +67,14 @@ +@@ -51,10 +51,13 @@ + /* Hidden "this" pointer for the video functions */ + #define _THIS SDL_VideoDevice *this + ++#define FULLSCREEN() \ ++ ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) ++ + #define WINDIB_FULLSCREEN() \ + ( \ + SDL_VideoSurface && \ +- ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \ ++ FULLSCREEN() && \ + (((SDL_VideoSurface->flags & SDL_OPENGL ) == SDL_OPENGL ) || \ + ((SDL_strcmp(this->name, "windib") == 0) || \ + (SDL_strcmp(this->name, "gapi") == 0))) \ +@@ -62,13 +65,19 @@ + #define DDRAW_FULLSCREEN() \ + ( \ + SDL_VideoSurface && \ +- ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \ ++ FULLSCREEN() && \ + ((SDL_VideoSurface->flags & SDL_OPENGL ) != SDL_OPENGL ) && \ (SDL_strcmp(this->name, "directx") == 0) \ ) -#define DINPUT_FULLSCREEN() DDRAW_FULLSCREEN() +#define DINPUT_FULLSCREEN() \ +( \ -+ ((SDL_VideoSurface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) && \ ++ FULLSCREEN() && \ + (strcmp(this->name, "directx") == 0) \ +) @@ -20,11 +41,49 @@ Index: src/video/wincommon/SDL_lowvideo.h extern LPWSTR SDL_Appname; Index: src/video/wincommon/SDL_sysevents.c =================================================================== ---- src/video/wincommon/SDL_sysevents.c (revision 3927) +--- src/video/wincommon/SDL_sysevents.c (revision 4067) +++ src/video/wincommon/SDL_sysevents.c (working copy) -@@ -431,27 +431,9 @@ - posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); - } +@@ -335,7 +335,6 @@ + { + SDL_VideoDevice *this = current_video; + static int mouse_pressed = 0; +- static int in_window = 0; + #ifdef WMMSG_DEBUG + fprintf(stderr, "Received windows message: "); + if ( msg > MAX_WMMSG ) { +@@ -411,62 +410,41 @@ + break; + + case WM_MOUSEMOVE: { +- +- /* Mouse is handled by DirectInput when fullscreen */ +- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) { +- Sint16 x, y; + +- /* mouse has entered the window */ +- if ( ! in_window ) { + #ifdef WM_MOUSELEAVE ++ /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */ ++ if ( SDL_VideoSurface && !FULLSCREEN() ) { ++ /* mouse has entered the window */ ++ ++ if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + TRACKMOUSEEVENT tme; + + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = SDL_Window; + _TrackMouseEvent(&tme); ++ } ++ } + #endif /* WM_MOUSELEAVE */ +- in_window = TRUE; + +- posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); +- } ++ /* Mouse motion is handled in DIB_PumpEvents or ++ * DX5_PumpEvents, depending on the video driver ++ * in use */ - /* mouse has moved within the window */ - x = LOWORD(lParam); @@ -47,13 +106,28 @@ Index: src/video/wincommon/SDL_sysevents.c -#endif - posted = SDL_PrivateMouseMotion(0, 0, x, y); - } -+ /* Mouse motion is handled in DIB_PumpEvents or -+ * DX5_PumpEvents, depending on the video driver -+ * in use */ - } +- } ++ posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); } return(0); -@@ -480,7 +462,7 @@ + + #ifdef WM_MOUSELEAVE + case WM_MOUSELEAVE: { + +- /* Mouse is handled by DirectInput when fullscreen */ +- if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) { ++ /* No need to handle SDL_APPMOUSEFOCUS when fullscreen */ ++ if ( SDL_VideoSurface && !FULLSCREEN() ) { + /* mouse has left the window */ + /* or */ + /* Elvis has left the building! */ + posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + } +- in_window = FALSE; + } + return(0); + #endif /* WM_MOUSELEAVE */ +@@ -480,7 +458,7 @@ case WM_XBUTTONDOWN: case WM_XBUTTONUP: { /* Mouse is handled by DirectInput when fullscreen */ @@ -62,7 +136,7 @@ Index: src/video/wincommon/SDL_sysevents.c WORD xbuttonval = 0; Sint16 x, y; Uint8 button, state; -@@ -544,20 +526,8 @@ +@@ -544,20 +522,8 @@ mouse_pressed = 0; } } @@ -84,7 +158,7 @@ Index: src/video/wincommon/SDL_sysevents.c /* * MSDN says: -@@ -578,7 +548,7 @@ +@@ -578,7 +544,7 @@ #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) case WM_MOUSEWHEEL: @@ -93,11 +167,67 @@ Index: src/video/wincommon/SDL_sysevents.c int move = (short)HIWORD(wParam); if ( move ) { Uint8 button; +Index: src/video/wincommon/SDL_sysmouse.c +=================================================================== +--- src/video/wincommon/SDL_sysmouse.c (revision 4067) ++++ src/video/wincommon/SDL_sysmouse.c (working copy) +@@ -208,15 +208,20 @@ + + void WIN_WarpWMCursor(_THIS, Uint16 x, Uint16 y) + { +- if ( DDRAW_FULLSCREEN() ) { +- SDL_PrivateMouseMotion(0, 0, x, y); +- } else if ( mouse_relative) { ++ if ( mouse_relative) { + /* RJR: March 28, 2000 + leave physical cursor at center of screen if + mouse hidden and grabbed */ + SDL_PrivateMouseMotion(0, 0, x, y); + } else { + POINT pt; ++ ++ /* With DirectInput the position doesn't follow ++ * the cursor, so it is set manually */ ++ if ( DINPUT() ) { ++ SDL_PrivateMouseMotion(0, 0, x, y); ++ } ++ + pt.x = x; + pt.y = y; + ClientToScreen(SDL_Window, &pt); +@@ -227,20 +232,15 @@ + /* Update the current mouse state and position */ + void WIN_UpdateMouse(_THIS) + { +- RECT rect; + POINT pt; + +- if ( ! DDRAW_FULLSCREEN() ) { +- GetClientRect(SDL_Window, &rect); +- GetCursorPos(&pt); +- MapWindowPoints(NULL, SDL_Window, &pt, 1); +- if (PtInRect(&rect, pt) && (WindowFromPoint(pt) == SDL_Window)){ +- SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); +- SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y); +- } else { +- SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); +- } +- } ++ /* Always unset SDL_APPMOUSEFOCUS to give the WM_MOUSEMOVE event ++ * handler a chance to install a TRACKMOUSEEVENT */ ++ SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); ++ ++ GetCursorPos(&pt); ++ ScreenToClient(SDL_Window, &pt); ++ SDL_PrivateMouseMotion(0,0, (Sint16)pt.x, (Sint16)pt.y); + } + + /* Check to see if we need to enter or leave mouse relative mode */ Index: src/video/windib/SDL_dibevents.c =================================================================== ---- src/video/windib/SDL_dibevents.c (revision 3927) +--- src/video/windib/SDL_dibevents.c (revision 4067) +++ src/video/windib/SDL_dibevents.c (working copy) -@@ -262,6 +262,35 @@ +@@ -262,6 +262,36 @@ return(DefWindowProc(hwnd, msg, wParam, lParam)); } @@ -122,9 +252,10 @@ Index: src/video/windib/SDL_dibevents.c + posted = SDL_PrivateMouseMotion(0, 1, mouse.x, mouse.y); + } + } else { ++ ScreenToClient(SDL_Window, &mouse); +#ifdef _WIN32_WCE + if (SDL_VideoSurface) -+ GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y); ++ GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &mouse.x, &mouse.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, mouse.x, mouse.y); + } @@ -133,20 +264,30 @@ Index: src/video/windib/SDL_dibevents.c void DIB_PumpEvents(_THIS) { MSG msg; -@@ -271,6 +300,10 @@ +@@ -271,6 +301,11 @@ DispatchMessage(&msg); } } + -+ if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { ++ if ( SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) == ++ (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ) { + DIB_GenerateMouseMotionEvent( ); + } } static HKL hLayoutUS = NULL; +@@ -494,7 +529,7 @@ + Uint16 wchars[2]; + + GetKeyboardState(keystate); +- if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1) ++ if (SDL_ToUnicode((UINT)vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } Index: src/video/windx5/SDL_dx5events.c =================================================================== ---- src/video/windx5/SDL_dx5events.c (revision 3927) +--- src/video/windx5/SDL_dx5events.c (revision 4067) +++ src/video/windx5/SDL_dx5events.c (working copy) @@ -143,7 +143,12 @@ (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), @@ -162,7 +303,84 @@ Index: src/video/windx5/SDL_dx5events.c (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), (DISCL_FOREGROUND|DISCL_EXCLUSIVE), handle_mouse }, { NULL, NULL, NULL, 0, 0, NULL } -@@ -298,12 +303,6 @@ +@@ -285,6 +290,76 @@ + } + } + } ++ ++static void post_mouse_motion(int relative, Sint16 x, Sint16 y) ++{ ++ extern int mouse_relative; ++ ++ if ( SDL_GetAppState() & (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) == ++ (SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS) ) { ++ posted = SDL_PrivateMouseMotion( ++ 0, relative, x, y); ++ ++ if ( !mouse_relative ) { ++ /* As DirectInput reads raw device coordinates, it has no notion of ++ * cursors or absolute position. We must assume responsibility for ++ * keeping track of this. */ ++ int current_x, current_y; ++ POINT cursor; ++ RECT trap; ++ RECT window; ++ int at_edge; ++ ++ /* Get the current cursor position */ ++ SDL_GetMouseState(¤t_x, ¤t_y); ++ cursor.x = current_x; ++ cursor.y = current_y; ++ ClientToScreen(SDL_Window, &cursor); ++ ++ /* Construct a 1 pixel square RECT that is used to confine the cursor ++ * pointer to a specific pixel using ClipCursor. This is used in ++ * preference to SetCursorPos as it avoids the cursor jumping around as ++ * both the OS and SDL attempt to move it simultaneously. */ ++ trap.left = cursor.x; ++ trap.top = cursor.y; ++ trap.right = cursor.x + 1; ++ trap.bottom = cursor.y + 1; ++ ++ GetClientRect(SDL_Window, &window); ++ window.right -= window.left; window.left = 0; ++ window.bottom -= window.top; window.top = 0; ++ ++ /* As we're assuming control over the cursor, we need to know when to ++ * relinquish control of it back to the operating system. This is when ++ * the cursor reaches the edge of the window. */ ++ at_edge = (current_x == window.left) || ++ (current_x == (window.right - 1)) || ++ (current_y == window.top) || ++ (current_y == (window.bottom - 1)); ++ ++ if ( at_edge ) { ++ ClipCursor(NULL); ++ } else { ++ ClipCursor(&trap); ++ } ++ } else { ++ /* When in relative mode, warp the OS's idea of where the cursor is to ++ * the center of the screen. This isn't really necessary as DirectInput ++ * reads from the hardware itself, but in case things go wrong, the ++ * cursor will be left in a sensible place. */ ++ POINT center; ++ center.x = (SDL_VideoSurface->w/2); ++ center.y = (SDL_VideoSurface->h/2); ++ ClientToScreen(SDL_Window, ¢er); ++ SetCursorPos(center.x, center.y); ++ } ++ } else { ++ /* No window or mouse focus, control is lost */ ++ mouse_lost = 1; ++ ClipCursor(NULL); ++ } ++} ++ + static void handle_mouse(const int numevents, DIDEVICEOBJECTDATA *ptrbuf) + { + int i; +@@ -298,14 +373,8 @@ return; } @@ -173,9 +391,20 @@ Index: src/video/windx5/SDL_dx5events.c - } - /* If the mouse was lost, regain some sense of mouse state */ - if ( mouse_lost ) { +- if ( mouse_lost ) { ++ if ( mouse_lost && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { POINT mouse_pos; -@@ -320,7 +319,11 @@ + Uint8 old_state; + Uint8 new_state; +@@ -313,14 +382,17 @@ + /* Set ourselves up with the current cursor position */ + GetCursorPos(&mouse_pos); + ScreenToClient(SDL_Window, &mouse_pos); +- posted = SDL_PrivateMouseMotion(0, 0, +- (Sint16)mouse_pos.x, (Sint16)mouse_pos.y); ++ post_mouse_motion( 0, (Sint16)mouse_pos.x, (Sint16)mouse_pos.y); + + /* Check for mouse button changes */ old_state = SDL_GetMouseState(NULL, NULL); new_state = 0; { /* Get the new DirectInput button state for the mouse */ @@ -187,7 +416,59 @@ Index: src/video/windx5/SDL_dx5events.c HRESULT result; result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1], -@@ -429,6 +432,12 @@ +@@ -341,14 +413,13 @@ + for ( i=0; i<8; ++i ) { + if ( (old_state&0x01) != (new_state&0x01) ) { + button = (Uint8)(i+1); +- /* Button #2 on two button mice is button 3 +- (the middle button is button 2) +- */ +- if ( button == 2 ) { +- button = 3; +- } else +- if ( button == 3 ) { +- button = 2; ++ /* Map DI button numbers to SDL */ ++ switch ( button ) { ++ case 2: button = SDL_BUTTON_RIGHT; break; ++ case 3: button = SDL_BUTTON_MIDDLE; break; ++ case 4: button = SDL_BUTTON_X1; break; ++ case 5: button = SDL_BUTTON_X2; break; ++ default: break; + } + if ( new_state & 0x01 ) { + /* Grab mouse so we get mouse-up */ +@@ -387,8 +458,7 @@ + case DIMOFS_X: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { +- posted = SDL_PrivateMouseMotion( +- 0, 1, xrel, yrel); ++ post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } +@@ -399,8 +469,7 @@ + case DIMOFS_Y: + if ( timestamp != ptrbuf[i].dwTimeStamp ) { + if ( xrel || yrel ) { +- posted = SDL_PrivateMouseMotion( +- 0, 1, xrel, yrel); ++ post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } +@@ -410,8 +479,7 @@ + break; + case DIMOFS_Z: + if ( xrel || yrel ) { +- posted = SDL_PrivateMouseMotion( +- 0, 1, xrel, yrel); ++ post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; + } +@@ -429,22 +497,26 @@ case DIMOFS_BUTTON1: case DIMOFS_BUTTON2: case DIMOFS_BUTTON3: @@ -198,9 +479,11 @@ Index: src/video/windx5/SDL_dx5events.c + case DIMOFS_BUTTON7: +#endif if ( xrel || yrel ) { - posted = SDL_PrivateMouseMotion( - 0, 1, xrel, yrel); -@@ -437,14 +446,13 @@ +- posted = SDL_PrivateMouseMotion( +- 0, 1, xrel, yrel); ++ post_mouse_motion(1, xrel, yrel); + xrel = 0; + yrel = 0; } timestamp = 0; button = (Uint8)(ptrbuf[i].dwOfs-DIMOFS_BUTTON0)+1; @@ -222,9 +505,27 @@ Index: src/video/windx5/SDL_dx5events.c } if ( ptrbuf[i].dwData & 0x80 ) { /* Grab mouse so we get mouse-up */ +@@ -471,7 +543,7 @@ + } + } + if ( xrel || yrel ) { +- posted = SDL_PrivateMouseMotion( 0, 1, xrel, yrel); ++ post_mouse_motion(1, xrel, yrel); + } + } + +@@ -840,7 +912,7 @@ + keysym->unicode = vkey; + #else + GetKeyboardState(keystate); +- if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) == 1) ++ if (SDL_ToUnicode(vkey, scancode, keystate, wchars, sizeof(wchars)/sizeof(wchars[0]), 0) > 0) + { + keysym->unicode = wchars[0]; + } Index: src/video/windx5/directx.h =================================================================== ---- src/video/windx5/directx.h (revision 3927) +--- src/video/windx5/directx.h (revision 4067) +++ src/video/windx5/directx.h (working copy) @@ -72,7 +72,7 @@ /* We need these defines to mark what version of DirectX API we use */ @@ -258,7 +559,7 @@ Index: src/video/windx5/directx.h #endif /* _directx_h */ Index: configure.in =================================================================== ---- configure.in (revision 3927) +--- configure.in (revision 4067) +++ configure.in (working copy) @@ -2442,7 +2442,7 @@ # Set up the system libraries we need