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

Widgets "unpress" when mouse is dragged a tiny distance. #5495

Open
barries opened this issue Dec 16, 2024 · 2 comments
Open

Widgets "unpress" when mouse is dragged a tiny distance. #5495

barries opened this issue Dec 16, 2024 · 2 comments
Labels
bug Something is broken

Comments

@barries
Copy link

barries commented Dec 16, 2024

Describe the bug
A widget, e.g. button, becomes "unpressed" when the mouse moves while clicking. When this happens, it feels to the user like the button didn't recognize a click.

We see this in our app's button widget, which uses ui.allocate_exact_size(size, Sense::click()). Also, below is a video showing the same behavior on on the web demo, showing just how short a drag it takes to have the button unpress. This is especially pronounced on touch screens, but was pronounced enough with a mouse that my coworker implemented a workaround for the mouse. Right now, our users are refusing to use it on a touch screen because it misses so many clicks (i.e. touches).

How can I prevent / workaround this?

Thanks!

To Reproduce
Steps to reproduce the behavior:

  1. Render a button
  2. Click-and-hold on it without moving the mouse
  3. Watch it "press"
  4. Drag very slowly, just a tiny amount
  5. Watch it "unpress"

Expected behavior

  1. The button should remained pressed as long as the pointer is in its sense rect (this is the bug)
  2. If the pointer leaves the button's sense rect plus some epsilon, it should unpress
  3. If the pointer re-enters the button's sense rect (not including the epsilon), it should press again

2 and 3 are also user expectations, though they are not the bug. The epsilon is to both provide hysteresis and to not miss "hairy edge" clicks where the mouse or finger touches down in the button but jitters off before its released.

Screenshots

Screen.Recording.2024-12-16.155227.mp4

Desktop (please complete the following information):

  • Device: n/a
  • OS: Windows 11, Ubuntu 24 (both native)
  • Browser: Firefox (see the egui demo)
  • Version: 29
@barries barries added the bug Something is broken label Dec 16, 2024
@barries barries changed the title Widgets "unpress" when drag starts Widgets "unpress" when mouse is dragged a tiny distance. Dec 16, 2024
@YgorSouza
Copy link
Contributor

This is actually a feature. It is controlled by these options:

pub struct InputOptions {
/// After a pointer-down event, if the pointer moves more than this, it won't become a click.
pub max_click_dist: f32,
/// If the pointer is down for longer than this it will no longer register as a click.
///
/// If a touch is held for this many seconds while still, then it will register as a
/// "long-touch" which is equivalent to a secondary click.
///
/// This is to support "press and hold for context menu" on touch screens.
pub max_click_duration: f64,
/// The new pointer press must come within this many seconds from previous pointer release
/// for double click (or when this value is doubled, triple click) to count.
pub max_double_click_delay: f64,
}

This type is not in the crate docs for some reason, but you can access it through Context::options_mut.

ui.ctx().options_mut(|opt| opt.input_options.max_click_dist = f32::INFINITY);

You can also try it out in the demo app.

image

However, when you do that, the response records a click when you release the button outside the rect, which is different from what you want, and from how most GUIs work, I guess. I'm not sure if it is intentional or a bug, but maybe another option could be added to configure this behavior. A field to specify what counts as a click, with 3 variants:

  • Pointer release anywhere (the current behavior)
  • Pointer release inside the area (what you suggest, and the most common behavior)
  • Pointer press (what John Carmack recommends)

@barries
Copy link
Author

barries commented Dec 18, 2024

Thanks, and especially for the undocumented tips! We'll tweak those for now, but this really seems like a behavior that should default out-of-the-box to the most common behavior because that's, well, what most UIs have trained their users to expect, and what I'm guessing most new UI frameworks hew to.

The John Carmack approach works well for things like ESTOP buttons, but leads to unexpected behaviors on other buttons--like the screen changing before they lift off. I'm guessing that there are a few UIs in gaming where the reaction time is similarly paramount, but probably not most, so the most-usable-in-general (i.e. most common) behavior seems like a natural default, so settings screens, lock screens, dialogs and other "normal" UI contexts act, well, normally. Also, some UIs need to react to press-and-hold actions, and defaulting to the "most common behavior" enables that.

I'm leaving this open so it can be resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken
Projects
None yet
Development

No branches or pull requests

2 participants