瀏覽代碼

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.
Andreas Kling 4 年之前
父節點
當前提交
b0cdb6b074
共有 1 個文件被更改,包括 6 次插入2 次删除
  1. 6 2
      Libraries/LibGUI/Window.cpp

+ 6 - 2
Libraries/LibGUI/Window.cpp

@@ -730,6 +730,7 @@ Vector<Widget*> Window::focusable_widgets(FocusSource source) const
     if (!m_main_widget)
         return {};
 
+    HashTable<Widget*> seen_widgets;
     Vector<Widget*> collected_widgets;
 
     Function<void(Widget&)> collect_focusable_widgets = [&](auto& widget) {
@@ -746,8 +747,11 @@ Vector<Widget*> 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;