sdl - use the wParam and rawinput data for mouse state rather than just the message type, fixes missing mouse up events when alt-tabing out of the window
authorSam Lantinga <slouken@libsdl.org>
Wed, 27 Feb 2013 11:39:39 -0800
changeset 6943ce87e12970f5
parent 6942 bdb9e35bc877
child 6944 e8effbc1a10e
sdl - use the wParam and rawinput data for mouse state rather than just the message type, fixes missing mouse up events when alt-tabing out of the window

CR: SamL
src/video/windows/SDL_windowsevents.c
src/video/windows/SDL_windowswindow.c
src/video/windows/SDL_windowswindow.h
     1.1 --- a/src/video/windows/SDL_windowsevents.c	Wed Feb 27 11:39:38 2013 -0800
     1.2 +++ b/src/video/windows/SDL_windowsevents.c	Wed Feb 27 11:39:39 2013 -0800
     1.3 @@ -187,6 +187,54 @@
     1.4  }
     1.5  
     1.6  
     1.7 +void 
     1.8 +WIN_CheckWParamMouseButton( SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button )
     1.9 +{
    1.10 +	if ( bwParamMousePressed && !bSDLMousePressed )
    1.11 +	{
    1.12 +		SDL_SendMouseButton(data->window, SDL_PRESSED, button);
    1.13 +	}
    1.14 +	else if ( !bwParamMousePressed && bSDLMousePressed )
    1.15 +	{
    1.16 +		SDL_SendMouseButton(data->window, SDL_RELEASED, button);
    1.17 +	}
    1.18 +}
    1.19 +
    1.20 +/*
    1.21 +* Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
    1.22 +*  so this funciton reconciles our view of the world with the current buttons reported by windows
    1.23 +*/
    1.24 +void 
    1.25 +WIN_CheckWParamMouseButtons( WPARAM wParam, SDL_WindowData *data )
    1.26 +{
    1.27 +	if ( wParam != data->mouse_button_flags )
    1.28 +	{
    1.29 +		Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
    1.30 +		WIN_CheckWParamMouseButton(  (wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
    1.31 +		WIN_CheckWParamMouseButton(  (wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE );
    1.32 +		WIN_CheckWParamMouseButton(  (wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT );
    1.33 +		WIN_CheckWParamMouseButton(  (wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
    1.34 +		WIN_CheckWParamMouseButton(  (wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
    1.35 +		data->mouse_button_flags = wParam;
    1.36 +	}
    1.37 +}
    1.38 +
    1.39 +
    1.40 +void 
    1.41 +WIN_CheckRawMouseButtons( ULONG rawButtons, SDL_WindowData *data )
    1.42 +{
    1.43 +	if ( rawButtons != data->mouse_button_flags )
    1.44 +	{
    1.45 +		Uint32 mouseFlags = SDL_GetMouseState( NULL, NULL );
    1.46 +		WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT );
    1.47 +		WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_RIGHT );
    1.48 +		WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_MIDDLE );
    1.49 +		WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1 );
    1.50 +		WIN_CheckWParamMouseButton(  (rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
    1.51 +		data->mouse_button_flags = rawButtons;
    1.52 +	}
    1.53 +}
    1.54 +
    1.55  LRESULT CALLBACK
    1.56  WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    1.57  {
    1.58 @@ -257,6 +305,10 @@
    1.59                  if (SDL_GetKeyboardFocus() != data->window) {
    1.60                      SDL_SetKeyboardFocus(data->window);
    1.61                  }
    1.62 +				/* mouse buttons may have changed state here, in theory we would need
    1.63 +				to resync them, but we will get a WM_MOUSEMOVE right away which will fix 
    1.64 +				things up
    1.65 +				*/
    1.66  
    1.67  				if(SDL_GetMouse()->relative_mode) {
    1.68  					LONG cx, cy;
    1.69 @@ -293,10 +345,20 @@
    1.70          break;
    1.71  
    1.72  	case WM_MOUSEMOVE:
    1.73 -		if(SDL_GetMouse()->relative_mode)
    1.74 -			break;
    1.75 -        SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
    1.76 -        break;
    1.77 +		if( !SDL_GetMouse()->relative_mode )
    1.78 +	        SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
    1.79 +		/* don't break here, fall through to check the wParam like the button presses */
    1.80 +	case WM_LBUTTONDOWN:
    1.81 +	case WM_LBUTTONUP:
    1.82 +	case WM_RBUTTONDOWN:
    1.83 +	case WM_RBUTTONUP:
    1.84 +	case WM_MBUTTONDOWN:
    1.85 +	case WM_MBUTTONUP:
    1.86 +	case WM_XBUTTONDOWN:
    1.87 +	case WM_XBUTTONUP:
    1.88 +		if(!SDL_GetMouse()->relative_mode)
    1.89 +			WIN_CheckWParamMouseButtons( wParam, data );
    1.90 +		break;
    1.91  
    1.92  	case WM_INPUT:
    1.93  	{
    1.94 @@ -333,44 +395,11 @@
    1.95  				initialMousePoint.x = mouse->lLastX;
    1.96  				initialMousePoint.y = mouse->lLastY;
    1.97  			}
    1.98 +			WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
    1.99  		}
   1.100  		break;
   1.101  	}
   1.102  
   1.103 -    case WM_LBUTTONDOWN:
   1.104 -        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
   1.105 -        break;
   1.106 -
   1.107 -    case WM_LBUTTONUP:
   1.108 -        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_LEFT);
   1.109 -        break;
   1.110 -
   1.111 -    case WM_RBUTTONDOWN:
   1.112 -        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_RIGHT);
   1.113 -        break;
   1.114 -
   1.115 -    case WM_RBUTTONUP:
   1.116 -        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_RIGHT);
   1.117 -        break;
   1.118 -
   1.119 -    case WM_MBUTTONDOWN:
   1.120 -        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_MIDDLE);
   1.121 -        break;
   1.122 -
   1.123 -    case WM_MBUTTONUP:
   1.124 -        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_MIDDLE);
   1.125 -        break;
   1.126 -
   1.127 -    case WM_XBUTTONDOWN:
   1.128 -        SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   1.129 -        returnCode = TRUE;
   1.130 -        break;
   1.131 -
   1.132 -    case WM_XBUTTONUP:
   1.133 -        SDL_SendMouseButton(data->window, SDL_RELEASED, SDL_BUTTON_X1 + GET_XBUTTON_WPARAM(wParam) - 1);
   1.134 -        returnCode = TRUE;
   1.135 -        break;
   1.136 -
   1.137      case WM_MOUSEWHEEL:
   1.138          {
   1.139              // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
     2.1 --- a/src/video/windows/SDL_windowswindow.c	Wed Feb 27 11:39:38 2013 -0800
     2.2 +++ b/src/video/windows/SDL_windowswindow.c	Wed Feb 27 11:39:39 2013 -0800
     2.3 @@ -89,7 +89,7 @@
     2.4      data->hwnd = hwnd;
     2.5      data->hdc = GetDC(hwnd);
     2.6      data->created = created;
     2.7 -    data->mouse_pressed = SDL_FALSE;
     2.8 +    data->mouse_button_flags = 0;
     2.9      data->videodata = videodata;
    2.10  
    2.11      window->driverdata = data;
     3.1 --- a/src/video/windows/SDL_windowswindow.h	Wed Feb 27 11:39:38 2013 -0800
     3.2 +++ b/src/video/windows/SDL_windowswindow.h	Wed Feb 27 11:39:39 2013 -0800
     3.3 @@ -32,7 +32,7 @@
     3.4      HBITMAP hbm;
     3.5      WNDPROC wndproc;
     3.6      SDL_bool created;
     3.7 -    int mouse_pressed;
     3.8 +    Uint32 mouse_button_flags;
     3.9      struct SDL_VideoData *videodata;
    3.10  } SDL_WindowData;
    3.11