1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:47:45 +00:00

LibGUI: Deduplicate widgets with proxied focus in focus chain

When computing the chain of focusable widgets in a window, only include
each widget once (to avoid loops) and resolve focus proxies immediately
instead of lazily. This prevents the focus from getting stuck when
cycling backwards and hitting a proxy that points forward.
This commit is contained in:
Andreas Kling 2020-10-30 18:03:40 +01:00
parent 9ccae7a908
commit b0cdb6b074

View file

@ -730,6 +730,7 @@ Vector<Widget*> Window::focusable_widgets(FocusSource source) const
if (!m_main_widget) if (!m_main_widget)
return {}; return {};
HashTable<Widget*> seen_widgets;
Vector<Widget*> collected_widgets; Vector<Widget*> collected_widgets;
Function<void(Widget&)> collect_focusable_widgets = [&](auto& widget) { Function<void(Widget&)> collect_focusable_widgets = [&](auto& widget) {
@ -746,8 +747,11 @@ Vector<Widget*> Window::focusable_widgets(FocusSource source) const
break; break;
} }
if (widget_accepts_focus) if (widget_accepts_focus) {
collected_widgets.append(&widget); auto& effective_focus_widget = widget.focus_proxy() ? *widget.focus_proxy() : widget;
if (seen_widgets.set(&effective_focus_widget) == AK::HashSetResult::InsertedNewEntry)
collected_widgets.append(&effective_focus_widget);
}
widget.for_each_child_widget([&](auto& child) { widget.for_each_child_widget([&](auto& child) {
if (!child.is_visible()) if (!child.is_visible())
return IterationDecision::Continue; return IterationDecision::Continue;