Fixed bug 2260 - SDL_SetCursorGrab() is buggy on Windows
BurnSpamAddress Steps to reproduce: 1. Grab the cursor with SDL_SetCursorGrab() 2. Alt-tab away from the window 3. Click on the titlebar of the window This will cause the window to disappear underneath the taskbar! This appears to be a general issue with ClipCursor() on windows, i.e. I am getting the same behavior if I call ClipCursor() directly. It is caused by a feedback loop between the ClipCursor function and the modal resize/move event loop that handles mouse-based sizing on Windows.main
parent
fa4e4a643a
commit
d2511d9ef9
|
@ -286,6 +286,45 @@ WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
WIN_UpdateClipCursor(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
|
||||
/* Don't clip the cursor while we're in the modal resize or move loop */
|
||||
if (data->in_modal_loop) {
|
||||
ClipCursor(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_GetMouse()->relative_mode) {
|
||||
LONG cx, cy;
|
||||
RECT rect;
|
||||
GetWindowRect(data->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 if ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
|
||||
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
RECT rect;
|
||||
if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
|
||||
ClientToScreen(data->hwnd, (LPPOINT) & rect);
|
||||
ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
} else {
|
||||
ClipCursor(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -369,22 +408,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
WIN_CheckWParamMouseButton( ( keyState & 0x8000 ), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2 );
|
||||
data->mouse_button_flags = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
WIN_UpdateClipCursor(data->window);
|
||||
|
||||
/*
|
||||
* FIXME: Update keyboard state
|
||||
|
@ -585,6 +609,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
#endif /* WM_INPUTLANGCHANGE */
|
||||
|
||||
case WM_ENTERSIZEMOVE:
|
||||
case WM_ENTERMENULOOP:
|
||||
{
|
||||
data->in_modal_loop = SDL_TRUE;
|
||||
WIN_UpdateClipCursor(data->window);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EXITSIZEMOVE:
|
||||
case WM_EXITMENULOOP:
|
||||
{
|
||||
data->in_modal_loop = SDL_FALSE;
|
||||
WIN_UpdateClipCursor(data->window);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef WM_GETMINMAXINFO
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
|
@ -673,20 +713,14 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
RECT rect;
|
||||
int x, y;
|
||||
int w, h;
|
||||
Uint32 window_flags;
|
||||
|
||||
if (!GetClientRect(hwnd, &rect) ||
|
||||
(rect.right == rect.left && rect.bottom == rect.top)) {
|
||||
if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
|
||||
break;
|
||||
}
|
||||
ClientToScreen(hwnd, (LPPOINT) & rect);
|
||||
ClientToScreen(hwnd, (LPPOINT) & rect + 1);
|
||||
|
||||
window_flags = SDL_GetWindowFlags(data->window);
|
||||
if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
|
||||
(window_flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
WIN_UpdateClipCursor(data->window);
|
||||
|
||||
x = rect.left;
|
||||
y = rect.top;
|
||||
|
|
|
@ -207,7 +207,7 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
|
|||
|
||||
|
||||
/* (Un)register raw input for mice */
|
||||
if(RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
|
||||
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. */
|
||||
|
@ -216,7 +216,7 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
|
|||
}
|
||||
}
|
||||
|
||||
if(enabled) {
|
||||
if (enabled) {
|
||||
LONG cx, cy;
|
||||
RECT rect;
|
||||
GetWindowRect(hWnd, &rect);
|
||||
|
@ -231,10 +231,9 @@ WIN_SetRelativeMouseMode(SDL_bool enabled)
|
|||
rect.bottom = cy+1;
|
||||
|
||||
ClipCursor(&rect);
|
||||
}
|
||||
else
|
||||
} else {
|
||||
ClipCursor(NULL);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue