Index: src/video/wincommon/SDL_lowvideo.h =================================================================== --- src/video/wincommon/SDL_lowvideo.h (revision 4067) +++ src/video/wincommon/SDL_lowvideo.h (working copy) @@ -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() \ +( \ + FULLSCREEN() && \ + (strcmp(this->name, "directx") == 0) \ +) +#define DINPUT() (strcmp(this->name, "directx") == 0) + /* The main window -- and a function to set it for the audio */ #ifdef _WIN32_WCE extern LPWSTR SDL_Appname; Index: src/video/wincommon/SDL_sysevents.c =================================================================== --- src/video/wincommon/SDL_sysevents.c (revision 4067) +++ src/video/wincommon/SDL_sysevents.c (working copy) @@ -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); - y = HIWORD(lParam); - if ( mouse_relative ) { - POINT center; - center.x = (SDL_VideoSurface->w/2); - center.y = (SDL_VideoSurface->h/2); - x -= (Sint16)center.x; - y -= (Sint16)center.y; - if ( x || y ) { - ClientToScreen(SDL_Window, ¢er); - SetCursorPos(center.x, center.y); - posted = SDL_PrivateMouseMotion(0, 1, x, y); - } - } else { -#ifdef _WIN32_WCE - if (SDL_VideoSurface) - GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y); -#endif - posted = SDL_PrivateMouseMotion(0, 0, x, y); - } - } + posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); } return(0); #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 */ - if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) { + if ( SDL_VideoSurface && ! DINPUT() ) { WORD xbuttonval = 0; Sint16 x, y; Uint8 button, state; @@ -544,20 +522,8 @@ mouse_pressed = 0; } } - if ( mouse_relative ) { - /* RJR: March 28, 2000 - report internal mouse position if in relative mode */ - x = 0; y = 0; - } else { - x = (Sint16)LOWORD(lParam); - y = (Sint16)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); + state, button, 0, 0); /* * MSDN says: @@ -578,7 +544,7 @@ #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) case WM_MOUSEWHEEL: - if ( SDL_VideoSurface && ! DINPUT_FULLSCREEN() ) { + if ( SDL_VideoSurface && ! DINPUT() ) { 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 4067) +++ src/video/windib/SDL_dibevents.c (working copy) @@ -262,6 +262,36 @@ return(DefWindowProc(hwnd, msg, wParam, lParam)); } +static void DIB_GenerateMouseMotionEvent(void) +{ + extern int mouse_relative; + extern int posted; + + POINT mouse; + GetCursorPos( &mouse ); + + if ( mouse_relative ) { + POINT center; + center.x = (SDL_VideoSurface->w/2); + center.y = (SDL_VideoSurface->h/2); + ClientToScreen(SDL_Window, ¢er); + + mouse.x -= (Sint16)center.x; + mouse.y -= (Sint16)center.y; + if ( mouse.x || mouse.y ) { + SetCursorPos(center.x, center.y); + 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, &mouse.x, &mouse.y); +#endif + posted = SDL_PrivateMouseMotion(0, 0, mouse.x, mouse.y); + } +} + void DIB_PumpEvents(_THIS) { MSG msg; @@ -271,6 +301,10 @@ DispatchMessage(&msg); } } + + if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) { + DIB_GenerateMouseMotionEvent( ); + } } static HKL hLayoutUS = NULL; Index: src/video/windx5/SDL_dx5events.c =================================================================== --- src/video/windx5/SDL_dx5events.c (revision 4067) +++ src/video/windx5/SDL_dx5events.c (working copy) @@ -143,7 +143,12 @@ (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), handle_keyboard }, { "mouse", - &GUID_SysMouse, &c_dfDIMouse, + &GUID_SysMouse, +#if DIRECTINPUT_VERSION >= 0x700 + &c_dfDIMouse2, +#else + &c_dfDIMouse, +#endif (DISCL_FOREGROUND|DISCL_NONEXCLUSIVE), (DISCL_FOREGROUND|DISCL_EXCLUSIVE), handle_mouse }, { NULL, NULL, NULL, 0, 0, NULL } @@ -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; } - /* If we are in windowed mode, Windows is taking care of the mouse */ - if ( (SDL_PublicSurface->flags & SDL_OPENGL) || - !(SDL_PublicSurface->flags & SDL_FULLSCREEN) ) { - return; - } - /* If the mouse was lost, regain some sense of mouse state */ - if ( mouse_lost ) { + if ( mouse_lost && (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { POINT mouse_pos; 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 */ +#if DIRECTINPUT_VERSION >= 0x700 + DIMOUSESTATE2 distate; +#else DIMOUSESTATE distate; +#endif HRESULT result; result=IDirectInputDevice2_GetDeviceState(SDL_DIdev[1], @@ -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: +#if DIRECTINPUT_VERSION >= 0x700 + case DIMOFS_BUTTON4: + case DIMOFS_BUTTON5: + case DIMOFS_BUTTON6: + case DIMOFS_BUTTON7: +#endif if ( xrel || yrel ) { - 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; - /* 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 ( 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); } } Index: src/video/windx5/directx.h =================================================================== --- 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 */ #define DIRECTDRAW_VERSION 0x0700 #define DIRECTSOUND_VERSION 0x0500 -#define DIRECTINPUT_VERSION 0x0500 +#define DIRECTINPUT_VERSION 0x0700 #ifdef __GNUC__ #define NONAMELESSUNION @@ -81,4 +81,20 @@ #include #include +#if DIRECTINPUT_VERSION >= 0x0700 && !defined(DIMOFS_BUTTON4) +typedef struct _DIMOUSESTATE2 { + LONG lX; + LONG lY; + LONG lZ; + BYTE rgbButtons[8]; +} DIMOUSESTATE2, *LPDIMOUSESTATE2; + +#define DIMOFS_BUTTON4 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4) +#define DIMOFS_BUTTON5 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5) +#define DIMOFS_BUTTON6 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6) +#define DIMOFS_BUTTON7 (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7) + +extern const DIDATAFORMAT c_dfDIMouse2; +#endif + #endif /* _directx_h */ Index: configure.in =================================================================== --- configure.in (revision 4067) +++ configure.in (working copy) @@ -2442,7 +2442,7 @@ # Set up the system libraries we need EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm" if test x$have_directx = xyes; then - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldxguid" + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ldxguid -ldinput8" fi # The Win32 platform requires special setup SOURCES="$SOURCES $srcdir/src/main/win32/*.rc"