Patrick Baggett implemented relative mouse mode on Win32

Here is my first rough attempt. "testrelative" feels right to me, but I'd like it someone else tested this, especially compared to Linux/OSX. The "Ctrl+r" to switch between relative and normal mouse movements seems to work flawlessly. With relative mouse movement, the only way to change focus is via keyboard. I'm not sure if that is the correct approach, but that would seem to be the most useful mode for games. Still, if my assumption is wrong, I can fix that no problem.
This commit is contained in:
Sam Lantinga 2012-07-03 23:52:02 -04:00
parent 540577559f
commit c7a5aa5128
3 changed files with 82 additions and 3 deletions

View file

@ -30,7 +30,7 @@
#define UNICODE 1 #define UNICODE 1
#endif #endif
#undef _WIN32_WINNT #undef _WIN32_WINNT
#define _WIN32_WINNT 0x500 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices() */ #define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */
#include <windows.h> #include <windows.h>

View file

@ -173,6 +173,24 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (SDL_GetKeyboardFocus() != data->window) { if (SDL_GetKeyboardFocus() != data->window) {
SDL_SetKeyboardFocus(data->window); SDL_SetKeyboardFocus(data->window);
} }
if(SDL_GetMouse()->relative_mode) {
LONG cx, cy;
RECT rect;
GetWindowRect(hwnd, &rect);
cx = (rect.left + rect.right) / 2;
cy = (rect.top + rect.bottom) / 2;
/* Make an absurdly small clip rect */
rect.left = cx-1;
rect.right = cx+1;
rect.top = cy-1;
rect.bottom = cy+1;
ClipCursor(&rect);
}
/* /*
* FIXME: Update keyboard state * FIXME: Update keyboard state
*/ */
@ -191,6 +209,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break; break;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if(SDL_GetMouse()->relative_mode)
break;
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
/* transform coords for VGA, WVGA... */ /* transform coords for VGA, WVGA... */
{ {
@ -208,6 +228,25 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam)); SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
break; break;
case WM_INPUT:
{
HRAWINPUT hRawInput = (HRAWINPUT)lParam;
RAWINPUT inp;
UINT size = sizeof(inp);
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
/* Mouse data */
if(inp.header.dwType == RIM_TYPEMOUSE)
{
RAWMOUSE* mouse = &inp.data.mouse;
if((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE)
SDL_SendMouseMotion(data->window, 1, (int)mouse->lLastX, (int)mouse->lLastY);
}
break;
}
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT); SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
break; break;

View file

@ -140,8 +140,48 @@ WIN_WarpMouse(SDL_Window * window, int x, int y)
static int static int
WIN_SetRelativeMouseMode(SDL_bool enabled) WIN_SetRelativeMouseMode(SDL_bool enabled)
{ {
SDL_Unsupported(); RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
return -1; HWND hWnd;
hWnd = GetActiveWindow();
rawMouse.hwndTarget = hWnd;
if(!enabled) {
rawMouse.dwFlags |= RIDEV_REMOVE;
rawMouse.hwndTarget = NULL;
}
/* (Un)register raw input for mice */
if(RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
/* Only return an error when registering. If we unregister and fail, then
it's probably that we unregistered twice. That's OK. */
if(enabled) {
SDL_Unsupported();
return -1;
}
}
if(enabled) {
LONG cx, cy;
RECT rect;
GetWindowRect(hWnd, &rect);
cx = (rect.left + rect.right) / 2;
cy = (rect.top + rect.bottom) / 2;
/* Make an absurdly small clip rect */
rect.left = cx-1;
rect.right = cx+1;
rect.top = cy-1;
rect.bottom = cy+1;
ClipCursor(&rect);
}
else
ClipCursor(NULL);
return 0;
} }
void void