From b0cdb6b07410e7f99ab33d339c58f3c7ad1f0240 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 30 Oct 2020 18:03:40 +0100 Subject: [PATCH] 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. --- Libraries/LibGUI/Window.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Libraries/LibGUI/Window.cpp b/Libraries/LibGUI/Window.cpp index 9ca5b352f2..50e44912bb 100644 --- a/Libraries/LibGUI/Window.cpp +++ b/Libraries/LibGUI/Window.cpp @@ -730,6 +730,7 @@ Vector Window::focusable_widgets(FocusSource source) const if (!m_main_widget) return {}; + HashTable seen_widgets; Vector collected_widgets; Function collect_focusable_widgets = [&](auto& widget) { @@ -746,8 +747,11 @@ Vector Window::focusable_widgets(FocusSource source) const break; } - if (widget_accepts_focus) - collected_widgets.append(&widget); + if (widget_accepts_focus) { + 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) { if (!child.is_visible()) return IterationDecision::Continue;