[gtk+] flowbox: correct the behavior with "can-focus"==FALSE



commit 3c253c46a5d3979475a6cd968cd15c85f0bf26b0
Author: Rafal Luzynski <digitalfreak lingonborough com>
Date:   Sun Aug 23 02:32:21 2015 +0200

    flowbox: correct the behavior with "can-focus"==FALSE
    
    In fact there were two issues:
    
    1. GtkFlowBoxChild with "can-focus"==FALSE should pass the focus
    to its child immediately.
    2. GtkFlowBox with "can-focus"==FALSE should cease its custom keynav
    implementation and fall back to the default GtkContainer behavior
    which is more natural.
    
    Thanks to these changes the flow box can act as a better replacement
    for GtkGrid and similar containers.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=753371

 gtk/gtkflowbox.c |   63 ++++++++++++++++++++++++++++++++++++++++++-----------
 gtk/gtkflowbox.h |    2 +-
 2 files changed, 51 insertions(+), 14 deletions(-)
---
diff --git a/gtk/gtkflowbox.c b/gtk/gtkflowbox.c
index bfd1490..84fae7d 100644
--- a/gtk/gtkflowbox.c
+++ b/gtk/gtkflowbox.c
@@ -292,6 +292,23 @@ gtk_flow_box_child_focus (GtkWidget        *widget,
 
   child = gtk_bin_get_child (GTK_BIN (widget));
 
+  /* Without "can-focus" flag try to pass the focus to the child immediately */
+  if (!gtk_widget_get_can_focus (widget))
+    {
+      if (child)
+        {
+          if (gtk_widget_child_focus (child, direction))
+            {
+              GtkFlowBox *box;
+              box = gtk_flow_box_child_get_box (GTK_FLOW_BOX_CHILD (widget));
+              if (box)
+                gtk_flow_box_update_cursor (box, GTK_FLOW_BOX_CHILD (widget));
+              return TRUE;
+            }
+        }
+      return FALSE;
+    }
+
   g_object_get (widget, "has-focus", &had_focus, NULL);
   if (had_focus)
     {
@@ -3193,6 +3210,12 @@ gtk_flow_box_focus (GtkWidget        *widget,
   GSequenceIter *iter;
   GtkFlowBoxChild *next_focus_child;
 
+  /* Without "can-focus" flag fall back to the default behavior immediately */
+  if (!gtk_widget_get_can_focus (widget))
+    {
+      return GTK_WIDGET_CLASS (gtk_flow_box_parent_class)->focus (widget, direction);
+    }
+
   focus_child = gtk_container_get_focus_child (GTK_CONTAINER (box));
   next_focus_child = NULL;
 
@@ -3313,7 +3336,7 @@ gtk_flow_box_toggle_cursor_child (GtkFlowBox *box)
     gtk_flow_box_select_and_activate (box, priv->cursor_child);
 }
 
-static void
+static gboolean
 gtk_flow_box_move_cursor (GtkFlowBox      *box,
                           GtkMovementStep  step,
                           gint             count)
@@ -3331,6 +3354,10 @@ gtk_flow_box_move_cursor (GtkFlowBox      *box,
   GtkAdjustment *adjustment;
   gboolean vertical;
 
+  /* Without "can-focus" flag fall back to the default behavior immediately */
+  if (!gtk_widget_get_can_focus (GTK_WIDGET (box)))
+    return FALSE;
+
   vertical = priv->orientation == GTK_ORIENTATION_VERTICAL;
 
   if (vertical)
@@ -3479,17 +3506,25 @@ gtk_flow_box_move_cursor (GtkFlowBox      *box,
 
       if (!gtk_widget_keynav_failed (GTK_WIDGET (box), direction))
         {
-          GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (box));
+          return FALSE;
+        }
 
-          if (toplevel)
-            gtk_widget_child_focus (toplevel,
-                                    direction == GTK_DIR_UP ?
-                                    GTK_DIR_TAB_BACKWARD :
-                                    GTK_DIR_TAB_FORWARD);
+      return TRUE;
+    }
 
-        }
+  /* If the child has its "can-focus" property set to FALSE then it will
+   * not grab the focus. We must pass the focus to its child directly.
+   */
+  if (!gtk_widget_get_can_focus (GTK_WIDGET (child)))
+    {
+      GtkWidget *subchild;
 
-      return;
+      subchild = gtk_bin_get_child (GTK_BIN (child));
+      if (subchild)
+        {
+          GtkDirectionType direction = count < 0 ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
+          gtk_widget_child_focus (subchild, direction);
+        }
     }
 
   get_current_selection_modifiers (GTK_WIDGET (box), &modify, &extend);
@@ -3497,6 +3532,7 @@ gtk_flow_box_move_cursor (GtkFlowBox      *box,
   gtk_flow_box_update_cursor (box, child);
   if (!modify)
     gtk_flow_box_update_selection (box, child, FALSE, extend);
+  return TRUE;
 }
 
 /* Selection {{{2 */
@@ -3845,8 +3881,6 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
    * The ::move-cursor signal is a
    * [keybinding signal][GtkBindingSignal]
    * which gets emitted when the user initiates a cursor movement.
-   * If the cursor is not visible in @text_view, this signal causes
-   * the viewport to be moved instead.
    *
    * Applications should not connect to it, but may emit it with
    * g_signal_emit_by_name() if they need to control the cursor
@@ -3859,14 +3893,17 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
    * - Arrow keys move by individual children
    * - Home/End keys move to the ends of the box
    * - PageUp/PageDown keys move vertically by pages
+   *
+   * Returns: %TRUE to stop other handlers from being invoked for the event.
+   * %FALSE to propagate the event further.
    */
   signals[MOVE_CURSOR] = g_signal_new (I_("move-cursor"),
                                        GTK_TYPE_FLOW_BOX,
                                        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                                        G_STRUCT_OFFSET (GtkFlowBoxClass, move_cursor),
                                        NULL, NULL,
-                                       _gtk_marshal_VOID__ENUM_INT,
-                                       G_TYPE_NONE, 2,
+                                       _gtk_marshal_BOOLEAN__ENUM_INT,
+                                       G_TYPE_BOOLEAN, 2,
                                        GTK_TYPE_MOVEMENT_STEP, G_TYPE_INT);
   /**
    * GtkFlowBox::select-all:
diff --git a/gtk/gtkflowbox.h b/gtk/gtkflowbox.h
index f15a86a..0b6ad4d 100644
--- a/gtk/gtkflowbox.h
+++ b/gtk/gtkflowbox.h
@@ -61,7 +61,7 @@ struct _GtkFlowBoxClass
   void (*selected_children_changed)  (GtkFlowBox        *box);
   void (*activate_cursor_child)      (GtkFlowBox        *box);
   void (*toggle_cursor_child)        (GtkFlowBox        *box);
-  void (*move_cursor)                (GtkFlowBox        *box,
+  gboolean (*move_cursor)            (GtkFlowBox        *box,
                                       GtkMovementStep    step,
                                       gint               count);
   void (*select_all)                 (GtkFlowBox        *box);


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