From b11b4b29e998b7c971e512580d6c5481bf4eb1f6 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 30 Oct 2020 23:38:42 +0100 Subject: [PATCH] LibGUI: Add Widget::has_focus_within() This returns true if the widget has focus, or if one of its descendant widgets does. Use this in StackWidget and TabWidget. This also fixes HackStudio crashing on startup in StackWidget, due to running before the window has a focused widget. --- Libraries/LibGUI/StackWidget.cpp | 2 +- Libraries/LibGUI/TabWidget.cpp | 3 ++- Libraries/LibGUI/Widget.cpp | 12 ++++++++++++ Libraries/LibGUI/Widget.h | 3 +++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Libraries/LibGUI/StackWidget.cpp b/Libraries/LibGUI/StackWidget.cpp index 8af53e00a99..531346195e4 100644 --- a/Libraries/LibGUI/StackWidget.cpp +++ b/Libraries/LibGUI/StackWidget.cpp @@ -43,7 +43,7 @@ void StackWidget::set_active_widget(Widget* widget) if (widget == m_active_widget) return; - bool active_widget_had_focus = m_active_widget && window() && (window()->focused_widget() == m_active_widget || m_active_widget->is_ancestor_of(*window()->focused_widget())); + bool active_widget_had_focus = m_active_widget && m_active_widget->has_focus_within(); if (m_active_widget) m_active_widget->set_visible(false); diff --git a/Libraries/LibGUI/TabWidget.cpp b/Libraries/LibGUI/TabWidget.cpp index 69d8914f977..4bafddd0499 100644 --- a/Libraries/LibGUI/TabWidget.cpp +++ b/Libraries/LibGUI/TabWidget.cpp @@ -88,12 +88,13 @@ void TabWidget::update_focus_policy() policy = FocusPolicy::NoFocus; set_focus_policy(policy); } + void TabWidget::set_active_widget(Widget* widget) { if (widget == m_active_widget) return; - bool active_widget_had_focus = m_active_widget && window() && (window()->focused_widget() == m_active_widget || m_active_widget->is_ancestor_of(*window()->focused_widget())); + bool active_widget_had_focus = m_active_widget && m_active_widget->has_focus_within(); if (m_active_widget) m_active_widget->set_visible(false); diff --git a/Libraries/LibGUI/Widget.cpp b/Libraries/LibGUI/Widget.cpp index b3997db3c36..69327e5c508 100644 --- a/Libraries/LibGUI/Widget.cpp +++ b/Libraries/LibGUI/Widget.cpp @@ -989,4 +989,16 @@ Widget* Widget::find_descendant_by_name(const String& name) }); return found_widget; } + +bool Widget::has_focus_within() const +{ + auto* window = this->window(); + if (!window) + return false; + if (!window->focused_widget()) + return false; + auto& effective_focus_widget = focus_proxy() ? *focus_proxy() : *this; + return window->focused_widget() == &effective_focus_widget || is_ancestor_of(*window->focused_widget()); +} + } diff --git a/Libraries/LibGUI/Widget.h b/Libraries/LibGUI/Widget.h index e494f6f81f3..10d3366cfc1 100644 --- a/Libraries/LibGUI/Widget.h +++ b/Libraries/LibGUI/Widget.h @@ -165,6 +165,9 @@ public: bool is_focused() const; void set_focus(bool, FocusSource = FocusSource::Programmatic); + // Returns true if this widget or one of its descendants is focused. + bool has_focus_within() const; + Widget* focus_proxy() { return m_focus_proxy; } const Widget* focus_proxy() const { return m_focus_proxy; } void set_focus_proxy(Widget*);