Report consumption from run_event

`Event::consumes` says whether having run uses up what triggered it,
defaulting to no. `run_fn` already calls `should_run` per registration,
so it ors that across everything that ran and hands it back through
`run_event`. `CursorSenses` answers it with the sense it matched: a press
or a scroll is used up, hovering is not.

That drops `TypeEventManager::registered` and the second pass over a
widget's senses -- the match that decides consumption is now the same one
that decides whether the handler runs.

A cursor that is only resting still stops at the layer it is over, which
`run_event` cannot report because nothing need answer for it to be true.
It must not stop at a widget it has merely left, though, or ending a hover
above blocks the hover below: `leaving_a_widget_does_not_block_the_layer_below`
is that case, and it fails on `main` too.
This commit is contained in:
iris committed 2026-09-13 20:53:34 -04:00
1 parent e53ce585e6
commit 827d317f41
5 files changed
+57 -26

No files matched your search

+4 -6
View File
@@ -135,19 +135,16 @@ impl<Rsc: HasEvents + 'static, E: Event> TypeEventManager<Rsc, E> {
));
}
/// What this widget registered, without running any of it.
pub fn registered(&self, id: WidgetId) -> impl Iterator<Item = &E> {
self.map.get(&id).into_iter().flatten().map(|(e, _)| e)
}
pub fn run_fn<'a>(
&mut self,
id: impl IdLike,
) -> impl for<'b> FnOnce(EventCtx<'_, Rsc, E::Data<'b>>, &mut Rsc) + 'a {
) -> impl for<'b> FnOnce(EventCtx<'_, Rsc, E::Data<'b>>, &mut Rsc) -> bool + 'a {
let fs = self.map.get(&id.id()).cloned().unwrap_or_default();
move |ctx, rsc| {
let mut consumed = false;
for (e, f) in fs {
if let Some(data) = e.should_run(&ctx.data) {
consumed |= e.consumes(&data);
f(
EventCtx {
state: ctx.state,
@@ -157,6 +154,7 @@ impl<Rsc: HasEvents + 'static, E: Event> TypeEventManager<Rsc, E> {
)
}
}
consumed
}
}
}
+8
View File
@@ -13,6 +13,14 @@ pub trait Event: Sized + 'static + Clone {
fn should_run<'a>(&self, data: &Self::Data<'a>) -> Option<Self::Data<'a>> {
Some(data.clone())
}
/// Whether having run on this data uses up whatever triggered it, so
/// nothing further should see it. `run_event` reports back the `or` of
/// this across everything that ran.
#[allow(unused_variables)]
fn consumes(&self, data: &Self::Data<'_>) -> bool {
false
}
}
pub trait EventLike {
+2 -1
View File
@@ -21,12 +21,13 @@ pub trait HasEvents: Sized + UiRsc + HasState {
}
pub trait RunEvents: HasEvents {
/// Whether anything that ran consumed the input; see `Event::consumes`.
fn run_event<E: EventLike>(
&mut self,
id: impl IdLike,
data: <E::Event as Event>::Data<'_>,
state: &mut Self::State,
) {
) -> bool {
let f = self.events_mut().get_type::<E>().run_fn(id);
f(EventCtx { state, data }, self)
}