Fixed up SDL_CaptureMouse() on Windows to work like I expected.
This would have been a one-line patch to the documentation (specifying that captures only work as long as the left mouse button is pressed), but I didn't like that, so I got a little crazy about this instead.main
parent
bcc2cc8722
commit
bb7a27fadd
|
@ -30,6 +30,7 @@
|
||||||
#include "../../events/SDL_events_c.h"
|
#include "../../events/SDL_events_c.h"
|
||||||
#include "../../events/SDL_touch_c.h"
|
#include "../../events/SDL_touch_c.h"
|
||||||
#include "../../events/scancodes_windows.h"
|
#include "../../events/scancodes_windows.h"
|
||||||
|
#include "SDL_assert.h"
|
||||||
|
|
||||||
/* Dropfile support */
|
/* Dropfile support */
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
@ -428,15 +429,20 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
HRAWINPUT hRawInput = (HRAWINPUT)lParam;
|
HRAWINPUT hRawInput = (HRAWINPUT)lParam;
|
||||||
RAWINPUT inp;
|
RAWINPUT inp;
|
||||||
UINT size = sizeof(inp);
|
UINT size = sizeof(inp);
|
||||||
|
const SDL_bool isRelative = mouse->relative_mode || mouse->relative_mode_warp;
|
||||||
|
const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
|
||||||
|
|
||||||
if (!mouse->relative_mode || mouse->relative_mode_warp || mouse->focus != data->window) {
|
if (!isRelative || mouse->focus != data->window) {
|
||||||
|
if (!isCapture) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
|
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
|
||||||
|
|
||||||
/* Mouse data */
|
/* Mouse data */
|
||||||
if (inp.header.dwType == RIM_TYPEMOUSE) {
|
if (inp.header.dwType == RIM_TYPEMOUSE) {
|
||||||
|
if (isRelative) {
|
||||||
RAWMOUSE* mouse = &inp.data.mouse;
|
RAWMOUSE* mouse = &inp.data.mouse;
|
||||||
|
|
||||||
if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
|
if ((mouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
|
||||||
|
@ -455,6 +461,23 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
initialMousePoint.y = mouse->lLastY;
|
initialMousePoint.y = mouse->lLastY;
|
||||||
}
|
}
|
||||||
WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
|
WIN_CheckRawMouseButtons( mouse->usButtonFlags, data );
|
||||||
|
} else if (isCapture) {
|
||||||
|
/* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
|
||||||
|
POINT pt;
|
||||||
|
HWND hwnd = data->hwnd;
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
if (WindowFromPoint(pt) != hwnd) { /* if in the window, WM_MOUSEMOVE, etc, will cover it. */
|
||||||
|
ScreenToClient(data->hwnd, &pt);
|
||||||
|
SDL_SendMouseMotion(data->window, 0, 0, (int) pt.x, (int) pt.y);
|
||||||
|
SDL_SendMouseButton(data->window, 0, GetKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT);
|
||||||
|
SDL_SendMouseButton(data->window, 0, GetKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT);
|
||||||
|
SDL_SendMouseButton(data->window, 0, GetKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
||||||
|
SDL_SendMouseButton(data->window, 0, GetKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
|
||||||
|
SDL_SendMouseButton(data->window, 0, GetKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDL_assert(0 && "Shouldn't happen");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -499,7 +522,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
#ifdef WM_MOUSELEAVE
|
#ifdef WM_MOUSELEAVE
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode) {
|
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
if (!IsIconic(hwnd)) {
|
if (!IsIconic(hwnd)) {
|
||||||
POINT cursorPos;
|
POINT cursorPos;
|
||||||
GetCursorPos(&cursorPos);
|
GetCursorPos(&cursorPos);
|
||||||
|
|
|
@ -30,6 +30,44 @@
|
||||||
|
|
||||||
HCURSOR SDL_cursor = NULL;
|
HCURSOR SDL_cursor = NULL;
|
||||||
|
|
||||||
|
static int rawInputEnableCount = 0;
|
||||||
|
|
||||||
|
static int
|
||||||
|
ToggleRawInput(SDL_bool enabled)
|
||||||
|
{
|
||||||
|
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
rawInputEnableCount++;
|
||||||
|
if (rawInputEnableCount > 1) {
|
||||||
|
return 0; /* already done. */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rawInputEnableCount == 0) {
|
||||||
|
return 0; /* already done. */
|
||||||
|
}
|
||||||
|
rawInputEnableCount--;
|
||||||
|
if (rawInputEnableCount > 0) {
|
||||||
|
return 0; /* not time to disable yet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
rawMouse.dwFlags |= RIDEV_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (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) {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static SDL_Cursor *
|
static SDL_Cursor *
|
||||||
WIN_CreateDefaultCursor()
|
WIN_CreateDefaultCursor()
|
||||||
|
@ -201,35 +239,25 @@ WIN_WarpMouse(SDL_Window * window, int x, int y)
|
||||||
static int
|
static int
|
||||||
WIN_SetRelativeMouseMode(SDL_bool enabled)
|
WIN_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
{
|
{
|
||||||
RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
|
return ToggleRawInput(enabled);
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
rawMouse.dwFlags |= RIDEV_REMOVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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) {
|
|
||||||
return SDL_Unsupported();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
WIN_CaptureMouse(SDL_Window *window)
|
WIN_CaptureMouse(SDL_Window *window)
|
||||||
{
|
{
|
||||||
if (!window) {
|
if (!window) {
|
||||||
ReleaseCapture();
|
SDL_Window *focusWin = SDL_GetKeyboardFocus();
|
||||||
} else {
|
if (focusWin) {
|
||||||
const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
SDL_WindowData *data = (SDL_WindowData *)focusWin->driverdata;
|
||||||
SetCapture(data->hwnd);
|
WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* While we were thinking of SetCapture() when designing this API in SDL,
|
||||||
|
we didn't count on the fact that SetCapture() only tracks while the
|
||||||
|
left mouse button is held down! Instead, we listen for raw mouse input
|
||||||
|
and manually query the mouse when it leaves the window. :/ */
|
||||||
|
return ToggleRawInput(window != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -259,6 +287,11 @@ WIN_QuitMouse(_THIS)
|
||||||
mouse->def_cursor = NULL;
|
mouse->def_cursor = NULL;
|
||||||
mouse->cur_cursor = NULL;
|
mouse->cur_cursor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rawInputEnableCount) { /* force RAWINPUT off here. */
|
||||||
|
rawInputEnableCount = 1;
|
||||||
|
ToggleRawInput(SDL_FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
|
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
|
||||||
|
|
Loading…
Reference in New Issue