summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElias Projahn <johrpan@gmail.com>2021-02-03 20:54:06 +0100
committerElias Projahn <johrpan@gmail.com>2021-02-03 21:22:55 +0100
commita7ae94c06e5126ef9c1065d684cb555e01d1a9ed (patch)
tree48a9f5f37efdb3b766b38eb400790903b62e95a1
parent120f2768e6a1e4aca6efc5481309cf6979a194be (diff)
downloadgtk+-a7ae94c06e5126ef9c1065d684cb555e01d1a9ed.tar.gz
listbox: Fix handling of non-focusable rows
This commit modifies the gtk_list_box_row_grab_focus() implementation to correctly return FALSE in case the row couldn't be focused. This behavior will also be honored by gtk_list_box_row_focus() to properly handle focus in that case. To achieve that, the method has been restructured slightly. Closes #3633
-rw-r--r--gtk/gtklistbox.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index 6445e70d05..6632dbc1be 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -2941,52 +2941,59 @@ gtk_list_box_row_focus (GtkWidget *widget,
GtkListBoxRow *row = GTK_LIST_BOX_ROW (widget);
gboolean had_focus = FALSE;
GtkWidget *child = ROW_PRIV (row)->child;
+ GtkWidget *focus_child = gtk_widget_get_focus_child (widget);
g_object_get (widget, "has-focus", &had_focus, NULL);
- if (had_focus)
+
+ /* If a child has focus, always try to navigate within that first. */
+ if (focus_child != NULL)
+ {
+ if (gtk_widget_child_focus (focus_child, direction))
+ return TRUE;
+ }
+
+ /* Otherwise, decide based on the direction. */
+ if (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD)
{
- /* If on row, going right, enter into possible container */
- if (child &&
- (direction == GTK_DIR_RIGHT || direction == GTK_DIR_TAB_FORWARD))
+ /* If a child was focused and focus couldn't be moved within that (see
+ * above), let focus leave. */
+ if (focus_child != NULL)
+ return FALSE;
+
+ /* If the row is not focused, try to focus it. */
+ if (!had_focus && gtk_widget_grab_focus (widget))
{
- if (gtk_widget_child_focus (GTK_WIDGET (child), direction))
- return TRUE;
+ gtk_list_box_row_set_focus (row);
+ return TRUE;
}
+ /* Finally, try to move focus into the child. */
+ if (child != NULL && gtk_widget_child_focus (child, direction))
+ return TRUE;
+
return FALSE;
}
- else if (gtk_widget_get_focus_child (widget) != NULL)
+ else if (direction == GTK_DIR_LEFT || direction == GTK_DIR_TAB_BACKWARD)
{
- /* Child has focus, always navigate inside it first */
- if (gtk_widget_child_focus (gtk_widget_get_focus_child (widget), direction))
+ /* If the row itself is focused, let focus leave it. */
+ if (had_focus)
+ return FALSE;
+
+ /* Otherwise, let focus enter the child widget, if possible. */
+ if (child != NULL && 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)
+ /* If that didn't work, try to focus the row itself. */
+ if (gtk_widget_grab_focus (widget))
{
- /* grab focus explicitly, since gtk_list_box_row_set_focus()
- * refuses to steal it from a child
- */
- gtk_widget_grab_focus (GTK_WIDGET (row));
gtk_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;
- }
- gtk_list_box_row_set_focus (row);
- return TRUE;
- }
+ return FALSE;
}
static void
@@ -3422,12 +3429,15 @@ gtk_list_box_row_grab_focus (GtkWidget *widget)
g_return_val_if_fail (box != NULL, FALSE);
- gtk_widget_grab_focus_self (widget);
+ if (gtk_widget_grab_focus_self (widget))
+ {
+ if (box->cursor_row != row)
+ gtk_list_box_update_cursor (box, row, FALSE);
- if (box->cursor_row != row)
- gtk_list_box_update_cursor (box, row, FALSE);
+ return TRUE;
+ }
- return TRUE;
+ return FALSE;
}
static void