Partial fix for bug 2726 - Win32 'mouse' events not applying 'SDL_TOUCH_MOUSEID'

This is a Win32-specific fix for bug 2726.  A WinRT fix for this bug was applied
separately, via https://hg.libsdl.org/SDL/rev/91f56dcad879

This fix applies SDL_TOUCH_MOUSEID to 'mouse' events coming from touch devices,
but only when relative-mouse-mode is turned OFF.  This bug is still present
when relative-mouse-mode is ON, however Microsoft does not provide documentation
on whether or not those input events (which come from WM_INPUT) can be
identified as touch-specific or not.  Unofficially, that data might be available
(via GetMessageExtraInfo()), however this patch only uses MS-documented APIs.
This commit is contained in:
David Ludwig 2014-12-20 11:45:39 -05:00
parent 719bb6fcee
commit a6df21cd00

View File

@ -45,6 +45,9 @@
#include "wmmsg.h" #include "wmmsg.h"
#endif #endif
/* For processing mouse WM_*BUTTON* and WM_MOUSEMOVE message-data from GetMessageExtraInfo() */
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
/* Masks for processing the windows KEYDOWN and KEYUP messages */ /* Masks for processing the windows KEYDOWN and KEYUP messages */
#define REPEATED_KEYMASK (1<<30) #define REPEATED_KEYMASK (1<<30)
#define EXTENDED_KEYMASK (1<<24) #define EXTENDED_KEYMASK (1<<24)
@ -196,7 +199,7 @@ WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
void void
WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button) WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID)
{ {
if (data->focus_click_pending && button == SDL_BUTTON_LEFT && !bwParamMousePressed) { if (data->focus_click_pending && button == SDL_BUTTON_LEFT && !bwParamMousePressed) {
data->focus_click_pending = SDL_FALSE; data->focus_click_pending = SDL_FALSE;
@ -204,9 +207,9 @@ WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePress
} }
if (bwParamMousePressed && !bSDLMousePressed) { if (bwParamMousePressed && !bSDLMousePressed) {
SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button); SDL_SendMouseButton(data->window, mouseID, SDL_PRESSED, button);
} else if (!bwParamMousePressed && bSDLMousePressed) { } else if (!bwParamMousePressed && bSDLMousePressed) {
SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button); SDL_SendMouseButton(data->window, mouseID, SDL_RELEASED, button);
} }
} }
@ -215,15 +218,15 @@ WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePress
* so this funciton reconciles our view of the world with the current buttons reported by windows * so this funciton reconciles our view of the world with the current buttons reported by windows
*/ */
void void
WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data) WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID)
{ {
if (wParam != data->mouse_button_flags) { if (wParam != data->mouse_button_flags) {
Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT); WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, mouseID);
WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE); WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, mouseID);
WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT); WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, mouseID);
WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1); WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, mouseID);
WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2); WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, mouseID);
data->mouse_button_flags = wParam; data->mouse_button_flags = wParam;
} }
} }
@ -235,25 +238,25 @@ WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
if (rawButtons != data->mouse_button_flags) { if (rawButtons != data->mouse_button_flags) {
Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL); Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN)) if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT); WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
if ((rawButtons & RI_MOUSE_BUTTON_1_UP)) if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT); WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN)) if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT); WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
if ((rawButtons & RI_MOUSE_BUTTON_2_UP)) if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT); WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN)) if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE); WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
if ((rawButtons & RI_MOUSE_BUTTON_3_UP)) if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE); WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN)) if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1); WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
if ((rawButtons & RI_MOUSE_BUTTON_4_UP)) if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1); WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN)) if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2); WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
if ((rawButtons & RI_MOUSE_BUTTON_5_UP)) if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2); WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
data->mouse_button_flags = rawButtons; data->mouse_button_flags = rawButtons;
} }
} }
@ -271,23 +274,23 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
keyState = GetAsyncKeyState(VK_LBUTTON); keyState = GetAsyncKeyState(VK_LBUTTON);
if (!(keyState & 0x8000)) { if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT); WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
} }
keyState = GetAsyncKeyState(VK_RBUTTON); keyState = GetAsyncKeyState(VK_RBUTTON);
if (!(keyState & 0x8000)) { if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT); WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
} }
keyState = GetAsyncKeyState(VK_MBUTTON); keyState = GetAsyncKeyState(VK_MBUTTON);
if (!(keyState & 0x8000)) { if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE); WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
} }
keyState = GetAsyncKeyState(VK_XBUTTON1); keyState = GetAsyncKeyState(VK_XBUTTON1);
if (!(keyState & 0x8000)) { if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1); WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
} }
keyState = GetAsyncKeyState(VK_XBUTTON2); keyState = GetAsyncKeyState(VK_XBUTTON2);
if (!(keyState & 0x8000)) { if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2); WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
} }
data->mouse_button_flags = 0; data->mouse_button_flags = 0;
} }
@ -410,7 +413,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
SDL_Mouse *mouse = SDL_GetMouse(); SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse->relative_mode || mouse->relative_mode_warp) { if (!mouse->relative_mode || mouse->relative_mode_warp) {
SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
SDL_SendMouseMotion(data->window, mouseID, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
} }
} }
/* don't break here, fall through to check the wParam like the button presses */ /* don't break here, fall through to check the wParam like the button presses */
@ -429,7 +433,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
SDL_Mouse *mouse = SDL_GetMouse(); SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse->relative_mode || mouse->relative_mode_warp) { if (!mouse->relative_mode || mouse->relative_mode_warp) {
WIN_CheckWParamMouseButtons(wParam, data); SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
WIN_CheckWParamMouseButtons(wParam, data, mouseID);
} }
} }
break; break;