[gtk+] GtkStack: Improve focus handling



commit 123c6dc5586dd19d04055cc329e6507d602c869a
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed Dec 10 22:32:45 2014 -0500

    GtkStack: Improve focus handling
    
    Add notebook-like focus handling: Keep track of the last focused
    descendent of each page, and focus it again when switching back
    to the page. If there is no last focused child, we move the focus
    into the page as if the user had hit Tab.

 gtk/gtkstack.c |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index 9726bed..b880c64 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -112,6 +112,7 @@ struct _GtkStackChildInfo {
   gchar *title;
   gchar *icon_name;
   gboolean needs_attention;
+  GtkWidget *last_focus;
 };
 
 typedef struct {
@@ -996,6 +997,9 @@ set_visible_child (GtkStack               *stack,
   GtkStackChildInfo *info;
   GtkWidget *widget = GTK_WIDGET (stack);
   GList *l;
+  GtkWidget *toplevel;
+  GtkWidget *focus;
+  gboolean contains_focus = FALSE;
 
   /* If none, pick first visible */
   if (child_info == NULL)
@@ -1014,6 +1018,25 @@ set_visible_child (GtkStack               *stack,
   if (child_info == priv->visible_child)
     return;
 
+  toplevel = gtk_widget_get_toplevel (widget);
+  if (GTK_IS_WINDOW (toplevel))
+    {
+      focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+      if (focus &&
+          priv->visible_child &&
+          gtk_widget_is_ancestor (focus, priv->visible_child->widget))
+        {
+          contains_focus = TRUE;
+
+          if (priv->visible_child->last_focus)
+            g_object_remove_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
+                                          (gpointer *)&priv->visible_child->last_focus);
+          priv->visible_child->last_focus = focus;
+          g_object_add_weak_pointer (G_OBJECT (priv->visible_child->last_focus),
+                                     (gpointer *)&priv->visible_child->last_focus);
+        }
+    }
+
   if (priv->last_visible_child)
     gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
   priv->last_visible_child = NULL;
@@ -1033,7 +1056,17 @@ set_visible_child (GtkStack               *stack,
   priv->visible_child = child_info;
 
   if (child_info)
-    gtk_widget_set_child_visible (child_info->widget, TRUE);
+    {
+      gtk_widget_set_child_visible (child_info->widget, TRUE);
+
+      if (contains_focus)
+        {
+          if (child_info->last_focus)
+            gtk_widget_grab_focus (child_info->last_focus);
+          else
+            gtk_widget_child_focus (child_info->widget, GTK_DIR_TAB_FORWARD);
+        }
+    }
 
   if ((child_info == NULL || priv->last_visible_child == NULL) &&
       is_direction_dependent_transition (transition_type))
@@ -1164,6 +1197,7 @@ gtk_stack_add (GtkContainer *container,
   child_info->title = NULL;
   child_info->icon_name = NULL;
   child_info->needs_attention = FALSE;
+  child_info->last_focus = NULL;
 
   priv->children = g_list_append (priv->children, child_info);
 
@@ -1224,6 +1258,11 @@ gtk_stack_remove (GtkContainer *container,
   g_free (child_info->name);
   g_free (child_info->title);
   g_free (child_info->icon_name);
+
+  if (child_info->last_focus)
+    g_object_remove_weak_pointer (G_OBJECT (child_info->last_focus),
+                                  (gpointer *)&child_info->last_focus);
+
   g_slice_free (GtkStackChildInfo, child_info);
 
   if ((priv->hhomogeneous || priv->vhomogeneous) && was_visible)


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