[egg-list-box/row-widget: 7/7] listbox: Move focusability to row widget



commit db44b5ef9a24ef7ad8e0a785ed182e575d946deb
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jun 7 17:03:34 2013 +0200

    listbox: Move focusability to row widget
    
    We set the focused widget to be the actual row, rather
    than the listbox.

 egg-list-box.c |  236 +++++++++++++++++++++++++++++---------------------------
 1 files changed, 121 insertions(+), 115 deletions(-)
---
diff --git a/egg-list-box.c b/egg-list-box.c
index c6851fc..abe7c8e 100644
--- a/egg-list-box.c
+++ b/egg-list-box.c
@@ -224,7 +224,6 @@ egg_list_box_init (EggListBox *list_box)
   list_box->priv = priv =
     G_TYPE_INSTANCE_GET_PRIVATE (list_box, EGG_TYPE_LIST_BOX, EggListBoxPrivate);
 
-  gtk_widget_set_can_focus (GTK_WIDGET (list_box), TRUE);
   gtk_widget_set_has_window (GTK_WIDGET (list_box), TRUE);
   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (list_box), TRUE);
   priv->selection_mode = GTK_SELECTION_SINGLE;
@@ -794,8 +793,8 @@ egg_list_box_update_cursor (EggListBox *list_box,
   EggListBoxPrivate *priv = list_box->priv;
 
   priv->cursor_row = row;
-  gtk_widget_grab_focus (GTK_WIDGET (list_box));
-  gtk_widget_queue_draw (GTK_WIDGET (list_box));
+  gtk_widget_grab_focus (GTK_WIDGET (row));
+  gtk_widget_queue_draw (GTK_WIDGET (row));
   if (row != NULL && priv->adjustment != NULL)
     {
       GtkAllocation allocation;
@@ -1026,134 +1025,65 @@ egg_list_box_real_focus (GtkWidget* widget, GtkDirectionType direction)
 {
   EggListBox *list_box = EGG_LIST_BOX (widget);
   EggListBoxPrivate *priv = list_box->priv;
-  gboolean had_focus = FALSE;
-  gboolean focus_into = FALSE;
-  EggListBoxRow *recurse_into;
-  EggListBoxRow *current_focus_row;
+  GtkWidget *focus_child;
   EggListBoxRow *next_focus_row;
-  gboolean modify_selection_pressed;
-  GdkModifierType state = 0;
-
-  recurse_into = NULL;
-  focus_into = TRUE;
 
-  g_object_get (GTK_WIDGET (list_box), "has-focus", &had_focus, NULL);
-  current_focus_row = NULL;
+  focus_child = gtk_container_get_focus_child ((GtkContainer*) list_box);
   next_focus_row = NULL;
-  if (had_focus)
+  if (focus_child != NULL)
     {
-      /* If on row, going right, enter into possible container */
-      if (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD)
-       {
-         if (priv->cursor_row != NULL)
-           recurse_into = priv->cursor_row;
-       }
-      current_focus_row = priv->cursor_row;
-      /* Unless we're going up/down we're always leaving
-      the container */
-      if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN)
-       focus_into = FALSE;
-    }
-  else if (gtk_container_get_focus_child ((GtkContainer*) list_box) != NULL)
-    {
-      /* There is a focus child, always navigate inside it first */
-      recurse_into = EGG_LIST_BOX_ROW (gtk_container_get_focus_child ((GtkContainer*) list_box));
-      current_focus_row = recurse_into;
+      GSequenceIter* i;
 
-      /* If exiting child container to the right, exit row */
-      if (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD)
-       focus_into = FALSE;
+      if (gtk_widget_child_focus (focus_child, direction))
+        return TRUE;
 
-      /* If exiting child container to the left, select row or out */
-      if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
-       next_focus_row = current_focus_row;
+      if (direction == GTK_DIR_UP || direction == GTK_DIR_TAB_BACKWARD)
+        {
+          i = egg_list_box_get_previous_visible (list_box, priv->cursor_row->priv->iter);
+          if (i != NULL)
+            next_focus_row = g_sequence_get (i);
+        }
+      else if (direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD)
+        {
+          i = egg_list_box_get_next_visible (list_box, priv->cursor_row->priv->iter);
+          if (!g_sequence_iter_is_end (i))
+            next_focus_row = g_sequence_get (i);
+        }
     }
   else
     {
-      /* If coming from the left, enter into possible container */
-      if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
-       {
-         if (priv->selected_row != NULL)
-           recurse_into = priv->selected_row;
-       }
-    }
-
-  if (recurse_into != NULL)
-    {
-      if (gtk_widget_child_focus (GTK_WIDGET (recurse_into), direction))
-       return TRUE;
-    }
-
-  if (!focus_into)
-    return FALSE; /* Focus is leaving us */
+      /* No current focus row */
 
-  /* TODO: This doesn't handle up/down going into a focusable separator */
-
-  if (next_focus_row == NULL)
-    {
-      if (current_focus_row != NULL)
-       {
-         GSequenceIter* i;
-         if (direction == GTK_DIR_UP)
-           {
-             i = egg_list_box_get_previous_visible (list_box, current_focus_row->priv->iter);
-             if (i != NULL)
-               next_focus_row = g_sequence_get (i);
-
-           }
-         else
-           {
-             i = egg_list_box_get_next_visible (list_box, current_focus_row->priv->iter);
-             if (!g_sequence_iter_is_end (i))
-               next_focus_row = g_sequence_get (i);
-           }
-       }
-      else
-       {
-         switch (direction)
-           {
-           case GTK_DIR_UP:
-           case GTK_DIR_TAB_BACKWARD:
-             next_focus_row = priv->selected_row;
-             if (next_focus_row == NULL)
-               next_focus_row = egg_list_box_get_last_visible (list_box);
-             break;
-           default:
-             next_focus_row = priv->selected_row;
-             if (next_focus_row == NULL)
-               next_focus_row =
-                 egg_list_box_get_first_visible (list_box);
-             break;
-           }
-       }
+      switch (direction)
+        {
+        case GTK_DIR_UP:
+        case GTK_DIR_TAB_BACKWARD:
+          next_focus_row = priv->selected_row;
+          if (next_focus_row == NULL)
+            next_focus_row = egg_list_box_get_last_visible (list_box);
+          break;
+        default:
+          next_focus_row = priv->selected_row;
+          if (next_focus_row == NULL)
+            next_focus_row =
+              egg_list_box_get_first_visible (list_box);
+          break;
+        }
     }
 
   if (next_focus_row == NULL)
     {
       if (direction == GTK_DIR_UP || direction == GTK_DIR_DOWN)
-       {
+        {
           if (gtk_widget_keynav_failed (GTK_WIDGET (list_box), direction))
-           return TRUE;
-       }
+            return TRUE;
+        }
 
       return FALSE;
     }
 
-  modify_selection_pressed = FALSE;
-  if (gtk_get_current_event_state (&state))
-    {
-      GdkModifierType modify_mod_mask;
-      modify_mod_mask =
-       gtk_widget_get_modifier_mask (GTK_WIDGET (list_box),
-                                     GDK_MODIFIER_INTENT_MODIFY_SELECTION);
-      if ((state & modify_mod_mask) == modify_mod_mask)
-       modify_selection_pressed = TRUE;
-    }
-
-  if (modify_selection_pressed)
-    egg_list_box_update_cursor (list_box, next_focus_row);
-  else
-    egg_list_box_update_selected (list_box, next_focus_row);
+  if (gtk_widget_child_focus (GTK_WIDGET (next_focus_row), direction))
+    return TRUE;
 
   return TRUE;
 }
@@ -2022,6 +1952,7 @@ egg_list_box_row_init (EggListBoxRow *row)
   row->priv = priv =
     G_TYPE_INSTANCE_GET_PRIVATE (row, EGG_TYPE_LIST_BOX_ROW, EggListBoxRowPrivate);
 
+  gtk_widget_set_can_focus (GTK_WIDGET (row), TRUE);
   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (row), TRUE);
 }
 
@@ -2066,6 +1997,83 @@ egg_list_box_row_get_box (EggListBoxRow *row)
 }
 
 static void
+egg_list_box_row_set_focus (EggListBoxRow *row)
+{
+  EggListBox *list_box = egg_list_box_row_get_box (row);
+  GdkModifierType state = 0;
+  gboolean modify_selection_pressed;
+
+  modify_selection_pressed = FALSE;
+  if (gtk_get_current_event_state (&state))
+    {
+      GdkModifierType modify_mod_mask;
+      modify_mod_mask =
+        gtk_widget_get_modifier_mask (GTK_WIDGET (list_box),
+                                      GDK_MODIFIER_INTENT_MODIFY_SELECTION);
+      if ((state & modify_mod_mask) == modify_mod_mask)
+        modify_selection_pressed = TRUE;
+    }
+
+  if (modify_selection_pressed)
+    egg_list_box_update_cursor (list_box, row);
+  else
+    egg_list_box_update_selected (list_box, row);
+}
+
+static gboolean
+egg_list_box_row_real_focus (GtkWidget* widget, GtkDirectionType direction)
+{
+  EggListBoxRow *row = EGG_LIST_BOX_ROW (widget);
+  gboolean had_focus = FALSE;
+  GtkWidget *child;
+
+  child = gtk_bin_get_child (GTK_BIN (widget));
+
+  g_object_get (widget, "has-focus", &had_focus, NULL);
+  if (had_focus)
+    {
+      /* If on row, going right, enter into possible container */
+      if (child &&
+          (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD))
+        {
+          if (gtk_widget_child_focus (GTK_WIDGET (child), direction))
+            return TRUE;
+        }
+
+      return FALSE;
+    }
+  else if (gtk_container_get_focus_child (GTK_CONTAINER (row)) != NULL)
+    {
+      /* Child has focus, always navigate inside it first */
+
+      if (gtk_widget_child_focus (child, direction))
+        return TRUE;
+
+      /* If exiting child container to the left, select row  */
+      if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
+        {
+          egg_list_box_row_set_focus (row);
+          return TRUE;
+        }
+
+      return FALSE;
+    }
+  else
+    {
+      /* If coming from the left, enter into possible container */
+      if (child &&
+          (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD))
+        {
+          if (gtk_widget_child_focus (child, direction))
+            return TRUE;
+        }
+
+      egg_list_box_row_set_focus (row);
+      return TRUE;
+    }
+}
+
+static void
 egg_list_box_row_real_show (GtkWidget *widget)
 {
   EggListBoxRow *row = EGG_LIST_BOX_ROW (widget);
@@ -2095,7 +2103,6 @@ static gboolean
 egg_list_box_row_real_draw (GtkWidget* widget, cairo_t* cr)
 {
   EggListBoxRow *row = EGG_LIST_BOX_ROW (widget);
-  EggListBox *list_box;
   GtkAllocation allocation = {0};
   GtkStyleContext* context;
   GtkStateFlags state;
@@ -2109,9 +2116,7 @@ egg_list_box_row_real_draw (GtkWidget* widget, cairo_t* cr)
   gtk_render_background (context, cr, (gdouble) 0, (gdouble) 0, (gdouble) allocation.width, (gdouble) 
allocation.height);
   gtk_render_frame (context, cr, (gdouble) 0, (gdouble) 0, (gdouble) allocation.width, (gdouble) 
allocation.height);
 
-  list_box = egg_list_box_row_get_box (row);
-  if (list_box && gtk_widget_has_visible_focus (GTK_WIDGET (list_box)) &&
-      row == list_box->priv->cursor_row)
+  if (gtk_widget_has_visible_focus (GTK_WIDGET (row)))
     {
       gtk_style_context_get_border (context, state, &border);
 
@@ -2318,4 +2323,5 @@ egg_list_box_row_class_init (EggListBoxRowClass *klass)
   widget_class->get_preferred_width = egg_list_box_row_real_get_preferred_width;
   widget_class->get_preferred_width_for_height = egg_list_box_row_real_get_preferred_width_for_height;
   widget_class->size_allocate = egg_list_box_row_real_size_allocate;
+  widget_class->focus = egg_list_box_row_real_focus;
 }


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