Skip to content

Use XInput2 RawMotion to generate MouseMotion events#19191

Closed
KeyboardDanni wants to merge 0 commit into
godotengine:masterfrom
KeyboardDanni:master
Closed

Use XInput2 RawMotion to generate MouseMotion events#19191
KeyboardDanni wants to merge 0 commit into
godotengine:masterfrom
KeyboardDanni:master

Conversation

@KeyboardDanni

@KeyboardDanni KeyboardDanni commented May 27, 2018

Copy link
Copy Markdown
Contributor

Fixes issue #19031.

A few things worth mentioning:

  • Because this introduces raw mouse input on X11, relative movement is now DPI-dependent. With my mouse (Logitech G500), the motion appears to be about twice as fast after the change. This means the mouse sensitivity in the editor's freelook is too high. I have tried to adjust this using the "Freelook Base Speed" setting but it does not seem to have any effect (either before or after the change).
  • I am not familiar with the goals of the input API. Because this is raw input, relative motion does not map 1:1 with the absolute mouse position. Will this be an issue?
  • I will need someone with a touch device to test my changes and make sure I didn't break anything.

Commit message:

The current system for capturing the mouse and generating motion events on X11
has issues with inaccurate and lopsided input. This is because both
XQueryPointer and XWarpPointer work in terms of integer coordinates when the
underlying X11 input driver may be tracking the mouse using subpixel
coordinates. When warping the pointer, the fractional part of the pointer
position is discarded.

To work around this issue, the fix uses raw motion events from XInput 2. These
events report relative motion and are not affected by pointer warping.
Additionally, this means Godot is able to detect motion at a higher resolution
under X11. Because this is raw mouse input, it is not affected by the user's
pointer speed and acceleration settings. This is the same system as SDL2 uses
for its relative motion.

This change introduces a new build option, "xinput2", which defines XI_ENABLED.
As "touch" relies on XInput, it now implies "xinput2". Multitouch input on X
requires XInput 2.2. Raw motion events require XInput 2.0. If XI_ENABLED is not
defined, the old mouse motion behavior is used. Older systems that require
"xinput2" disabled are likely to be using the "xf86-input-evdev" driver which
is not affected by the bug this commit addresses.

@KeyboardDanni

KeyboardDanni commented May 27, 2018

Copy link
Copy Markdown
Contributor Author

Uncovered an issue after some more testing, please don't merge until this is fixed.

- I may have a solution to the DPI issues.
- Absolute mouse positioning is broken. Am investigating.

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

With this latest commit, absolute motion is fixed, and mouse motion speed no longer feels too fast (the RawMotion event was getting received twice, due to a bug in X).

Feel free to review.

@akien-mga

Copy link
Copy Markdown
Member

CC @RandomShaper @Hinsbart

@mhilbrunner

Copy link
Copy Markdown
Member

Formatting needs to be fixed (seee CI output) :)

@akien-mga

Copy link
Copy Markdown
Member

Formatting needs to be fixed (seee CI output) :)

It's all cases where clang-format is outsmarted and does weird stuff though.

@mhilbrunner

Copy link
Copy Markdown
Member

Ah yeah those are indeed weird.

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Could this PR be relabeled as a bug to be consistent with the issue it references? I am currently using Godot off of master with this fix applied because mouselook is too annoying to work with otherwise.

@RandomShaper

Copy link
Copy Markdown
Member

I can't test this thoroughly at this time, but the idea seems good and the implementation looks sensible.

@fire

fire commented Aug 16, 2018

Copy link
Copy Markdown
Member

Can you see if the ci error is fixable?

@akien-mga

Copy link
Copy Markdown
Member

I think the CI errors are false positives from a time where the master branch was not building. This PR needs to be squashed though to merge the fixups in the original commit and remove the "Merge branch" unnecessary commits (and fix current merge conflicts).

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

I was under the impression that this PR was waiting on @RandomShaper to review it. But I can go ahead and squash the commits now.

Those "Merge branch" commits were due to me resolving merge conflicts. This next "Merge branch" will be the third one. I was gonna wait until the alpha but given how frequently the merge conflicts are coming up, I'd rather have the PR merged now, if that's not an issue.

