[gtk/wip/carlosg/for-master] gtkwidget: Revert focus to parent on hide()




commit be342c4d2c46e9389fd89df73ad59c3263e8683f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Oct 1 16:54:10 2020 +0200

    gtkwidget: Revert focus to parent on hide()
    
    If a widget is being hidden while containing the focus, it can
    get caught on a state that it (or a child) is still the focus widget,
    but the focus cannot cycle back to visible widgets. One such case are
    popover menus, which will keep focus cycling within the hidden popover
    menu items after closed.
    
    It is generally undesirable to keep focus on a widget after hiding,
    so in order to fix this and other similar situations, ensure focus is
    restored to the parent after hiding a widget in the chain to the focus.
    
    Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3214

 gtk/gtkwidget.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 2ea7fb9c3a..f9cda90dd2 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -2588,6 +2588,39 @@ gtk_widget_real_show (GtkWidget *widget)
     gtk_widget_map (widget);
 }
 
+static void
+maybe_revert_focus_to_parent (GtkWidget *widget)
+{
+  GtkRoot *root;
+  GtkWidget *parent, *focus = NULL;
+
+  parent = gtk_widget_get_parent (widget);
+  if (!parent)
+    return;
+
+  root = _gtk_widget_get_root (widget);
+  if (!root)
+    return;
+
+  focus = gtk_root_get_focus (root);
+  if (!focus)
+    return;
+
+  if (focus == widget || gtk_widget_is_ancestor (focus, widget))
+    {
+      while (parent)
+        {
+          if (_gtk_widget_get_visible (parent))
+            {
+              gtk_widget_grab_focus (parent);
+              break;
+            }
+
+          parent = gtk_widget_get_parent (parent);
+        }
+    }
+}
+
 /**
  * gtk_widget_hide:
  * @widget: a #GtkWidget
@@ -2637,6 +2670,8 @@ gtk_widget_hide (GtkWidget *widget)
 
       gtk_widget_queue_allocate (widget);
 
+      maybe_revert_focus_to_parent (widget);
+
       gtk_widget_pop_verify_invariants (widget);
       g_object_unref (widget);
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]