From 571d399af5a681f2a399f64db0388c4437acc095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nelson=20Ben=C3=ADtez=20Le=C3=B3n?= Date: Wed, 5 Apr 2023 22:33:39 -0400 Subject: [PATCH] gtkwidget: better handle when trying to focus a widget with no GtkRoot Issue #5676 found a case where GTK tried to focus a widget with a NULL GtkRoot. That specific case was a GtkButton which was a GtkExpander's child, and until the GtkExpander is expanded (and thus the GtkButton becomes visible) the button has no GtkRoot, yet GTK tried to focus on it when GtkExpander's code called gtk_widget_focus_child() on it. We could change GtkExpander code to check if widget has no GtkRoot and in that case avoid calling gtk_widget_focus_child(), but it seems generally better to handle this at GtkWidget level so it may cover other widgets that could misbehave in a similar way as GtkExpander. So in this patch: We turn a critical message (failed assertion) into a proper warning which informs the user about the non-allowed action. We also make sure gtk_widget_focus_child() properly returns FALSE when called on an unrooted widget. Fixes #5676 --- gtk/gtkwidget.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index f8a96ccf6f5..846fa324441 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -5020,6 +5020,7 @@ gtk_widget_real_focus (GtkWidget *widget, GtkDirectionType direction) { GtkWidget *focus; + GtkRoot *root; /* For focusable widgets, we want to focus the widget * before its children. We differentiate 3 cases: @@ -5037,7 +5038,12 @@ gtk_widget_real_focus (GtkWidget *widget, return FALSE; } - focus = gtk_window_get_focus (GTK_WINDOW (gtk_widget_get_root (widget))); + root = gtk_widget_get_root (widget); + if (!root) { + g_warning ("Attempted to focus a widget with no GtkRoot"); + return FALSE; + } + focus = gtk_window_get_focus (GTK_WINDOW (root)); if (focus && gtk_widget_is_ancestor (focus, widget)) { @@ -6883,7 +6889,8 @@ gtk_widget_child_focus (GtkWidget *widget, if (!_gtk_widget_get_visible (widget) || !gtk_widget_is_sensitive (widget) || - !gtk_widget_get_can_focus (widget)) + !gtk_widget_get_can_focus (widget)|| + !gtk_widget_get_root (widget)) return FALSE; /* Emit ::focus in any case, even if focusable is FALSE, -- GitLab