gpui: Support hitbox blocking mouse interaction except scrolling (#31712)

tl;dr: This adds `.block_mouse_except_scroll()` which should typically
be used instead of `.occlude()` for cases when the mouse shouldn't
interact with elements drawn below an element. The rationale for
treating scroll events differently:

* Mouse move / click / styles / tooltips are for elements the user is
interacting with directly.
* Mouse scroll events are about finding the current outer scroll
container.

Most use of `occlude` should probably be switched to this, but I figured
I'd derisk this change by minimizing behavior changes to just the 3 uses
of `block_mouse_except_scroll`.

GPUI changes:

* Added `InteractiveElement::block_mouse_except_scroll()`, and removes
`stop_mouse_events_except_scroll()`

* Added `Hitbox::should_handle_scroll()` to be used when handling scroll
wheel events.

* `Window::insert_hitbox` now takes `HitboxBehavior` instead of
`occlude: bool`.

    - `false` for that bool is now `HitboxBehavior::Normal`.

    - `true` for that bool is now `HitboxBehavior::BlockMouse`.
    
    - The new mode is `HitboxBehavior::BlockMouseExceptScroll`.

* Removes `Default` impl for `HitboxId` since applications should not
manually create `HitboxId(0)`.

Release Notes:

- N/A
This commit is contained in:
Michael Sloan 2025-05-29 15:41:15 -06:00 committed by GitHub
parent 2abc5893c1
commit 9086784038
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 231 additions and 99 deletions

View file

@ -136,7 +136,9 @@ pub struct IndentGuideLayout {
/// Implements the necessary functionality for rendering indent guides inside a uniform list.
mod uniform_list {
use gpui::{DispatchPhase, Hitbox, MouseButton, MouseDownEvent, MouseMoveEvent};
use gpui::{
DispatchPhase, Hitbox, HitboxBehavior, MouseButton, MouseDownEvent, MouseMoveEvent,
};
use super::*;
@ -256,7 +258,12 @@ mod uniform_list {
.indent_guides
.as_ref()
.iter()
.map(|guide| window.insert_hitbox(guide.hitbox.unwrap_or(guide.bounds), false))
.map(|guide| {
window.insert_hitbox(
guide.hitbox.unwrap_or(guide.bounds),
HitboxBehavior::Normal,
)
})
.collect();
Self::PrepaintState::Interactive {
hitboxes: Rc::new(hitboxes),