From 1d2ff9a069a3f1a8d2510dfcf7177420d2b076e3 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 21 Aug 2015 20:51:03 -0400 Subject: [PATCH] list box: Make focusable headers possible Previously we were assuming that only list box rows could occur as focus children of a list box, and would crash if that wasn't the case. This commit handles this case, and integrates focusable headers into directional keynav and the focus chain. The typical case of using separators as headers is not affected by this change. https://bugzilla.gnome.org/show_bug.cgi?id=753694 --- gtk/gtklistbox.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c index c278326b86..0e8f9c0b3a 100644 --- a/gtk/gtklistbox.c +++ b/gtk/gtklistbox.c @@ -1939,8 +1939,11 @@ gtk_list_box_focus (GtkWidget *widget, GtkListBoxPrivate *priv = BOX_PRIV (box); GtkWidget *focus_child; GtkListBoxRow *next_focus_row; + GtkWidget *row; + GtkWidget *header; focus_child = gtk_container_get_focus_child ((GtkContainer *)box); + next_focus_row = NULL; if (focus_child != NULL) { @@ -1951,7 +1954,23 @@ gtk_list_box_focus (GtkWidget *widget, if (direction == GTK_DIR_UP || direction == GTK_DIR_TAB_BACKWARD) { - i = gtk_list_box_get_previous_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->iter); + if (GTK_IS_LIST_BOX_ROW (focus_child)) + { + header = ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->header; + if (header && gtk_widget_child_focus (header, direction)) + return TRUE; + } + + if (GTK_IS_LIST_BOX_ROW (focus_child)) + row = focus_child; + else + row = g_hash_table_lookup (priv->header_hash, focus_child); + + if (GTK_IS_LIST_BOX_ROW (row)) + i = gtk_list_box_get_previous_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (row))->iter); + else + i = NULL; + while (i != NULL) { if (gtk_widget_get_sensitive (g_sequence_get (i))) @@ -1965,7 +1984,17 @@ gtk_list_box_focus (GtkWidget *widget, } else if (direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD) { - i = gtk_list_box_get_next_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->iter); + if (GTK_IS_LIST_BOX_ROW (focus_child)) + i = gtk_list_box_get_next_visible (box, ROW_PRIV (GTK_LIST_BOX_ROW (focus_child))->iter); + else + { + row = g_hash_table_lookup (priv->header_hash, focus_child); + if (GTK_IS_LIST_BOX_ROW (row)) + i = ROW_PRIV (GTK_LIST_BOX_ROW (row))->iter; + else + i = NULL; + } + while (!g_sequence_iter_is_end (i)) { if (gtk_widget_get_sensitive (g_sequence_get (i))) @@ -2008,10 +2037,17 @@ gtk_list_box_focus (GtkWidget *widget, return FALSE; } + if (direction == GTK_DIR_DOWN || direction == GTK_DIR_TAB_FORWARD) + { + header = ROW_PRIV (next_focus_row)->header; + if (header && gtk_widget_child_focus (header, direction)) + return TRUE; + } + if (gtk_widget_child_focus (GTK_WIDGET (next_focus_row), direction)) return TRUE; - return TRUE; + return FALSE; } static gboolean