Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Patrick Baggett implemented relative mouse mode on Win32
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
slouken committed Jul 4, 2012
1 parent a6469c4 commit 3a57725
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/core/windows/SDL_windows.h
Expand Up @@ -30,7 +30,7 @@
#define UNICODE 1
#endif
#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>

Expand Down
39 changes: 39 additions & 0 deletions src/video/windows/SDL_windowsevents.c
Expand Up @@ -173,6 +173,24 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (SDL_GetKeyboardFocus() != 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
*/
Expand All @@ -191,6 +209,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break;

case WM_MOUSEMOVE:
if(SDL_GetMouse()->relative_mode)
break;
#ifdef _WIN32_WCE
/* transform coords for VGA, WVGA... */
{
Expand All @@ -208,6 +228,25 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_SendMouseMotion(data->window, 0, LOWORD(lParam), HIWORD(lParam));
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:
SDL_SendMouseButton(data->window, SDL_PRESSED, SDL_BUTTON_LEFT);
break;
Expand Down
44 changes: 42 additions & 2 deletions src/video/windows/SDL_windowsmouse.c
Expand Up @@ -140,8 +140,48 @@ WIN_WarpMouse(SDL_Window * window, int x, int y)
static int
WIN_SetRelativeMouseMode(SDL_bool enabled)
{
SDL_Unsupported();
return -1;
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
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
Expand Down

0 comments on commit 3a57725

Please sign in to comment.