When I squash, should the merges be squashed together with the rest?

@akien-mga

Copy link
Copy Markdown
Member

Yes, you should squash all 8 commits together, which will end up in this much more readable diff: https://github.com/godotengine/godot/pull/19191.diff

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Please ignore @neikeq, had a bad merge while trying to squash the commits initially.

@capnm

capnm commented Sep 6, 2018

Copy link
Copy Markdown
Contributor

Your (master-rebased) PR doesn't work at all with absolute tracking mode devices, see
#21751 (comment)

The relative offset is now very different. It is more accelerated and in the confined mode the update continues on window edges. I do not know if the old behavior was expected ...
peek 2018-09-06 08-23

@KeyboardDanni

KeyboardDanni commented Sep 6, 2018

Copy link
Copy Markdown
Contributor Author

What is the intended behavior here? Is the white dot meant to line up perfectly with the green dot? The mouse cursor and raw input events update at different rates so it's not likely to be possible. The reason it moves faster is because it does not account for mouse DPI. I could probably look into using the other values provided in the RawInput event, which do seem to compensate for it.

Good catch on absolute mouse devices being broken. It looks like the axis values reported for absolute devices are in absolute coordinates, but are being interpreted as relative movement. I'll have to dig out my old Wacom tablet, it looks like. :)

Edit: Relative motion going past the edges of the window/screen is intentional. Otherwise it'd break anything needing "infinite" mouse movement space.

@capnm

capnm commented Sep 6, 2018

Copy link
Copy Markdown
Contributor

Relative motion going past the edges of the window/screen is intentional. Otherwise it'd break anything needing "infinite" mouse movement space.

I meant the confined mode, check the current behaviour.
And try moving the 2D editor window with the MMB …

@guilhermefelipecgs

guilhermefelipecgs commented Sep 7, 2018

Copy link
Copy Markdown
Contributor

Screencast to simplify.

Notice how the cursor sits on godot's nose.

godot HEAD 74359a1:
peek 06-09-2018 21-20

After this PR:
peek 06-09-2018 21-11

Windows also have the first behavior.

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

I think it's almost there.

