Skip to content

multi-click support#24023

Merged
alice-i-cecile merged 11 commits intobevyengine:mainfrom
ickshonpe:click-counts
Apr 29, 2026
Merged

multi-click support#24023
alice-i-cecile merged 11 commits intobevyengine:mainfrom
ickshonpe:click-counts

Conversation

@ickshonpe
Copy link
Copy Markdown
Contributor

@ickshonpe ickshonpe commented Apr 28, 2026

Objective

Implement minimal multi-click support.
Add double click to select word and triple click to select all support to text input widgets.

Fixes #23874

Solution

New MULTI_CLICK_DURATION constant that sets the max time between clicks for them to count as consecutive.

Added a field count to Click. 1 is a single click, 2 is a double click, 3 is a triple click and so on. It's a u8 and saturates at 255 if you click that many times.

Current multi-click state is stored in a field clicking on PointerButtonState.
The clicking state is cleared after MULTI_CLICK_DURATION without another click.

New SelectWordAtPoint TextEdit.

New observer system on_pointer_click in bevy_ui_widgets::text_input. This queues SelectWordAtPoint for 2 clicks and SelectAll for 3 or more. Click events are dispatched on release, so they happen after Press. The Press for a double click might move the cursor but that doesn't affect the SelectWordAtPoint edit that is dispatched.

The implementation is deliberately minimal, I just added here what was needed for the text input. Left for followups:

  • Tracking the initial click position and returning the displacement with Click.
  • Spatial tolerance (clicks are only multi-clicks if the pointer hasn't moved too far).
  • Configurable multi-click duration.

We could add a separate MultiClick event instead. It seems to me things would be more complicated with both Click and MultiClick observer systems though.

Testing

Text inputs now support double click to select a word and triple click to select all:

cargo run --example multiline_text_input

Added SelectWordAtPoint TextEdit.
Added on_pointer_click observer to text_input. On double and triple click events queue appropriate TextEdits
@ickshonpe ickshonpe added A-UI Graphical user interfaces, styles, layouts, and widgets A-Text Rendering and layout for characters A-Picking Pointing at and selecting objects of all sorts labels Apr 28, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in UI Apr 28, 2026
@ickshonpe ickshonpe added C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 28, 2026
Comment thread crates/bevy_picking/src/events.rs
/// Duration between the pointer pressed and lifted for this click
pub duration: Duration,
/// Number of consecutive clicks, starting at `1`.
pub count: u8,
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.

New minigame idea just dropped!

Copy link
Copy Markdown
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

Oh lovely. That's very simple!

@alice-i-cecile alice-i-cecile added X-Uncontroversial This work is generally agreed upon A-Input Player input via keyboard, mouse, gamepad, and more labels Apr 29, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Input Apr 29, 2026
Comment thread crates/bevy_ui_widgets/src/text_input.rs Outdated
Comment thread crates/bevy_ui_widgets/src/text_input.rs
@ickshonpe ickshonpe added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 29, 2026
Comment thread crates/bevy_ui_widgets/src/text_input.rs Outdated
Comment on lines +67 to +68
// TODO: add optional feature-flagged support for fetching this from the OS preferences
pub const MULTI_CLICK_DURATION: Duration = Duration::from_millis(500);
Copy link
Copy Markdown
Contributor

@SpecificProtagonist SpecificProtagonist Apr 29, 2026

Choose a reason for hiding this comment

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

This should be a resource instead so it can be overwritten.
(I wish that there already was a crate to fetch this setting, but I haven't found one)

Copy link
Copy Markdown
Contributor

@viridia viridia Apr 29, 2026

Choose a reason for hiding this comment

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

There's no crate that does this AFAIK. Instead, we'll eventually need to add OS-specific code in bevy_platform. For example, the windows version looks like this:

#[cfg(target_os = "windows")]
mod platform {
    use super::*;
 
    pub fn get() -> Option<Duration> {
        // GetDoubleClickTime returns the interval in milliseconds.
        // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdoubleclicktime
        extern "system" {
            fn GetDoubleClickTime() -> u32;
        }
        let ms = unsafe { GetDoubleClickTime() };
        if ms == 0 {
            None
        } else {
            Some(Duration::from_millis(ms as u64))
        }
    }
}

Also, on Linux there's no single setting, you have to parse the Gnome or KDE settings files, this will take some time at startup.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Which is why a separate crate would be nice – Bevy isn't the only library having this issue.

Copy link
Copy Markdown
Contributor Author

@ickshonpe ickshonpe Apr 29, 2026

Choose a reason for hiding this comment

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

Should this be a resource instead? (I wish that there already was a crate to fetch this setting, but I haven't found one)

I'm just using a constant here because I wanted to keep this a narrow PR focused on the multi-click implementation. It should definitely be user configurable, or fetched from the OS if possible, though.

Copy link
Copy Markdown
Contributor Author

@ickshonpe ickshonpe Apr 29, 2026

Choose a reason for hiding this comment

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

There's spatial tolerance as well, which we'd also want to get from the OS. Left it out from this PR because it has to account for scale factor (which is annoying).

Co-authored-by: Talin <viridia@gmail.com>
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Apr 29, 2026
Merged via the queue into bevyengine:main with commit 68c4223 Apr 29, 2026
38 checks passed
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in UI Apr 29, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in Input Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Input Player input via keyboard, mouse, gamepad, and more A-Picking Pointing at and selecting objects of all sorts A-Text Rendering and layout for characters A-UI Graphical user interfaces, styles, layouts, and widgets C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Uncontroversial This work is generally agreed upon

Projects

Status: Done
Status: Done

Development

Successfully merging this pull request may close these issues.

Double-click events

5 participants