diff --git a/src/lib.rs b/src/lib.rs index c886db1b9b..98c9f3a687 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,7 @@ pub struct EventCtx<'a> { window: &'a WindowHandle, base_state: &'a mut BaseState, had_active: bool, + is_handled: bool, } pub struct UpdateCtx { @@ -226,7 +227,7 @@ impl> WidgetPod { data: &mut T, env: &Env, ) -> Option { - if !event.recurse() { + if ctx.is_handled || !event.recurse() { // This function is called by containers to propagate an event from // containers to children. Non-recurse events will be invoked directly // from other points in the library. @@ -237,6 +238,7 @@ impl> WidgetPod { window: &ctx.window, base_state: &mut self.state, had_active, + is_handled: false, }; let rect = child_ctx.base_state.layout_rect; // Note: could also represent this as `Option`. @@ -283,6 +285,7 @@ impl> WidgetPod { ctx.base_state.needs_inval |= child_ctx.base_state.needs_inval; ctx.base_state.is_hot |= child_ctx.base_state.is_hot; ctx.base_state.has_active |= child_ctx.base_state.has_active; + ctx.is_handled |= child_ctx.is_handled; action } @@ -349,6 +352,7 @@ impl UiState { window: &self.handle, base_state: &mut base_state, had_active: self.root.state.has_active, + is_handled: false, }; let env = self.root_env(); let action = self.root.event(&event, &mut ctx, &mut self.data, &env); @@ -360,7 +364,7 @@ impl UiState { self.handle.invalidate(); } // TODO: process actions - action.is_some() + ctx.is_handled() } fn paint(&mut self, piet: &mut Piet) -> bool { @@ -526,6 +530,17 @@ impl<'a> EventCtx<'a> { pub fn window(&self) -> &WindowHandle { &self.window } + + /// Set the event as "handled", which stops its propagation to other + /// widgets. + pub fn set_handled(&mut self) { + self.is_handled = true; + } + + /// Determine whether the event has been handled by some other widget. + pub fn is_handled(&self) -> bool { + self.is_handled + } } impl UpdateCtx { diff --git a/src/widget/scroll.rs b/src/widget/scroll.rs index 5a5660e1de..fc6c8ef3c5 100644 --- a/src/widget/scroll.rs +++ b/src/widget/scroll.rs @@ -100,18 +100,21 @@ impl Widget for Scroll { ) -> Option { let size = ctx.base_state.size(); let viewport = Rect::from_origin_size(Point::ORIGIN, size); - if let Event::Wheel(wheel) = event { - if self.scroll(wheel.delta, size) { - ctx.invalidate(); - } - } - // TODO: cancellation logic let child_event = event.transform_scroll(self.scroll_offset, viewport); - if let Some(child_event) = child_event { + let action = if let Some(child_event) = child_event { self.child.event(&child_event, ctx, data, env) } else { None + }; + if !ctx.is_handled() { + if let Event::Wheel(wheel) = event { + if self.scroll(wheel.delta, size) { + ctx.invalidate(); + ctx.set_handled(); + } + } } + action } fn update(&mut self, ctx: &mut UpdateCtx, _old_data: Option<&T>, data: &T, env: &Env) {