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 position bug under High DPI on Windows #3358

Closed
tgjones opened this issue Jan 5, 2015 · 7 comments
Closed

Mouse position bug under High DPI on Windows #3358

tgjones opened this issue Jan 5, 2015 · 7 comments

Comments

@tgjones
Copy link
Contributor

tgjones commented Jan 5, 2015

My "FPS camera" code, that constantly resets the mouse position to the centre of the window, worked in XNA but doesn't (quite) work in MonoGame. It sometimes works, but other times, if you leave the mouse stationary, it still thinks the mouse is moving by 1 pixel in the X or Y direction.

I've tracked the problem down to DPI scaling. If I set my DPI scaling to 100%, there's no problem. But with 150% scaling, there seems to be a problem with mouse position getting rounded. I haven't looked into it yet, but I guess that somewhere between setting the mouse position and retrieving it, there's a float getting rounded to an int, or something, which means MonoGame constantly thinks that the mouse has moved by a little bit, even if it hasn't.

I'll work on a pull request for this, but I wanted to raise this issue first in case anyone else has experienced this issue. Do any MonoGame developers have DPI scaling enabled on their monitors?

@tgjones
Copy link
Contributor Author

tgjones commented Jan 5, 2015

Actually, I'm wrong about XNA - it doesn't work properly in XNA either. So in both XNA and MonoGame, at 150% scaling, this code doesn't work correctly:

Mouse.SetPosition(400, 300);

var state = Mouse.GetState();
// state.X is sometimes 400, sometimes 401 (or 399)

It only starts drifting if you move the mouse in that direction, which makes me think it's some kind of rounding error.

I'll keep investigating.

@polsys
Copy link
Contributor

polsys commented Jan 5, 2015

I can confirm this on my laptop... rounding error happens at 150% scaling but not 200%, as can be expected.

As an interesting side note (which probably should be a separate issue), WindowsDX seems to apply scaling to window size, so on my 3200x1800 monitor PreferredBackBufferWidth can be at most 1600 (with 200% scaling enabled). On WindowsGL the window size is not scaled. Does MonoGame have any convention on DPI handling?

@tgjones
Copy link
Contributor Author

tgjones commented Jan 5, 2015

Researching a bit more, it seems that there is indeed a precision issue with GetCursorPos/SetCursorPos in non-DPI-aware applications. At 150%, there's a 50% loss of precision, and at 200% scaling, there's a 100% loss of precision. So calling SetCursorPos immediately followed by GetCursorPos will not necessarily give you what you'd expect.

For most types of Windows applications, this isn't that noticeable, but for games and specifically FPS-style camera controls, it's obviously a bit of a problem!

There are (at least) two solutions I can think of:

  • Make WinFormsGameWindow DPI-aware. But this is a big change.
  • Use SetPhysicalCursorPos/GetPhysicalCursorPos. This might work?

@polsys
Copy link
Contributor

polsys commented Jan 5, 2015

Making WinFormsGameWindow DPI-aware would force developers to implement scaling themselves, but on the other hand it would allow real control over backbuffer size (4K games?). Currently WindowsDX has to upscale the backbuffer, which blurs the final image.

Do we want the DX or GL behavior to be the default? Which one is better for backwards compatibility?

@polsys
Copy link
Contributor

polsys commented Jan 5, 2015

XNA seems to maintain 100% backbuffer scaling regardless of OS setting, so making WinFormsGameWindow DPI-aware should fix both the backbuffer (that is, make it compatible with XNA and WindowsGL MonoGame) and the mouse.

@tgjones
Copy link
Contributor Author

tgjones commented Mar 25, 2015

For now, I've fixed this by just adding an application manifest to my game project.

I briefly experimented with adding a DpiAware property to GraphicsDeviceManager, and hooked it up for OpenTK (via OpenTK's ToolkitOptions.EnableHighResolution property) and WinForms. If MonoGame is going to have a DpiAware property on desktop platforms, it should at least work consistently across all of them. But getting it working for all platforms is a bit more involved than I have time for right now.

I'm going to close this, because adding an application manifest, with dpiAware="true", to my game project does fix the original mouse position bug. If anyone is interested in adding a DpiAware property to MonoGame, that can be logged as a separate issue.

@tgjones tgjones closed this as completed Mar 25, 2015
@tomspilman
Copy link
Member

I briefly experimented with adding a DpiAware property to GraphicsDeviceManager , and hooked it up for OpenTK (via OpenTK's ToolkitOptions.EnableHighResolution property) and WinForms. If MonoGame is going to have a DpiAware property on desktop platforms, it should at least work consistently across all of them.

I agree... this is probably the right path.

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

No branches or pull requests

3 participants