Issue with sliders (#19692) are fixed now (but not for touch):
sliders

Pen and mouse seems fine but touch doesn't. See gifs below, the white dot always go back to the center.
I merged this pr with my (#21753) in this tests.
Mouse:
test_mouse
Pen:
test_pen
Touch:
test_touch

This means that we can't control 3d camera (freelook) or sliders with touch, for example.
Pen:
pen
Touch:
touch

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

About resolution, here is a little comparison:

On master (1093c0f):
Mouse:
res_mouse_master
Pen:
pen_res_master

With this pr:
Mouse:
res_mouse_raw
Pen:
pen_res_raw

Mouse is two times slower, but is acceptable yet and with pen, is too small, I can barely move the slider.

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Is the touch device detected as an absolute or relative device? What does "xinput test-xi2" give for it?

I unfortunately do not know how I would get a touch device working on my setup. I don't have any touch screens (outside of Android devices). I have an Apple trackpad and a PS4 controller, both of which should be multi-touch capable yet aren't picked up as such.

I'll up the pen sensitivity. For mouse, what Godot really needs is an editor option to control the capture speed, because this is going to be slightly different on every configuration.

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

Is the touch device detected as an absolute or relative device? What does "xinput test-xi2" give for it?

absolute

Mouse is two times slower, but is acceptable yet and with pen, is too small, I can barely move the slider.

The stranger part about this is that I only have small resolution when moving sliders, for freelook or using the test case with colored dots I don't get any issue with resolution.

Maybe it's a bug with sliders 🤔

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

I'll up the pen sensitivity.

I'm not sure if this is the problem, rotation for example have a complete different resolution. I'm not sure how slider decide what "speed" to use:

peek 09-09-2018 17-32

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Slider sensitivity is the least of my concerns right now. What I really want to do is fix the touch issues. So far nobody has been able to help me get multitouch set up, but you appear to have a working configuration, so you'll need to work with me to get this resolved.

I don't know what kind of hardware setup you have - specifically, what is the touch device? And I would still like to see the output from "xinput test-xi2".

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

cc @RandomShaper

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

When using touch of wacom, the device should not be treated as absolute anymore. I think this should works.

Update:

When reading the "change devices" log, it seems that the wacom reports finger touch as absolute mode, but it doesn't (should not be, because it works as relative for me).

Update 2:

Confirmed, changing Finger Touch to Relative works as expected. Now works in absolute mode as well, it seems a bug in my system or tablet. I didn't even know that finger touch on wacom had absolute mode.

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

@cosmicchipsocket I don't have any problems anymore, my wacom was not reporting correct values for linux, maybe it's a driver bug. Mouse, Pen and Touch are working good, I don't have any other complain about this PR except for the sensitivity with slider that maybe should not be treated here.

Thanks.

@guilhermefelipecgs

Copy link
Copy Markdown
Contributor

Almost forget, I think my wacom support multi touch but I don't know how to test it. I'll try to discover.

@guilhermefelipecgs

guilhermefelipecgs commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

Ok, I think my wacom is not considered has touch device.

XInput: Refreshing devices.
XInput: No touch devices found.

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

@guilhermefelipecgs Thanks for the update!

@akien-mga

Copy link
Copy Markdown
Member

@cosmicchipsocket IMO we can safely have a strong requirement on XInput 2 given its age and widespread availability. That should simplify things a bit and avoid keeping code that we'll never use in the end. CC @hpvb

@capnm

capnm commented Sep 12, 2018

Copy link
Copy Markdown
Contributor

IMO we can safely have a strong requirement on XInput 2

GLFW did that more than a year ago
glfw/glfw@a570d0a

@oskude

oskude commented Oct 3, 2018

Copy link
Copy Markdown

FWIW, this pull request seems to really fix godotengine/godot-docs#1774 for me on linux.
(the camera stutter was just less noticable when i closed that ticket, then i tried to debug/fix it myself...)

if i understand this MOUSE_MODE_CAPTURED correctly, the current (godot git master couple hours ago) method to get around the problem that xorg (xcb?) wont give us any mouse movement when pointer is at window edge, is to warp the mouse pointer to the center of the window, on every mouse move?

and this pull request - i assume (did not read, just merged and works. and gotta get sleep) - allows us to get mouse movement constantly? that sounds like a perfect solution for a 3d fps camera movement with MOUSE_MODE_CAPTURED!

ps. this pull request could also fix some of these https://github.com/godotengine/godot/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+MOUSE_MODE_CAPTURED on linux

pps. FWIW, during my "research" i found https://www.x.org/releases/current/doc/man/man3/XWarpPointer.3.xhtml and it sais "...it generates events just as if the user had instantaneously moved the pointer from one position to another." but could not figure out how to test if thats the cause of the current camera stutter...

@akien-mga

Copy link
Copy Markdown
Member

IMO we can safely have a strong requirement on XInput 2 given its age and widespread availability.

Bump @cosmicchipsocket, could you do those changes? (make XInput 2.0 strong requirement, only keep the 2.2 checks for the touch feature).

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Dissolved the XI_ENABLED ifdef and removed the xinput option from detect.py (reverting it to its original state).

Also went ahead and fixed an issue where the faux global mouse position was still stairsteppy in captured mode with a relative device.

@capnm

capnm commented Oct 5, 2018

Copy link
Copy Markdown
Contributor

In the Free-Cam (F) view, the relative device is about twice? as sensitive as before (independent to the mouse speed OS settings).

Otherwise everything lgtm.

@KeyboardDanni

Copy link
Copy Markdown
Contributor Author

Now the engine and buildsystem will fail out if XInput 2 is missing. Feeling like this is more or less done now.

Comment thread platform/x11/detect.py Outdated
@akien-mga akien-mga requested a review from RandomShaper October 5, 2018 07:54
@akien-mga akien-mga closed this Dec 14, 2018
@akien-mga

Copy link
Copy Markdown
Member

Sorry about the auto-close, I tried to force push a rebased commit but I pushed the wrong branch, which closed the PR as it was the same as current origin/master.

I've actually merged this PR manually as cf124b1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants