[gtk+/wip/baedert/focus: 15/20] widget: Allow focusing widgets with non-container parent



commit fff036e8badc024462c0dd4ee011006a2f008d94
Author: Timm Bäder <mail baedert org>
Date:   Wed Feb 8 15:50:30 2017 +0100

    widget: Allow focusing widgets with non-container parent
    
    Especially if said parent also has can-focus set to FALSE, which is a
    special-case we had before for GtkContainer instances.

 gtk/gtkwidget.c |  143 ++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 84 insertions(+), 59 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 5f84e6c..dc84149 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7159,71 +7159,68 @@ reset_focus_recurse (GtkWidget *widget,
 static void
 gtk_widget_real_grab_focus (GtkWidget *focus_widget)
 {
-  if (gtk_widget_get_can_focus (focus_widget))
-    {
-      GtkWidget *toplevel;
-      GtkWidget *widget;
+  GtkWidget *toplevel;
+  GtkWidget *widget;
 
-      /* clear the current focus setting, break if the current widget
-       * is the focus widget's parent, since containers above that will
-       * be set by the next loop.
-       */
-      toplevel = _gtk_widget_get_toplevel (focus_widget);
-      if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
-       {
-          widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
+  /* clear the current focus setting, break if the current widget
+   * is the focus widget's parent, since containers above that will
+   * be set by the next loop.
+   */
+  toplevel = _gtk_widget_get_toplevel (focus_widget);
+  if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
+    {
+      widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
 
-         if (widget == focus_widget)
-           {
-             /* We call _gtk_window_internal_set_focus() here so that the
-              * toplevel window can request the focus if necessary.
-              * This is needed when the toplevel is a GtkPlug
-              */
-             if (!gtk_widget_has_focus (widget))
-               _gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
+      if (widget == focus_widget)
+        {
+          /* We call _gtk_window_internal_set_focus() here so that the
+           * toplevel window can request the focus if necessary.
+           * This is needed when the toplevel is a GtkPlug
+           */
+          if (!gtk_widget_has_focus (widget))
+            _gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
 
-             return;
-           }
+          return;
+        }
 
-         if (widget)
-           {
-             GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
+      if (widget)
+        {
+          GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
 
-             if (widget != common_ancestor)
-               {
-                 while (widget->priv->parent)
-                   {
-                     widget = widget->priv->parent;
-                      gtk_widget_set_focus_child (widget, NULL);
-                     if (widget == common_ancestor)
-                       break;
-                   }
-               }
-           }
-       }
-      else if (toplevel != focus_widget)
-       {
-         /* gtk_widget_grab_focus() operates on a tree without window...
-          * actually, this is very questionable behavior.
-          */
+          if (widget != common_ancestor)
+            {
+              while (widget->priv->parent)
+                {
+                  widget = widget->priv->parent;
+                  gtk_widget_set_focus_child (widget, NULL);
+                  if (widget == common_ancestor)
+                    break;
+                }
+            }
+        }
+    }
+  else if (toplevel != focus_widget)
+    {
+      /* gtk_widget_grab_focus() operates on a tree without window...
+       * actually, this is very questionable behavior.
+       */
 
-          gtk_widget_forall (toplevel,
-                             reset_focus_recurse,
-                             NULL);
-       }
+      gtk_widget_forall (toplevel,
+                         reset_focus_recurse,
+                         NULL);
+    }
 
-      /* now propagate the new focus up the widget tree and finally
-       * set it on the window
-       */
-      widget = focus_widget;
-      while (widget->priv->parent)
-       {
-          gtk_widget_set_focus_child (widget->priv->parent, widget);
-         widget = widget->priv->parent;
-       }
-      if (GTK_IS_WINDOW (widget))
-       _gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
+  /* now propagate the new focus up the widget tree and finally
+   * set it on the window
+   */
+  widget = focus_widget;
+  while (widget->priv->parent)
+    {
+      gtk_widget_set_focus_child (widget->priv->parent, widget);
+      widget = widget->priv->parent;
     }
+  if (GTK_IS_WINDOW (widget))
+    _gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
 }
 
 static gboolean
@@ -7314,7 +7311,35 @@ gtk_widget_real_focus (GtkWidget         *widget,
                        GtkDirectionType   direction)
 {
   if (!gtk_widget_get_can_focus (widget))
-    return FALSE;
+    {
+      /* @widget can't be focused, but maybe one of its child widgets. */
+      GtkWidget *focus_child = gtk_widget_get_focus_child (widget);
+      GtkWidget *child;
+
+      for (child = _gtk_widget_get_first_child (widget);
+           child != NULL;
+           child = _gtk_widget_get_next_sibling (child))
+        {
+          if (focus_child)
+            {
+              if (focus_child == child)
+                {
+                  focus_child = NULL;
+
+                  if (gtk_widget_child_focus (child, direction))
+                    return TRUE;
+                }
+            }
+          else if (_gtk_widget_is_drawable (child) &&
+                   gtk_widget_is_ancestor (child, widget))
+            {
+              if (gtk_widget_child_focus (child, direction))
+                  return TRUE;
+            }
+        }
+
+      return FALSE;
+    }
 
   if (!gtk_widget_is_focus (widget))
     {


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