Use more stringent criteria for entering warp emulation mode
Require more than one warp to the window center within a certain timespan (currently 30ms, but can be tweaked) to better avoid erroneously entering warp emulation mode. This also correctly resets the warp emulation mode activation if the window loses and regains focus.
This commit is contained in:
committed by
Sam Lantinga
parent
1a57ea7fba
commit
ae8065e1ec
@@ -33,6 +33,8 @@
|
||||
|
||||
/* #define DEBUG_MOUSE */
|
||||
|
||||
#define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30)
|
||||
|
||||
typedef struct SDL_MouseInstance
|
||||
{
|
||||
SDL_MouseID instance_id;
|
||||
@@ -1271,22 +1273,53 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_EnableWarpEmulation(SDL_Mouse *mouse)
|
||||
void SDL_DisableMouseWarpEmulation()
|
||||
{
|
||||
if (!mouse->cursor_shown && mouse->warp_emulation_hint && !mouse->warp_emulation_prohibited) {
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) {
|
||||
mouse->warp_emulation_active = SDL_TRUE;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->warp_emulation_active) {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
}
|
||||
|
||||
mouse->warp_emulation_prohibited = SDL_TRUE;
|
||||
}
|
||||
|
||||
static void SDL_MaybeEnableWarpEmulation(SDL_Window *window, float x, float y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (!mouse->warp_emulation_prohibited && mouse->warp_emulation_hint && !mouse->cursor_shown && !mouse->warp_emulation_active) {
|
||||
if (!window) {
|
||||
window = mouse->focus;
|
||||
}
|
||||
|
||||
/* Disable attempts at enabling warp emulation until further notice. */
|
||||
mouse->warp_emulation_prohibited = SDL_TRUE;
|
||||
if (window) {
|
||||
const float cx = window->w / 2.f;
|
||||
const float cy = window->h / 2.f;
|
||||
if (x >= SDL_floorf(cx) && x <= SDL_ceilf(cx) &&
|
||||
y >= SDL_floorf(cy) && y <= SDL_ceilf(cy)) {
|
||||
|
||||
/* Require two consecutive warps to the center within a certain timespan to enter warp emulation mode. */
|
||||
const Uint64 now = SDL_GetTicksNS();
|
||||
if (now - mouse->last_center_warp_time_ns < WARP_EMULATION_THRESHOLD_NS) {
|
||||
if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) {
|
||||
mouse->warp_emulation_active = SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
mouse->last_center_warp_time_ns = now;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mouse->last_center_warp_time_ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_WarpMouseInWindow(SDL_Window *window, float x, float y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_EnableWarpEmulation(mouse);
|
||||
SDL_MaybeEnableWarpEmulation(window, x, y);
|
||||
|
||||
SDL_PerformWarpMouseInWindow(window, x, y, mouse->warp_emulation_active);
|
||||
}
|
||||
@@ -1317,16 +1350,9 @@ int SDL_SetRelativeMouseMode(SDL_bool enabled)
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Window *focusWindow = SDL_GetKeyboardFocus();
|
||||
|
||||
if (enabled) {
|
||||
if (mouse->warp_emulation_active) {
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* If the app has used relative mode before, it probably shouldn't
|
||||
* also be emulating it using repeated mouse warps, so disable
|
||||
* mouse warp emulation by default.
|
||||
*/
|
||||
mouse->warp_emulation_prohibited = SDL_TRUE;
|
||||
if (!enabled) {
|
||||
/* If warps were being emulated, reset the flag. */
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
}
|
||||
|
||||
if (enabled == mouse->relative_mode) {
|
||||
@@ -1701,7 +1727,6 @@ int SDL_ShowCursor(void)
|
||||
if (mouse->warp_emulation_active) {
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
mouse->warp_emulation_active = SDL_FALSE;
|
||||
mouse->warp_emulation_prohibited = SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!mouse->cursor_shown) {
|
||||
|
||||
@@ -97,6 +97,7 @@ typedef struct
|
||||
SDL_bool warp_emulation_hint;
|
||||
SDL_bool warp_emulation_active;
|
||||
SDL_bool warp_emulation_prohibited;
|
||||
Uint64 last_center_warp_time_ns;
|
||||
int relative_mode_clip_interval;
|
||||
SDL_bool enable_normal_speed_scale;
|
||||
float normal_speed_scale;
|
||||
@@ -183,6 +184,7 @@ extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, S
|
||||
extern int SDL_SetRelativeMouseMode(SDL_bool enabled);
|
||||
extern SDL_bool SDL_GetRelativeMouseMode(void);
|
||||
extern void SDL_UpdateRelativeMouseMode(void);
|
||||
extern void SDL_DisableMouseWarpEmulation(void);
|
||||
|
||||
/* TODO RECONNECT: Set mouse state to "zero" */
|
||||
#if 0
|
||||
|
||||
@@ -3786,6 +3786,12 @@ int SDL_SetWindowRelativeMouseMode(SDL_Window *window, SDL_bool enabled)
|
||||
{
|
||||
CHECK_WINDOW_MAGIC(window, -1);
|
||||
|
||||
/* If the app toggles relative mode directly, it probably shouldn't
|
||||
* also be emulating it using repeated mouse warps, so disable
|
||||
* mouse warp emulation by default.
|
||||
*/
|
||||
SDL_DisableMouseWarpEmulation();
|
||||
|
||||
if (enabled == SDL_GetWindowRelativeMouseMode(window)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user