Skip to content

Filter out tiny mouse events#3523

Merged
kchibisov merged 1 commit intomasterfrom
notgull/delta
Mar 1, 2024
Merged

Filter out tiny mouse events#3523
kchibisov merged 1 commit intomasterfrom
notgull/delta

Conversation

@notgull
Copy link
Copy Markdown
Contributor

@notgull notgull commented Feb 26, 2024

Usually, if mouse events are equal to (0, 0) we filter them out.
However, if the event is very close to zero it will still be given to
the user. In some cases this can be caused by bad float math on the X11
server side.

I fix this by refusing to forward events where both of their deltas fall
below a certain threshold.

Closes #3500

  • Tested on all platforms changed
  • Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • Created or updated an example program if it would help users understand this functionality
  • Updated feature matrix, if new features were added or implemented

@notgull notgull requested a review from kchibisov as a code owner February 26, 2024 03:14
@notgull notgull added B - bug Dang, that shouldn't have happened DS - x11 Affects the X11 backend, or generally free Unix platforms C - waiting on maintainer A maintainer must review this code labels Feb 26, 2024
const KEYCODE_OFFSET: u8 = 8;

/// Minimum delta for a device event to be considered.
const NOTGULL_THRESHOLD: f32 = 4.0e-8;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should insert my username in more source code! 😁

(I've tried hard with the mtm: MainThreadMarker, but while mtm is my initials, nothing beats just spelling out the whole thing)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be renamed to something useful. Also it should be explained why the given constant was picked in the first place, otherwise it may not work for some cases.

There's also a case where you move the mouse really slowly, thus filtering may not actually move the mouse where it should or accumulate in error.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've elected to use the float epsilon instead. Since float comparison breaks down past the epsilon, for all intentions and purposes any number less than the epsilon is zero.

const KEYCODE_OFFSET: u8 = 8;

/// Minimum delta for a device event to be considered.
const NOTGULL_THRESHOLD: f32 = 4.0e-8;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be renamed to something useful. Also it should be explained why the given constant was picked in the first place, otherwise it may not work for some cases.

There's also a case where you move the mouse really slowly, thus filtering may not actually move the mouse where it should or accumulate in error.

Comment on lines +1470 to +1471
if mouse_delta.0.abs() as f32 >= NOTGULL_THRESHOLD
|| mouse_delta.1.abs() as f32 >= NOTGULL_THRESHOLD
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite like this logic in-particular. Could you instead check if the given value is small enough and null it? Then just send the thing if something is not null, since those low values don't make much sense in the first place.

@valaphee
Copy link
Copy Markdown
Contributor

valaphee commented Feb 27, 2024

This wouldn't fix the underlying issue. Interestingly, I didn't had any issues with Bevy for example, but its also not a regression.

Didn't want to use thresholds because normally raw mouse input events should not be less than 1.0

But I also don't know how to trace X11 ^^'

@notgull
Copy link
Copy Markdown
Contributor Author

notgull commented Feb 28, 2024

This wouldn't fix the underlying issue. Interestingly, I didn't had any issues with Bevy for example, but its also not a regression.

Didn't want to use thresholds because normally raw mouse input events should not be less than 1.0

I think the underlying issue is that the underlying driver is making an error somewhere in the floating point calculation and sending us a very tiny number instead of zero. 7.1e-222 is far less than the epsilon on all platforms, so for all intents and purposes it might as well be zero.

@valaphee
Copy link
Copy Markdown
Contributor

valaphee commented Feb 28, 2024

Then this would definitely be a valid fix, but the value is always near zero, even if there is movement, that's why I don't think it's a floating point error.

@notgull
Copy link
Copy Markdown
Contributor Author

notgull commented Feb 29, 2024

Then this would definitely be a valid fix, but the value is always near zero, even if there is movement, that's why I don't think it's a floating point error.

My understanding of Xinput's raw mouse events is that they are always multiples of 1. So we shouldn't be seeing any floating point numbers anyways. So it's fine for us to assume that a value less than the epsilon is, for all intents and purposes, supposed to be zero.

Usually, if mouse events are equal to (0, 0) we filter them out.
However, if the event is very close to zero it will still be given to
the user. In some cases this can be caused by bad float math on the X11
server side.

Fix it by filtering absolute values smaller than floating point epsilon.

Signed-off-by: John Nunley <dev@notgull.net>
Closes: #3500
@kchibisov kchibisov merged commit 3d4c534 into master Mar 1, 2024
@kchibisov kchibisov deleted the notgull/delta branch March 1, 2024 09:11
Comment on lines +33 to +34
(true, false) => (this.x, 0.0),
(false, true) => (0.0, this.y),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey yall :) The code here is mistakenly returning the axis that's lower than the epsilon.
It's the likely cause of this issue in Bevy: bevyengine/bevy#12198.

Suggested change
(true, false) => (this.x, 0.0),
(false, true) => (0.0, this.y),
(false, true) => (this.x, 0.0),
(true, false) => (0.0, this.y),

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

Labels

B - bug Dang, that shouldn't have happened C - waiting on maintainer A maintainer must review this code DS - x11 Affects the X11 backend, or generally free Unix platforms

Development

Successfully merging this pull request may close these issues.

X11: Mouse motion events sometimes contain garbage

5 participants