diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index cd150fab6..14e79ca49 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -638,6 +638,7 @@ SDL_SetKeyboardFocus(SDL_Window * window) /* old window must lose an existing mouse capture. */ if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) { SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */ + SDL_UpdateMouseCapture(SDL_TRUE); SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE)); } diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 092c95f40..f95c5b71c 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -156,12 +156,8 @@ SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldVal SDL_bool auto_capture = SDL_GetStringBoolean(hint, SDL_TRUE); if (auto_capture != mouse->auto_capture) { - /* Turn off mouse capture if it's currently active because of button presses */ - if (!auto_capture && SDL_GetMouseState(NULL, NULL) != 0) { - SDL_CaptureMouse(SDL_FALSE); - } - mouse->auto_capture = auto_capture; + SDL_UpdateMouseCapture(SDL_FALSE); } } @@ -668,10 +664,7 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state /* Automatically capture the mouse while buttons are pressed */ if (mouse->auto_capture) { - SDL_bool has_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE); - if (has_buttons_pressed != had_buttons_pressed) { - SDL_CaptureMouse(has_buttons_pressed); - } + SDL_UpdateMouseCapture(SDL_FALSE); } return posted; @@ -768,6 +761,7 @@ SDL_MouseQuit(void) if (mouse->CaptureMouse) { SDL_CaptureMouse(SDL_FALSE); + SDL_UpdateMouseCapture(SDL_TRUE); } SDL_SetRelativeMouseMode(SDL_FALSE); SDL_ShowCursor(1); @@ -972,6 +966,8 @@ SDL_SetRelativeMouseMode(SDL_bool enabled) if (!enabled) { SDL_WarpMouseInWindow(focusWindow, mouse->x, mouse->y); } + + SDL_UpdateMouseCapture(SDL_FALSE); } if (!enabled) { @@ -993,39 +989,61 @@ SDL_GetRelativeMouseMode() return mouse->relative_mode; } +int +SDL_UpdateMouseCapture(SDL_bool force_release) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Window *capture_window = NULL; + + if (!mouse->CaptureMouse) { + return 0; + } + + if (!force_release) { + if (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseState(NULL, NULL) != 0)) { + if (!mouse->relative_mode) { + capture_window = SDL_GetKeyboardFocus(); + } + } + } + + if (capture_window != mouse->capture_window) { + if (mouse->capture_window) { + mouse->CaptureMouse(NULL); + mouse->capture_window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; + mouse->capture_window = NULL; + } + + if (capture_window) { + if (mouse->CaptureMouse(capture_window) < 0) { + /* CaptureMouse() will have set an error */ + return -1; + } + capture_window->flags |= SDL_WINDOW_MOUSE_CAPTURE; + } + + mouse->capture_window = capture_window; + } + return 0; +} + int SDL_CaptureMouse(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); - SDL_Window *focusWindow; - SDL_bool isCaptured; + SDL_Window *focus_window; if (!mouse->CaptureMouse) { return SDL_Unsupported(); } - focusWindow = SDL_GetKeyboardFocus(); - - isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE); - if (isCaptured == enabled) { - return 0; /* already done! */ + focus_window = SDL_GetKeyboardFocus(); + if (enabled && !focus_window) { + return SDL_SetError("No window has focus"); } + mouse->capture_desired = enabled; - if (enabled) { - if (!focusWindow) { - return SDL_SetError("No window has focus"); - } else if (mouse->CaptureMouse(focusWindow) == -1) { - return -1; /* CaptureMouse() should call SetError */ - } - focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE; - } else { - if (mouse->CaptureMouse(NULL) == -1) { - return -1; /* CaptureMouse() should call SetError */ - } - focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE; - } - - return 0; + return SDL_UpdateMouseCapture(SDL_FALSE); } SDL_Cursor * diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index e2298d981..f06934b6f 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -104,6 +104,8 @@ typedef struct Uint8 vita_touch_mouse_device; #endif SDL_bool auto_capture; + SDL_bool capture_desired; + SDL_Window *capture_window; /* Data for input source state */ int num_sources; @@ -135,6 +137,9 @@ extern void SDL_SetDefaultCursor(SDL_Cursor * cursor); /* Set the mouse focus window */ extern void SDL_SetMouseFocus(SDL_Window * window); +/* Update the mouse capture window */ +extern int SDL_UpdateMouseCapture(SDL_bool force_release); + /* Send a mouse motion event */ extern int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);