diff --git a/CHANGELOG.md b/CHANGELOG.md index acedc3633a..11ea902a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ You can find its changes [documented below](#070---2021-01-01). - GTK Shell: Prevent mangling of newline characters in clipboard ([#1695] by [@ForLoveOfCats]) - Use correct fill rule when rendering SVG paths ([#1606] by [@SecondFlight]) - Correctly capture and use stroke properties when rendering SVG paths ([#1647] by [@SecondFlight]) +- focus-chain now only includes non hidden (`should_propagate_to_hidden()` on `Event` and `Lifecylce`) widgets ([#1724] by [@xarvic]) - Fixed layout of scrollbar with very small viewports ([#1715] by [@andrewhickman]) ### Visual @@ -682,6 +683,7 @@ Last release without a changelog :( [#1702]: https://github.com/linebender/druid/pull/1702 [#1713]: https://github.com/linebender/druid/pull/1713 [#1715]: https://github.com/linebender/druid/pull/1715 +[#1724]: https://github.com/linebender/druid/pull/1724 [Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master [0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0 diff --git a/druid/src/core.rs b/druid/src/core.rs index 0c08731288..f9b98500d2 100644 --- a/druid/src/core.rs +++ b/druid/src/core.rs @@ -912,6 +912,8 @@ impl> WidgetPod { // we may send an extra event after the actual event let mut extra_event = None; + let had_focus = self.state.has_focus; + let recurse = match event { LifeCycle::Internal(internal) => match internal { InternalLifeCycle::RouteWidgetAdded => { @@ -1035,6 +1037,10 @@ impl> WidgetPod { } LifeCycle::BuildFocusChain => { if self.state.update_focus_chain { + // Replace has_focus to check if the value changed in the meantime + let is_focused = ctx.state.focus_widget == Some(self.state.id); + self.state.has_focus = is_focused; + self.state.focus_chain.clear(); true } else { @@ -1082,6 +1088,17 @@ impl> WidgetPod { // Update focus-chain of our parent LifeCycle::BuildFocusChain => { self.state.update_focus_chain = false; + + // had_focus is the old focus value. state.has_focus was repaced with ctx.is_focused(). + // Therefore if had_focus is true but state.has_focus is false then the widget which is + // currently focused is not part of the functional tree anymore + // (Lifecycle::BuildFocusChain.should_propagate_to_hidden() is false!) and should + // resign the focus. + if had_focus && !self.state.has_focus { + self.state.request_focus = Some(FocusChange::Resign); + } + self.state.has_focus = had_focus; + if !self.state.is_disabled() { ctx.widget_state.focus_chain.extend(&self.state.focus_chain); } diff --git a/druid/src/event.rs b/druid/src/event.rs index ef9552eb20..816e305986 100644 --- a/druid/src/event.rs +++ b/druid/src/event.rs @@ -428,10 +428,11 @@ impl LifeCycle { pub fn should_propagate_to_hidden(&self) -> bool { match self { LifeCycle::Internal(internal) => internal.should_propagate_to_hidden(), - LifeCycle::WidgetAdded | LifeCycle::DisabledChanged(_) | LifeCycle::BuildFocusChain => { - true - } - LifeCycle::Size(_) | LifeCycle::HotChanged(_) | LifeCycle::FocusChanged(_) => false, + LifeCycle::WidgetAdded | LifeCycle::DisabledChanged(_) => true, + LifeCycle::Size(_) + | LifeCycle::HotChanged(_) + | LifeCycle::FocusChanged(_) + | LifeCycle::BuildFocusChain => false, } } }