From 9abb6790d30ed98ee8de34e51ff37dc2aeadbc3a Mon Sep 17 00:00:00 2001 From: Malkierian Date: Wed, 15 Oct 2025 15:06:25 -0700 Subject: [PATCH] Cursor Visibility Tweaks (#944) * Fixed typo (ForceCursorVisability -> ForceCursorVisibility). Tweaked the cursor visibility tick to only call SetCursorVisibility(false) once per visibility cycle. * Fix SetCursorVisibility in DXGI to not need looping. * Undo previous, and add better presentation for `CursorTimeoutTick()`. --- include/fast/backends/gfx_dxgi.h | 2 +- include/fast/backends/gfx_sdl.h | 2 +- .../fast/backends/gfx_window_manager_api.h | 2 +- src/fast/Fast3dWindow.cpp | 2 +- src/fast/backends/gfx_dxgi.cpp | 6 ++-- src/fast/backends/gfx_sdl2.cpp | 2 +- src/ship/window/gui/Gui.cpp | 35 ++++++++++++------- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/include/fast/backends/gfx_dxgi.h b/include/fast/backends/gfx_dxgi.h index 3be9640..fb720c0 100644 --- a/include/fast/backends/gfx_dxgi.h +++ b/include/fast/backends/gfx_dxgi.h @@ -23,7 +23,7 @@ class GfxWindowBackendDXGI final : public GfxWindowBackend { void SetFullscreenChangedCallback(void (*onnFullscreenChanged)(bool is_now_fullscreen)) override; void SetFullscreen(bool fullscreen) override; void GetActiveWindowRefreshRate(uint32_t* refreshRate) override; - void SetCursorVisability(bool visability) override; + void SetCursorVisibility(bool visability) override; void SetMousePos(int32_t posX, int32_t posY) override; void GetMousePos(int32_t* x, int32_t* y) override; void GetMouseDelta(int32_t* x, int32_t* y) override; diff --git a/include/fast/backends/gfx_sdl.h b/include/fast/backends/gfx_sdl.h index 61e1f71..8669135 100644 --- a/include/fast/backends/gfx_sdl.h +++ b/include/fast/backends/gfx_sdl.h @@ -16,7 +16,7 @@ class GfxWindowBackendSDL2 final : public GfxWindowBackend { void SetFullscreenChangedCallback(void (*onFullscreenChanged)(bool is_now_fullscreen)) override; void SetFullscreen(bool fullscreen) override; void GetActiveWindowRefreshRate(uint32_t* refreshRate) override; - void SetCursorVisability(bool visability) override; + void SetCursorVisibility(bool visability) override; void SetMousePos(int32_t posX, int32_t posY) override; void GetMousePos(int32_t* x, int32_t* y) override; void GetMouseDelta(int32_t* x, int32_t* y) override; diff --git a/include/fast/backends/gfx_window_manager_api.h b/include/fast/backends/gfx_window_manager_api.h index 6f93fcd..3263d50 100644 --- a/include/fast/backends/gfx_window_manager_api.h +++ b/include/fast/backends/gfx_window_manager_api.h @@ -15,7 +15,7 @@ class GfxWindowBackend { virtual void SetFullscreenChangedCallback(void (*mOnFullscreenChanged)(bool is_now_fullscreen)) = 0; virtual void SetFullscreen(bool fullscreen) = 0; virtual void GetActiveWindowRefreshRate(uint32_t* refreshRate) = 0; - virtual void SetCursorVisability(bool visability) = 0; + virtual void SetCursorVisibility(bool visability) = 0; virtual void SetMousePos(int32_t posX, int32_t posY) = 0; virtual void GetMousePos(int32_t* x, int32_t* y) = 0; virtual void GetMouseDelta(int32_t* x, int32_t* y) = 0; diff --git a/src/fast/Fast3dWindow.cpp b/src/fast/Fast3dWindow.cpp index 6267090..0db4353 100644 --- a/src/fast/Fast3dWindow.cpp +++ b/src/fast/Fast3dWindow.cpp @@ -206,7 +206,7 @@ void Fast3dWindow::HandleEvents() { } void Fast3dWindow::SetCursorVisibility(bool visible) { - mWindowManagerApi->SetCursorVisability(visible); + mWindowManagerApi->SetCursorVisibility(visible); } uint32_t Fast3dWindow::GetWidth() { diff --git a/src/fast/backends/gfx_dxgi.cpp b/src/fast/backends/gfx_dxgi.cpp index 1c0775a..dc0350a 100644 --- a/src/fast/backends/gfx_dxgi.cpp +++ b/src/fast/backends/gfx_dxgi.cpp @@ -606,7 +606,7 @@ void GfxWindowBackendDXGI::SetFullscreenChangedCallback(void (*mOnFullscreenChan mOnFullscreenChanged = mOnFullscreenChanged; } -void GfxWindowBackendDXGI::SetCursorVisability(bool visible) { +void GfxWindowBackendDXGI::SetCursorVisibility(bool visible) { // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showcursor // https://devblogs.microsoft.com/oldnewthing/20091217-00/?p=15643 // ShowCursor uses a counter, not a boolean value, and increments or decrements that value when called @@ -678,12 +678,12 @@ void GfxWindowBackendDXGI::SetMouseCapture(bool capture) { mIsMouseCaptured = capture; if (capture) { ApplyMouseCaptureClip(); - SetCursorVisability(false); + SetCursorVisibility(false); SetCapture(h_wnd); mHasMousePosition = false; } else { ClipCursor(nullptr); - SetCursorVisability(true); + SetCursorVisibility(true); ReleaseCapture(); UpdateMousePrevPos(); } diff --git a/src/fast/backends/gfx_sdl2.cpp b/src/fast/backends/gfx_sdl2.cpp index 63aa57e..5a52a78 100644 --- a/src/fast/backends/gfx_sdl2.cpp +++ b/src/fast/backends/gfx_sdl2.cpp @@ -443,7 +443,7 @@ void GfxWindowBackendSDL2::SetFullscreen(bool enable) { SetFullscreenImpl(enable, true); } -void GfxWindowBackendSDL2::SetCursorVisability(bool visible) { +void GfxWindowBackendSDL2::SetCursorVisibility(bool visible) { if (visible) { SDL_ShowCursor(SDL_ENABLE); } else { diff --git a/src/ship/window/gui/Gui.cpp b/src/ship/window/gui/Gui.cpp index b85898e..17f0c2b 100644 --- a/src/ship/window/gui/Gui.cpp +++ b/src/ship/window/gui/Gui.cpp @@ -607,19 +607,28 @@ void Gui::HandleMouseCapture() { void Gui::CursorTimeoutTick() { auto wnd = std::dynamic_pointer_cast(Context::GetInstance()->GetWindow()); - if (!wnd->ShouldForceCursorVisibility()) { - Ship::Coords mousePos = wnd->GetMousePos(); - if ((!wnd->IsMouseCaptured()) && - (abs(mousePos.x - mPrevMousePos.x) > 0 || abs(mousePos.y - mPrevMousePos.y) > 0)) { - wnd->SetCursorVisibility(true); - mCursorVisibleTicks = mCursorVisibleSeconds * wnd->GetTargetFps(); - } - if (mCursorVisibleTicks > 0) { - mCursorVisibleTicks--; - } else { - wnd->SetCursorVisibility(false); - } - mPrevMousePos = mousePos; + if (wnd->ShouldForceCursorVisibility() || wnd->IsMouseCaptured()) { + return; + } + + Ship::Coords mousePos = wnd->GetMousePos(); + bool mouseMoved = abs(mousePos.x - mPrevMousePos.x) > 0 || abs(mousePos.y - mPrevMousePos.y) > 0; + mPrevMousePos = mousePos; + + if (mouseMoved) { + wnd->SetCursorVisibility(true); + mCursorVisibleTicks = mCursorVisibleSeconds * wnd->GetTargetFps(); + return; + } + + if (mCursorVisibleTicks == 0) { + wnd->SetCursorVisibility(false); + mCursorVisibleTicks = -1; + return; + } + + if (mCursorVisibleTicks > 0) { + mCursorVisibleTicks--; } }