Don't need to use raw input to track the mouse during mouse capture (thanks Brick!)
parent
0b6a821188
commit
5e89b3c89e
|
@ -742,6 +742,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
|
||||||
|
if (!data->mouse_tracked) {
|
||||||
|
TRACKMOUSEEVENT trackMouseEvent;
|
||||||
|
|
||||||
|
trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
|
trackMouseEvent.dwFlags = TME_LEAVE;
|
||||||
|
trackMouseEvent.hwndTrack = data->hwnd;
|
||||||
|
|
||||||
|
if (TrackMouseEvent(&trackMouseEvent)) {
|
||||||
|
data->mouse_tracked = SDL_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
||||||
/* Only generate mouse events for real mouse */
|
/* Only generate mouse events for real mouse */
|
||||||
if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
|
if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
|
||||||
|
@ -781,13 +794,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM 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 isRelative = mouse->relative_mode || mouse->relative_mode_warp;
|
||||||
const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
|
|
||||||
|
|
||||||
/* Relative mouse motion is delivered to the window with keyboard focus */
|
/* Relative mouse motion is delivered to the window with keyboard focus */
|
||||||
if (!isRelative || data->window != SDL_GetKeyboardFocus()) {
|
if (!isRelative || data->window != SDL_GetKeyboardFocus()) {
|
||||||
if (!isCapture) {
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
|
GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
|
||||||
|
@ -910,28 +920,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data, mouseID);
|
WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data, mouseID);
|
||||||
|
|
||||||
} 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;
|
|
||||||
RECT hwndRect;
|
|
||||||
HWND currentHnd;
|
|
||||||
|
|
||||||
GetCursorPos(&pt);
|
|
||||||
currentHnd = WindowFromPoint(pt);
|
|
||||||
ScreenToClient(hwnd, &pt);
|
|
||||||
GetClientRect(hwnd, &hwndRect);
|
|
||||||
|
|
||||||
/* if in the window, WM_MOUSEMOVE, etc, will cover it. */
|
|
||||||
if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
|
|
||||||
SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
|
|
||||||
|
|
||||||
SDL_SendMouseMotion(data->window, mouseID, 0, (int)pt.x, (int)pt.y);
|
|
||||||
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT);
|
|
||||||
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT);
|
|
||||||
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
|
||||||
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
|
|
||||||
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
SDL_assert(0 && "Shouldn't happen");
|
SDL_assert(0 && "Shouldn't happen");
|
||||||
}
|
}
|
||||||
|
@ -951,7 +939,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef WM_MOUSELEAVE
|
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
if (!IsIconic(hwnd)) {
|
if (!IsIconic(hwnd)) {
|
||||||
|
@ -973,18 +960,16 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When WM_MOUSELEAVE is fired we can be assured that the cursor has left the window.
|
/* When WM_MOUSELEAVE is fired we can be assured that the cursor has left the window */
|
||||||
Regardless of relative mode, it is important that mouse focus is reset as there is a potential
|
if (!(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
race condition when in the process of leaving/entering relative mode, resulting in focus never
|
|
||||||
being lost. This then causes a cascading failure where SDL_WINDOWEVENT_ENTER / SDL_WINDOWEVENT_LEAVE
|
|
||||||
can stop firing permanently, due to the focus being in the wrong state and TrackMouseEvent never
|
|
||||||
resubscribing. */
|
|
||||||
if (!(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE))
|
|
||||||
SDL_SetMouseFocus(NULL);
|
SDL_SetMouseFocus(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once we get WM_MOUSELEAVE we're guaranteed that the window is no longer tracked */
|
||||||
|
data->mouse_tracked = SDL_FALSE;
|
||||||
|
|
||||||
returnCode = 0;
|
returnCode = 0;
|
||||||
break;
|
break;
|
||||||
#endif /* WM_MOUSELEAVE */
|
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
case WM_SYSKEYDOWN:
|
case WM_SYSKEYDOWN:
|
||||||
|
@ -1467,6 +1452,31 @@ static void WIN_UpdateClipCursorForWindows()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void WIN_UpdateMouseCapture()
|
||||||
|
{
|
||||||
|
SDL_Window* focusWindow = SDL_GetKeyboardFocus();
|
||||||
|
|
||||||
|
if (focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||||
|
SDL_WindowData *data = (SDL_WindowData *) focusWindow->driverdata;
|
||||||
|
|
||||||
|
if (!data->mouse_tracked) {
|
||||||
|
POINT pt;
|
||||||
|
|
||||||
|
if (GetCursorPos(&pt) && ScreenToClient(data->hwnd, &pt)) {
|
||||||
|
SDL_bool swapButtons = GetSystemMetrics(SM_SWAPBUTTON) != 0;
|
||||||
|
SDL_MouseID mouseID = SDL_GetMouse()->mouseID;
|
||||||
|
|
||||||
|
SDL_SendMouseMotion(data->window, mouseID, 0, (int)pt.x, (int)pt.y);
|
||||||
|
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_LEFT : SDL_BUTTON_RIGHT);
|
||||||
|
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, !swapButtons ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT);
|
||||||
|
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
||||||
|
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
|
||||||
|
SDL_SendMouseButton(data->window, mouseID, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* A message hook called before TranslateMessage() */
|
/* A message hook called before TranslateMessage() */
|
||||||
static SDL_WindowsMessageHook g_WindowsMessageHook = NULL;
|
static SDL_WindowsMessageHook g_WindowsMessageHook = NULL;
|
||||||
static void *g_WindowsMessageHookData = NULL;
|
static void *g_WindowsMessageHookData = NULL;
|
||||||
|
@ -1584,6 +1594,9 @@ WIN_PumpEvents(_THIS)
|
||||||
|
|
||||||
/* Update the clipping rect in case someone else has stolen it */
|
/* Update the clipping rect in case someone else has stolen it */
|
||||||
WIN_UpdateClipCursorForWindows();
|
WIN_UpdateClipCursorForWindows();
|
||||||
|
|
||||||
|
/* Update mouse capture */
|
||||||
|
WIN_UpdateMouseCapture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -292,18 +292,22 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
|
||||||
static int
|
static int
|
||||||
WIN_CaptureMouse(SDL_Window *window)
|
WIN_CaptureMouse(SDL_Window *window)
|
||||||
{
|
{
|
||||||
if (!window) {
|
if (window) {
|
||||||
SDL_Window *focusWin = SDL_GetKeyboardFocus();
|
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
|
||||||
if (focusWin) {
|
SetCapture(data->hwnd);
|
||||||
WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
|
} else {
|
||||||
|
SDL_Window *focus_window = SDL_GetMouseFocus();
|
||||||
|
|
||||||
|
if (focus_window) {
|
||||||
|
SDL_WindowData *data = (SDL_WindowData *)focus_window->driverdata;
|
||||||
|
if (!data->mouse_tracked) {
|
||||||
|
SDL_SetMouseFocus(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ReleaseCapture();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* While we were thinking of SetCapture() when designing this API in SDL,
|
return 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint32
|
static Uint32
|
||||||
|
|
|
@ -953,18 +953,6 @@ void WIN_OnWindowEnter(_THIS, SDL_Window * window)
|
||||||
if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
|
if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
|
||||||
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
|
WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WM_MOUSELEAVE
|
|
||||||
{
|
|
||||||
TRACKMOUSEEVENT trackMouseEvent;
|
|
||||||
|
|
||||||
trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
|
|
||||||
trackMouseEvent.dwFlags = TME_LEAVE;
|
|
||||||
trackMouseEvent.hwndTrack = data->hwnd;
|
|
||||||
|
|
||||||
TrackMouseEvent(&trackMouseEvent);
|
|
||||||
}
|
|
||||||
#endif /* WM_MOUSELEAVE */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -53,6 +53,7 @@ typedef struct
|
||||||
SDL_bool in_window_deactivation;
|
SDL_bool in_window_deactivation;
|
||||||
RECT cursor_clipped_rect;
|
RECT cursor_clipped_rect;
|
||||||
SDL_Point last_raw_mouse_position;
|
SDL_Point last_raw_mouse_position;
|
||||||
|
SDL_bool mouse_tracked;
|
||||||
struct SDL_VideoData *videodata;
|
struct SDL_VideoData *videodata;
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
#if SDL_VIDEO_OPENGL_EGL
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
|
|
Loading…
Reference in New Issue