[gtk/focusable-containers: 2/3] widget: Improve focus handling



commit ddee5cfc43618f413197252dfaedeeb42edc8e52
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jun 11 17:09:10 2019 +0000

    widget: Improve focus handling
    
    Make gtk_widget_real_focus do the right
    thing for focusable widgets with children.
    
    A case where this is (now) relevant is
    an entry with a context popover.

 gtk/gtkwidget.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 58 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 07080d6b9e..dc2d00c207 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -5522,31 +5522,79 @@ gtk_widget_real_style_updated (GtkWidget *widget)
     }
 }
 
+static gboolean
+direction_is_forward (GtkDirectionType direction)
+{
+  switch (direction)
+    {
+    case GTK_DIR_TAB_FORWARD:
+    case GTK_DIR_RIGHT:
+    case GTK_DIR_DOWN:
+      return TRUE;
+    case GTK_DIR_TAB_BACKWARD:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_UP:
+      return FALSE;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
 static gboolean
 gtk_widget_real_focus (GtkWidget         *widget,
                        GtkDirectionType   direction)
 {
-  if (gtk_widget_get_can_focus (widget))
+  GtkWidget *focus;
+
+  /* The easy case: not focusable. Just try the children */
+  if (!gtk_widget_get_can_focus (widget))
+    {
+      if (gtk_widget_focus_move (widget, direction))
+        return TRUE;
+
+      return FALSE;
+    }
+
+  /* For focusable widgets, we want to focus the widget
+   * before its children. We differentiate 3 cases:
+   * 1) focus is currently on widget
+   * 2) focus is on some child
+   * 3) focus is outside
+   */
+
+  if (gtk_widget_is_focus (widget))
+    {
+      if (direction_is_forward (direction) &&
+          gtk_widget_focus_move (widget, direction))
+        return TRUE;
+
+      return FALSE;
+    }
+
+  focus = gtk_window_get_focus (GTK_WINDOW (gtk_widget_get_root (widget)));
+
+  if (focus && gtk_widget_is_ancestor (focus, widget))
     {
-      if (!gtk_widget_is_focus (widget))
+      if (gtk_widget_focus_move (widget, direction))
+        return TRUE;
+
+      if (direction_is_forward (direction))
+        return FALSE;
+      else
         {
           gtk_widget_grab_focus (widget);
           return TRUE;
         }
     }
-  else if (_gtk_widget_get_first_child (widget) == NULL)
-    {
-      /* No children, no possibility to focus anything */
-      return FALSE;
-    }
-  else
+
+  if (!direction_is_forward (direction))
     {
-      /* Try focusing any of the child widgets, depending on the given direction */
       if (gtk_widget_focus_move (widget, direction))
         return TRUE;
     }
 
-  return FALSE;
+  gtk_widget_grab_focus (widget);
+  return TRUE;
 }
 
 static void


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