fix(switch): stop pad cursor flicker from SDL mouse drift

Disable mouse-yield on NX where stick/touch moves the system pointer between sparse axis events, clamp pad dt, pixel-snap the overlay, and soften FlexLove GC so the launcher cursor stays steady.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Andrew Quenehen
2026-08-03 14:31:05 -03:00
parent 0e5ea26e36
commit cfe482e1fc
3 changed files with 78 additions and 23 deletions
+14
View File
@@ -109,6 +109,15 @@ function LauncherView.applyNxPerfGuards(imp)
FlexLove._Performance.enabled = false
local mp = FlexLove._Performance._memoryProfiler
if mp then mp.enabled = false end
-- Immediate-mode rebuilds allocate a full tree every frame; the default
-- auto GC steps hitch the pad cursor on Switch. Less frequent steps, higher
-- threshold — desktop keeps FlexLove defaults.
if FlexLove._gcConfig then
FlexLove._gcConfig.strategy = "periodic"
FlexLove._gcConfig.interval = 90
FlexLove._gcConfig.stepSize = 40
FlexLove._gcConfig.memoryThreshold = 180
end
return true
end
@@ -1734,7 +1743,12 @@ end
local function drawPadCursor(imp)
if not imp._padCursorActive then return end
-- Pixel-snap on NX: subpixel polygon edges shimmer on the 720p Switch
-- framebuffer when the stick advances by fractional pixels each frame.
local x, y = imp._padCursor.x, imp._padCursor.y
if imp.isNX then
x, y = math.floor(x + 0.5), math.floor(y + 0.5)
end
love.graphics.push("all")
love.graphics.origin()
love.graphics.setLineWidth(1)
+14 -15
View File
@@ -1984,24 +1984,24 @@ end
function RomImporter:_updatePadCursor(dt)
if self.isNX then
self:_ensureNxPointerBridge()
-- Cap dt so a hitch in the FlexLove immediate-mode frame does not fling
-- the cursor; desktop keeps raw dt (setPosition path already smooth there).
if dt > 1 / 30 then dt = 1 / 30 end
end
-- Real mouse motion yields the pad cursor so desktop users keep a normal
-- pointer after bumping a stick once. On NX the bridged getPosition returns
-- pad coords while active, so yield must sample the *real* mouse or an A
-- press after idle falsely drops the cursor (pad vs last real position).
local mx, my
if self.isNX and self._nxRealGetPosition then
mx, my = self._nxRealGetPosition()
else
mx, my = love.mouse.getPosition()
end
if self._lastMouseX and self._padCursorActive then
if math.abs(mx - self._lastMouseX) > 3 or math.abs(my - self._lastMouseY) > 3 then
self._padCursorActive = false
-- pointer after bumping a stick once. On NX this must stay off: love-nx /
-- SDL often drifts the system mouse with the stick (or touch), and axis
-- events are not every frame, so yield+reactivate flickers the overlay.
if not self.isNX then
local mx, my = love.mouse.getPosition()
if self._lastMouseX and self._padCursorActive then
if math.abs(mx - self._lastMouseX) > 3 or math.abs(my - self._lastMouseY) > 3 then
self._padCursorActive = false
end
end
self._lastMouseX, self._lastMouseY = mx, my
end
self._lastMouseX, self._lastMouseY = mx, my
local ax = self._padAxis.leftx or 0
local ay = self._padAxis.lefty or 0
@@ -2025,8 +2025,7 @@ function RomImporter:_updatePadCursor(dt)
self._padCursor.x = math.max(ox, math.min(ox + w, nx))
self._padCursor.y = math.max(oy, math.min(oy + h, ny))
-- Desktop: FlexLove polls the real mouse, so warp it with the pad pointer.
-- NX: the getPosition bridge already returns pad coords — skip setPosition
-- and leave _lastMouse* on the real pointer baseline (yield above).
-- NX: the getPosition bridge already returns pad coords — skip setPosition.
if not self.isNX and love.mouse.setPosition then
pcall(love.mouse.setPosition, self._padCursor.x, self._padCursor.y)
self._lastMouseX, self._lastMouseY = self._padCursor.x, self._padCursor.y