From fa86fdfdd48196b271c9b630e794f811d6962ffe Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Tue, 27 Oct 2020 19:32:26 +0000 Subject: [PATCH 1/5] Add `should_propagate_to_hidden` methods to `Event` and `LifeCycle` --- druid/src/event.rs | 32 ++++++++++++++++++++++++++++++++ druid/src/widget/tabs.rs | 32 ++------------------------------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/druid/src/event.rs b/druid/src/event.rs index a918a308cb..5c53b9a12b 100644 --- a/druid/src/event.rs +++ b/druid/src/event.rs @@ -300,6 +300,38 @@ impl Event { _ => Some(self.clone()), } } + + /// Whether this event should be sent to widgets which are currently not visible + /// (for example the hidden tabs in a tabs widget). + pub fn should_propagate_to_hidden(&self) -> bool { + match self { + Event::WindowConnected + | Event::WindowSize(_) + | Event::Timer(_) + | Event::AnimFrame(_) + | Event::Command(_) + | Event::Internal(_) => true, + Event::MouseDown(_) + | Event::MouseUp(_) + | Event::MouseMove(_) + | Event::Wheel(_) + | Event::KeyDown(_) + | Event::KeyUp(_) + | Event::Paste(_) + | Event::Zoom(_) => false, + } + } +} + +impl LifeCycle { + /// Whether this event should be sent to widgets which are currently not visible + /// (for example the hidden tabs in a tabs widget). + pub fn should_propagate_to_hidden(&self) -> bool { + match self { + LifeCycle::WidgetAdded | LifeCycle::Internal(_) => true, + LifeCycle::Size(_) | LifeCycle::HotChanged(_) | LifeCycle::FocusChanged(_) => false, + } + } } #[cfg(test)] diff --git a/druid/src/widget/tabs.rs b/druid/src/widget/tabs.rs index 13a9523ce6..ae229f5753 100644 --- a/druid/src/widget/tabs.rs +++ b/druid/src/widget/tabs.rs @@ -550,37 +550,9 @@ impl TabsBody { } } -/// Possibly should be moved to Event -fn hidden_should_receive_event(evt: &Event) -> bool { - match evt { - Event::WindowConnected - | Event::WindowSize(_) - | Event::Timer(_) - | Event::AnimFrame(_) - | Event::Command(_) - | Event::Internal(_) => true, - Event::MouseDown(_) - | Event::MouseUp(_) - | Event::MouseMove(_) - | Event::Wheel(_) - | Event::KeyDown(_) - | Event::KeyUp(_) - | Event::Paste(_) - | Event::Zoom(_) => false, - } -} - -/// Possibly should be moved to Lifecycle. -fn hidden_should_receive_lifecycle(lc: &LifeCycle) -> bool { - match lc { - LifeCycle::WidgetAdded | LifeCycle::Internal(_) => true, - LifeCycle::Size(_) | LifeCycle::HotChanged(_) | LifeCycle::FocusChanged(_) => false, - } -} - impl Widget> for TabsBody { fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut TabsState, env: &Env) { - if hidden_should_receive_event(event) { + if event.should_propagate_to_hidden() { for child in self.child_pods() { child.event(ctx, event, &mut data.inner, env); } @@ -612,7 +584,7 @@ impl Widget> for TabsBody { ctx.request_layout(); } - if hidden_should_receive_lifecycle(event) { + if event.should_propagate_to_hidden() { for child in self.child_pods() { child.lifecycle(ctx, event, &data.inner, env); } From 1b086f4e75e84cb66fd0a08c962579bd68f1bb7c Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Tue, 27 Oct 2020 19:39:47 +0000 Subject: [PATCH 2/5] Add `Either::current_widget` to clean up code slightly --- druid/src/widget/either.rs | 40 ++++++++++++++------------------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/druid/src/widget/either.rs b/druid/src/widget/either.rs index 5725fd7e56..c00a6ba83d 100644 --- a/druid/src/widget/either.rs +++ b/druid/src/widget/either.rs @@ -46,11 +46,7 @@ impl Either { impl Widget for Either { fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { - if self.current { - self.true_branch.event(ctx, event, data, env) - } else { - self.false_branch.event(ctx, event, data, env) - } + self.current_widget().event(ctx, event, data, env) } fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) { @@ -67,34 +63,28 @@ impl Widget for Either { self.current = current; ctx.request_layout(); } - if self.current { - self.true_branch.update(ctx, data, env); - } else { - self.false_branch.update(ctx, data, env); - } + self.current_widget().update(ctx, data, env) } fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size { - if self.current { - let size = self.true_branch.layout(ctx, bc, data, env); - self.true_branch - .set_layout_rect(ctx, data, env, size.to_rect()); - ctx.set_paint_insets(self.true_branch.paint_insets()); - size - } else { - let size = self.false_branch.layout(ctx, bc, data, env); - self.false_branch - .set_layout_rect(ctx, data, env, size.to_rect()); - ctx.set_paint_insets(self.false_branch.paint_insets()); - size - } + let current_widget = self.current_widget(); + let size = current_widget.layout(ctx, bc, data, env); + current_widget.set_layout_rect(ctx, data, env, size.to_rect()); + ctx.set_paint_insets(current_widget.paint_insets()); + size } fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) { + self.current_widget().paint(ctx, data, env) + } +} + +impl Either { + fn current_widget(&mut self) -> &mut WidgetPod>> { if self.current { - self.true_branch.paint_raw(ctx, data, env); + &mut self.true_branch } else { - self.false_branch.paint_raw(ctx, data, env); + &mut self.false_branch } } } From e46578afbfacf628cb50f6511a26c444e5051be3 Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Tue, 27 Oct 2020 19:42:10 +0000 Subject: [PATCH 3/5] Propagate events to hidden widgets in `Either` --- druid/src/widget/either.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/druid/src/widget/either.rs b/druid/src/widget/either.rs index c00a6ba83d..fca237e0ae 100644 --- a/druid/src/widget/either.rs +++ b/druid/src/widget/either.rs @@ -46,15 +46,25 @@ impl Either { impl Widget for Either { fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { - self.current_widget().event(ctx, event, data, env) + if event.should_propagate_to_hidden() { + self.true_branch.event(ctx, event, data, env); + self.false_branch.event(ctx, event, data, env); + } else { + self.current_widget().event(ctx, event, data, env) + } } fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) { if let LifeCycle::WidgetAdded = event { self.current = (self.closure)(data, env); } - self.true_branch.lifecycle(ctx, event, data, env); - self.false_branch.lifecycle(ctx, event, data, env); + + if event.should_propagate_to_hidden() { + self.true_branch.lifecycle(ctx, event, data, env); + self.false_branch.lifecycle(ctx, event, data, env); + } else { + self.current_widget().lifecycle(ctx, event, data, env) + } } fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &T, data: &T, env: &Env) { From 6407860840fa2bfd63a93db82965cd89baa7d158 Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Thu, 29 Oct 2020 21:29:17 +0000 Subject: [PATCH 4/5] Make `missed call to set_layout_rect` warning conditional on `should_propagate_to_hidden` --- druid/src/core.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/druid/src/core.rs b/druid/src/core.rs index 6809318590..50a00ee580 100644 --- a/druid/src/core.rs +++ b/druid/src/core.rs @@ -550,21 +550,13 @@ impl> WidgetPod { } // log if we seem not to be laid out when we should be - if self.state.layout_rect.is_none() { - match event { - Event::Internal(_) => (), - Event::Timer(_) => (), - Event::WindowConnected => (), - Event::WindowSize(_) => (), - _ => { - log::warn!( - "Widget '{}' received an event ({:?}) without having been laid out. \ - This likely indicates a missed call to set_layout_rect.", - self.inner.type_name(), - event, - ); - } - } + if self.state.layout_rect.is_none() && !event.should_propagate_to_hidden() { + log::warn!( + "Widget '{}' received an event ({:?}) without having been laid out. \ + This likely indicates a missed call to set_layout_rect.", + self.inner.type_name(), + event, + ); } // TODO: factor as much logic as possible into monomorphic functions. From bca89c7486d6e0c5e69c3b53d17b7e66dbc3e166 Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Fri, 30 Oct 2020 18:28:15 +0000 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6597aa983..4d300409b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ You can find its changes [documented below](#060---2020-06-01). - Widgets can specify a baseline, flex rows can align baselines ([#1295] by [@cmyr]) - `TextBox::with_text_color` and `TextBox::set_text_color` ([#1320] by [@cmyr]) - `Checkbox::set_text` to update the label. ([#1346] by [@finnerale]) +- `Event::should_propagate_to_hidden` and `Lifecycle::should_propagate_to_hidden` to determine whether an event should be sent to hidden widgets (e.g. in `Tabs` or `Either`). ([#1351] by [@andrewhickman]) ### Changed @@ -114,6 +115,7 @@ You can find its changes [documented below](#060---2020-06-01). - Fix `widget::Either` using the wrong paint insets ([#1299] by [@andrewhickman]) - Various fixes to cross-platform menus ([#1306] by [@raphlinus]) - Improve Windows 7 DXGI compatibility ([#1311] by [@raphlinus]) +- Fixed `Either` not passing events to its hidden child correctly. ([#1351] by [@andrewhickman]) ### Visual @@ -517,6 +519,7 @@ Last release without a changelog :( [#1320]: https://github.com/linebender/druid/pull/1320 [#1326]: https://github.com/linebender/druid/pull/1326 [#1346]: https://github.com/linebender/druid/pull/1346 +[#1351]: https://github.com/linebender/druid/pull/1351 [Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master [0.6.0]: https://github.com/linebender/druid/compare/v0.5.0...v0.6.0