[gtk/wip/matthiasc/focus2: 20/33] Add a child-focusable flag



commit 09b01f28ad2389f5978b555e1518847edac6e23c
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Mar 3 00:35:02 2019 -0500

    Add a child-focusable flag
    
    This gives a convenient way to exclude children from
    the focus chain.

 gtk/gtkwidget.c        | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--
 gtk/gtkwidget.h        |  6 +++++
 gtk/gtkwidgetfocus.c   |  2 +-
 gtk/gtkwidgetprivate.h |  1 +
 4 files changed, 75 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index e6addd15ee..d7dff52e7a 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -2812,6 +2812,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
 
   priv->visible = gtk_widget_class_get_visible_by_default (g_class);
   priv->child_visible = TRUE;
+  priv->child_focusable = TRUE;
   priv->name = NULL;
   priv->user_alpha = 255;
   priv->alpha = 255;
@@ -3101,10 +3102,11 @@ gtk_widget_unparent (GtkWidget *widget)
   toplevel = NULL;
 
   /* Removing a widget from a container restores the child visible
-   * flag to the default state, so it doesn't affect the child
-   * in the next parent.
+   * and focusable flags to the default state, so they don't affect
+   * the child in the next parent.
    */
   priv->child_visible = TRUE;
+  priv->child_focusable = TRUE;
 
   old_parent = priv->parent;
   if (old_parent)
@@ -13503,3 +13505,66 @@ gtk_widget_get_height (GtkWidget *widget)
 
   return priv->height;
 }
+
+/**
+ * gtk_widget_get_child_focusable:
+ * @widget: a #GtkWidget
+ *
+ * Gets the value set with gtk_widget_set_child_focusable().
+ * If you feel a need to use this function, your code probably
+ * needs reorganization.
+ *
+ * This function is only useful for widget implementations and
+ * never should be called by an application.
+ *
+ * Returns: %TRUE if the widget is focusable
+ **/
+gboolean
+gtk_widget_get_child_focusable (GtkWidget *widget)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+  return priv->child_focusable;
+}
+
+/**
+ * gtk_widget_set_child_focusable:
+ * @widget: a #GtkWidget
+ * @focusable: if %TRUE, @widget should be focusable
+ *
+ * Sets whether @widget should be able to receive focus
+ *
+ * Child focusability will be reset to its default state of %TRUE
+ * when the widget is removed from its parent.
+ *
+ * This function is only useful for widget implementations and
+ * never should be called by an application.
+ **/
+void
+gtk_widget_set_child_focusable (GtkWidget *widget,
+                                gboolean   focusable)
+{
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  focusable = !!focusable;
+
+  if (priv->child_focusable == focusable)
+    return;
+
+  if (focusable)
+    priv->child_focusable = TRUE;
+  else
+    {
+      GtkWidget *toplevel;
+
+      priv->child_focusable = FALSE;
+
+      toplevel = _gtk_widget_get_toplevel (widget);
+      if (toplevel != widget && _gtk_widget_is_toplevel (toplevel))
+       _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
+    }
+}
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index 38d33893cd..28b34a97e4 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -1063,6 +1063,12 @@ void                    gtk_widget_insert_before        (GtkWidget *widget,
 GDK_AVAILABLE_IN_ALL
 void                    gtk_widget_set_focus_child      (GtkWidget *widget,
                                                          GtkWidget *child);
+GDK_AVAILABLE_IN_ALL
+void                    gtk_widget_set_child_focusable  (GtkWidget *widget,
+                                                         gboolean   focusable);
+GDK_AVAILABLE_IN_ALL
+gboolean                gtk_widget_get_child_focusable  (GtkWidget *widget);
+
 GDK_AVAILABLE_IN_ALL
 void                    gtk_widget_snapshot_child       (GtkWidget   *widget,
                                                          GtkWidget   *child,
diff --git a/gtk/gtkwidgetfocus.c b/gtk/gtkwidgetfocus.c
index c835b0f64d..2be4f75369 100644
--- a/gtk/gtkwidgetfocus.c
+++ b/gtk/gtkwidgetfocus.c
@@ -423,7 +423,7 @@ gtk_widget_focus_sort (GtkWidget        *widget,
            child = _gtk_widget_get_next_sibling (child))
         {
           if (_gtk_widget_get_realized (child) &&
-              _gtk_widget_is_drawable (child) &&
+              gtk_widget_get_child_focusable (child) &&
               gtk_widget_get_sensitive (child))
             g_ptr_array_add (focus_order, child);
         }
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index b3f706ebc8..7848874954 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -72,6 +72,7 @@ struct _GtkWidgetPrivate
   guint has_grab              : 1;
   guint shadowed              : 1;
   guint child_visible         : 1;
+  guint child_focusable       : 1;
   guint multidevice           : 1;
   guint can_pick              : 1;
 


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