Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL issuing errenous warps during RelativeMode #7943

Closed
expikr opened this issue Jul 7, 2023 · 1 comment · Fixed by #7947
Closed

SDL issuing errenous warps during RelativeMode #7943

expikr opened this issue Jul 7, 2023 · 1 comment · Fixed by #7947
Milestone

Comments

@expikr
Copy link
Contributor

expikr commented Jul 7, 2023

Run the following Love2D script:

function love.load()
    WIDTH,HEIGHT = love.graphics.getDimensions()
    R,G,B = 1,1,1
    EXPECT_X,EXPECT_Y = 0,0
    WTF_X, WTF_Y = nil,nil
   do 
      local override = true
      if override then
         ffi = require('ffi')
         local sdl = ffi.load('SDL2.dll')
         ffi.cdef[[
            typedef enum {SDL_HINT_DEFAULT , SDL_HINT_NORMAL , SDL_HINT_OVERRIDE } SDL_HintPriority ;
            bool SDL_SetHintWithPriority(const char *name,  const char *value, SDL_HintPriority priority);
            int ShowCursor(bool bShow);
            int SetCursor(int hCursor);
            int LoadImageA(int hInstance, const char *lpCursorName, unsigned int type, int cx, int cy, unsigned int fuload);
            int LoadCursorA(int a, uint64_t);
         ]]
         sdl.SDL_SetHintWithPriority('SDL_MOUSE_RELATIVE_SPEED_SCALE','1',ffi.C.SDL_HINT_OVERRIDE)
      end
   end
   hCur = ffi.C.LoadCursorA(0,32515)
   love.mouse.setCursor(love.mouse.getSystemCursor("crosshair"))
end

function love.draw()
    local x,y = love.mouse.getPosition()
    if love.mouse.getRelativeMode() then 
       if EXPECT_X ~= x or EXPECT_Y ~= y then 
          R,G,B = 1,0,0
          WTF_X,WTF_Y = x,y
       end
    end
    love.graphics.setColor(R,G,B)
    local str = x..','..y
    if WTF_X~=nil and WTF_Y~=nil then str = str .. '\n' .. WTF_X .. ',' .. WTF_Y end
    love.graphics.print(str)
end

function love.keypressed(key)
    if key=='f10' then
       local enabled = love.mouse.getRelativeMode()
       if not enabled then
          love.mouse.setPosition(WIDTH/2,HEIGHT/2) 
          EXPECT_X,EXPECT_Y = love.mouse.getPosition()
          WTF_X, WTF_Y = nil,nil
       end
       R,G,B = 1,1,1
       love.mouse.setRelativeMode(not enabled)
    end
end

function love.mousemoved()
    if love.mouse.getRelativeMode() then love.mouse.setPosition(WIDTH/2,HEIGHT/2) end
end

function love.run()
	if love.load then love.load(love.arg.parseGameArguments(arg), arg) end

	-- We don't want the first frame's dt to include time taken by love.load.
	if love.timer then love.timer.step() end

	local dt = 0

	-- Main loop time.
	return function()
		-- Process events.
		if love.event then
			love.event.pump()
ffi.C.SetCursor(hCur)
			for name, a,b,c,d,e,f in love.event.poll() do
				if name == "quit" then
					if not love.quit or not love.quit() then
						return a or 0
					end
				end
				love.handlers[name](a,b,c,d,e,f)
			end
		end

		-- Update dt, as we'll be passing it to update
		if love.timer then dt = love.timer.step() end

		-- Call update and draw
		if love.update then love.update(dt) end -- will pass 0 if love.timer is disabled

		if love.graphics and love.graphics.isActive() then
			love.graphics.origin()
			love.graphics.clear(love.graphics.getBackgroundColor())

			if love.draw then love.draw() end

			love.graphics.present()
		end

		if love.timer then love.timer.sleep(0.001) end
	end
end

Then, start spamming your left and right mouse buttons while shaking your mouse. You will observe the following:

  1. The cursor sometimes flashing invisible for a split second (expected, since callbacks in Love2D could not catch up to SDL's instantaneous WM_SETCURSOR response to Windows
  2. The cursor sometimes flashing to a different spot on the screen for a split second (this should not happen under any circumstance, regardless of whether or not RelativeMode is meant to have the cursor visible. Somewhere in the code SDL is issuing an errenous WarpCursor or unclip-cursor-then-reclip for no good reason that is separate from the pre-drawing warp calback being issued from Lua)
  3. The SDL's internal position slightly warping from the logical center, despite the mousemoved callback warping it back to center before drawing the frame.
@expikr
Copy link
Contributor Author

expikr commented Jul 7, 2023

this build cherry picked from #7947 seems to fix behavior no.1 and no.2:

SDL2.zip

No.1 is directly addressed by the change, but I have no idea why it would also fix no.2, so the latent issue is probably still there related to erroneous window focus events.

No.3 is still present.

@slouken slouken added this to the 3.2.0 milestone Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants