diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 8ec9bc8784..5aedeb5d34 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -455,7 +455,15 @@ gtk_list_base_focus (GtkWidget *widget, GtkDirectionType direction) { GtkListBase *self = GTK_LIST_BASE (widget); + GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); guint old, pos, n_items; + GtkWidget *focus_child; + GtkListItemManagerItem *item; + + focus_child = gtk_widget_get_focus_child (widget); + /* focus is moving around fine inside the focus child, don't disturb it */ + if (focus_child && gtk_widget_child_focus (focus_child, direction)) + return TRUE; pos = gtk_list_base_get_focus_position (self); n_items = gtk_list_base_get_n_items (self); @@ -468,12 +476,12 @@ gtk_list_base_focus (GtkWidget *widget, pos = 0; } - else if (gtk_widget_get_focus_child (widget) == NULL) + else if (focus_child == NULL) { /* Focus was outside the list, just grab the old focus item * while keeping the selection intact. */ - return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, FALSE, FALSE, FALSE); + old = GTK_INVALID_LIST_POSITION; } else { @@ -513,14 +521,18 @@ gtk_list_base_focus (GtkWidget *widget, } } - if (old != pos) - { - return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, TRUE, FALSE, FALSE); - } - else - { - return TRUE; - } + if (old == pos) + return TRUE; + + item = gtk_list_item_manager_get_nth (priv->item_manager, pos, NULL); + if (item == NULL) + return FALSE; + + /* This shouldn't really happen, but if it does, oh well */ + if (item->widget == NULL) + return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, TRUE, FALSE, FALSE); + + return gtk_widget_child_focus (item->widget, direction); } static void @@ -1460,6 +1472,7 @@ gtk_list_base_grab_focus_on_item (GtkListBase *self, { GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); GtkListItemManagerItem *item; + gboolean success; item = gtk_list_item_manager_get_nth (priv->item_manager, pos, NULL); if (item == NULL) @@ -1478,17 +1491,18 @@ gtk_list_base_grab_focus_on_item (GtkListBase *self, item = gtk_list_item_manager_get_nth (priv->item_manager, pos, NULL); g_assert (item->widget); - if (!gtk_widget_grab_focus (item->widget)) - return FALSE; + success = gtk_widget_grab_focus (item->widget); gtk_list_item_tracker_free (priv->item_manager, tracker); } else { - if (!gtk_widget_grab_focus (item->widget)) - return FALSE; + success = gtk_widget_grab_focus (item->widget); } + if (!success) + return FALSE; + if (select) gtk_list_base_select_item (self, pos, modify, extend); diff --git a/gtk/gtklistitemwidget.c b/gtk/gtklistitemwidget.c index 2e6078d704..3057dac55d 100644 --- a/gtk/gtklistitemwidget.c +++ b/gtk/gtklistitemwidget.c @@ -83,8 +83,7 @@ static gboolean gtk_list_item_widget_focus (GtkWidget *widget, GtkDirectionType direction) { - GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (widget); - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); + GtkWidget *child, *focus_child; /* The idea of this function is the following: * 1. If any child can take focus, do not ever attempt @@ -96,19 +95,24 @@ gtk_list_item_widget_focus (GtkWidget *widget, * activation and selection handling, but no useless widgets * get focused and moving focus is as fast as possible. */ - if (priv->list_item && priv->list_item->child) + + focus_child = gtk_widget_get_focus_child (widget); + if (focus_child && gtk_widget_child_focus (focus_child, direction)) + return TRUE; + + for (child = focus_child ? gtk_widget_get_next_sibling (focus_child) + : gtk_widget_get_first_child (widget); + child; + child = gtk_widget_get_next_sibling (child)) { - if (gtk_widget_get_focus_child (widget)) - return FALSE; - if (gtk_widget_child_focus (priv->list_item->child, direction)) + if (gtk_widget_child_focus (child, direction)) return TRUE; } - if (gtk_widget_is_focus (widget)) + if (focus_child) return FALSE; - if (!gtk_widget_get_can_focus (widget) || - !priv->list_item->selectable) + if (gtk_widget_is_focus (widget)) return FALSE; return gtk_widget_grab_focus (widget); @@ -119,9 +123,19 @@ gtk_list_item_widget_grab_focus (GtkWidget *widget) { GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (widget); GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); + GtkWidget *child; - if (priv->list_item && priv->list_item->child && gtk_widget_grab_focus (priv->list_item->child)) - return TRUE; + for (child = gtk_widget_get_first_child (widget); + child; + child = gtk_widget_get_next_sibling (child)) + { + if (gtk_widget_grab_focus (child)) + return TRUE; + } + + if (priv->list_item == NULL || + !priv->list_item->selectable) + return FALSE; return GTK_WIDGET_CLASS (gtk_list_item_widget_parent_class)->grab_focus (widget); }