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

Mouse is not updating on right / bottom screen edge (DPI scale > 100%) #2049

Open
damil42 opened this issue Apr 1, 2024 · 7 comments
Open
Labels
bug Something isn't working library dependency Related to a library used by LÖVE Windows

Comments

@damil42
Copy link

damil42 commented Apr 1, 2024

The mouse does not update on the right and bottom edges of the screen.

demo

function love.draw()
  love.graphics.clear(0.1, 0.2, 0.3)

  local sw, sh = love.graphics.getDimensions()
  local mx, my = love.mouse.getPosition()
  local time = love.timer.getTime()

  love.graphics.setColor(0.3, 0.4, 0.5)
  love.graphics.setLineWidth(5)
  love.graphics.line(0, my, sw, my)
  love.graphics.line(mx, 0, mx, sh)
  love.graphics.circle("fill", mx, my, 20 + math.cos(time * 5) * 5)
  love.graphics.circle("line", mx, my, 40 + math.sin(time * 5) * 10)

  love.graphics.setColor(1, 1, 1)
  love.graphics.print("Press F11 to toggle fullscreen.", 10, 10)
  love.graphics.print("In fullscreen, move the mouse to each edge of the screen.", 10, 30)
  love.graphics.print("Bug: The mouse is not updated on the right and bottom edges.", 10, 50)
  love.graphics.print("Tested on Windows 11.", 10, 70)
end

function love.keypressed(key)
  if key == "escape" then love.event.quit() end
  if key == "f11" then love.window.setFullscreen(not love.window.getFullscreen()) end
end

Version 11.5 (2023-12-03)
Windows 11

@slime73
Copy link
Member

slime73 commented Apr 1, 2024

It's working as expected for me in Windows 10 with love 11.5 - in windowed mode, the mouse position isn't updated when the cursor is outside of the window (no matter what edge). In fullscreen it behaves the same, I have two monitors and if my mouse cursor goes past the right edge of the primary one where love is into my secondary monitor, then the mouse position in love doesn't update.

Additionally, if I hold my left mouse button down and move the cursor around, it updates the mouse position past the bounds of the window no matter the edge but still clamps it (this is new intended behaviour as of the latest SDL version).

Do you have a multi-monitor setup that extends past the bottom and right sides of the display where you made that recording, maybe?

love also has APIs like love.mouse.setRelativeMode and love.mouse.setGrabbed if you want to constrain the user's cursor to the window in a particular way.

@damil42
Copy link
Author

damil42 commented Apr 1, 2024

I only have one monitor. The mouse is within the screen. In the gif video, you can see a bit of the cursor when moving on the right edge. I know that the mouse is not updating when moved outside. This is ok. But in this case, the mouse is still within the window. You can just detect this bug in fullscreen where you can't move outside.

One use case I'm thinking is an RTS/city building game where you can move the mouse on the edge to scroll the camera view. No mouse event (click or position) is working on the edge right or bottom.

function love.draw()
  love.graphics.clear(0.1, 0.2, 0.3, 0.1)

  local sw, sh = love.graphics.getDimensions()
  local mx, my = love.mouse.getPosition()

  love.graphics.setColor(0.3, 0.4, 0.5)
  love.graphics.setLineWidth(5)
  love.graphics.line(0, my, sw, my)
  love.graphics.line(mx, 0, mx, sh)
  love.graphics.circle("fill", mx, my, love.mouse.isDown(1) and 30 or 10)
end

function love.keypressed(key)
  if key == "escape" then love.event.quit() end
  if key == "f11" then love.window.setFullscreen(not love.window.getFullscreen()) end
end

As you can see in the code. You can now click the (left) mouse button to change the circle size. Try it on the edge. Unplug your second monitor and test it.

I don't know the source code but it looks like (pseudo code):

mosue_pos >= 0 and mouse_pos < screen_size
-- instead of
mosue_pos >= 0 and mouse_pos <= screen_size

You know what I mean? Or the game area is 1 pixel smaller that the screen. Or the window invisible border blocks the event. I don't know. But it's definitly a bug.

@slime73
Copy link
Member

slime73 commented Apr 1, 2024

Like I said, it's working as expected on my system, I can't reproduce the problem you're describing - and also love doesn't have code like that itself (it just does what SDL and the OS do under the hood). So there's probably a difference between our two systems causing it. Maybe the OS itself considering you have windows 11 and I have windows 10, or maybe something else.

Do you use a DPI scale / display scale set to something other than 100%, for your monitor? Windows will handle a bunch of scaling itself and upscale love in that situation.

@damil42
Copy link
Author

damil42 commented Apr 1, 2024

Indeed, I use 200% UI scaling for my 4k TV. For testing I changed it back to 100% and the problem no longer occurs. So it seems it's related to the UI scaling. Can someone reproduce this or explain what happened here? So, it's a bug. The question is, can we fix this in love2d? Any workaround?

@damil42 damil42 changed the title The mouse does not update on the right and bottom edges of the screen. Mouse does not update on the right and bottom edge of screen when DPI > 100%. Apr 1, 2024
@damil42 damil42 changed the title Mouse does not update on the right and bottom edge of screen when DPI > 100%. Mouse does not update on the right and bottom edge of screen (DPI scale > 100%) Apr 1, 2024
@damil42 damil42 changed the title Mouse does not update on the right and bottom edge of screen (DPI scale > 100%) Mouse is not updating on right / bottom screen edge (DPI scale > 100%) Apr 1, 2024
@damil42
Copy link
Author

damil42 commented Apr 1, 2024

Btw. t.window.highdpi = true does not work on Windows. I would expect an option to disable scaling for the application. I also tried variations with t.window.usedpiscale. It seems this is not supported in love2d. These options are for mobile, right? In e.g. Godot this option also works on Windows. Btw. this is one reason why the screen looks pixelated.

@slime73
Copy link
Member

slime73 commented Apr 1, 2024

Btw. t.window.highdpi = true does not work on Windows.

That's correct, the version of SDL love uses doesn't support it on Windows with love 11's api.

It does work on macOS, iOS, Android, and Wayland (Linux). Microsoft ended up implementing app DPI scaling in a manner that's incompatible with how love sets it dynamically for the window though.

love 12 has a global per-app API for it instead, to accommodate Windows.

@damil42
Copy link
Author

damil42 commented Apr 1, 2024

I just played around again and found this... (for the sake of completeness and possible bug fixes)

  • It has nothing to do with the fullscreen. I was able to reproduce the same behavior with mouse.setGrabbed.
  • If isGrabbed then the mouse also hangs on right / bottom edges.
  • If I click and hold the mouse button while moving the cursor around the edges and outside, it works without any problems.

In both cases (grabbed and pressing) the mouse position on edge is the same. But only pressing works as expected (mouse also works on edges). But you can also move the mouse outside the game (if windowed). So I guess it's a global mouse event. Only the last pixel on the right/bottom doesn't seem to be a part of the game view. So setGrabbed does also not work. ...

demo.webm
function love.load()
  love.mouse.setGrabbed(true)
end

function love.draw()
  love.graphics.clear(0.1, 0.2, 0.3, 0.1)

  local sw, sh = love.graphics.getDimensions()
  local mx, my = love.mouse.getPosition()

  love.graphics.setColor(0.3, 0.4, 0.5)
  love.graphics.setLineWidth(5)
  love.graphics.line(0, my, sw, my)
  love.graphics.line(mx, 0, mx, sh)
  love.graphics.circle("fill", mx, my, love.mouse.isDown(1) and 30 or 10)

  love.graphics.setColor(1, 1, 1)
  love.graphics.print("ESC: Quit; F11: Fullscreen; F1: Grab/Free mouse", 10, 10)
  love.graphics.print("Screen size: " .. sw .. ", " .. sh, 10, 30)
  love.graphics.print("Mouse pos: " .. mx .. ", " .. my, 10, 50)
end

function love.keypressed(key)
  if key == "escape" then love.event.quit() end
  if key == "f11" then love.window.setFullscreen(not love.window.getFullscreen()) end
  if key == "f1" then love.mouse.setGrabbed(not love.mouse.isGrabbed()) end
end

@slime73 slime73 added bug Something isn't working library dependency Related to a library used by LÖVE Windows labels Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working library dependency Related to a library used by LÖVE Windows
Projects
None yet
Development

No branches or pull requests

2 participants