diff options
author | Benjamin Otte <otte@redhat.com> | 2023-03-23 04:37:29 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2023-03-23 04:51:50 +0100 |
commit | 30d4629043f54b6454cd1b4f5723179bc20a0b0e (patch) | |
tree | a0e865459eb5d0e96e33eba7bb87319b90e6b387 /gtk/gtkcolumnviewrowwidget.c | |
parent | 78e72ad1deacd152885c60205d620557138e5eaf (diff) | |
download | gtk+-30d4629043f54b6454cd1b4f5723179bc20a0b0e.tar.gz |
columnview: Handle focus movement properly
- grab_focus() on a row (happens with scroll_to()) keeps the focus
column intact if possible.
- <Tab> and <Shift-Tab> move through the cells in order, and move
to the next row when at the end.
- <Up> an <Down> move to the next/prev row, keeping the same column
focused.
- <Left> and <Right> move to the prev/next cell, if one is available.
If not, they stay where they are.
Diffstat (limited to 'gtk/gtkcolumnviewrowwidget.c')
-rw-r--r-- | gtk/gtkcolumnviewrowwidget.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/gtk/gtkcolumnviewrowwidget.c b/gtk/gtkcolumnviewrowwidget.c index cf2c434356..8871ebcd0f 100644 --- a/gtk/gtkcolumnviewrowwidget.c +++ b/gtk/gtkcolumnviewrowwidget.c @@ -64,6 +64,23 @@ gtk_column_view_row_child_get_column (GtkWidget *child) g_return_val_if_reached (NULL); } +static GtkWidget * +gtk_column_view_row_widget_find_child (GtkColumnViewRowWidget *self, + GtkColumnViewColumn *column) +{ + GtkWidget *child; + + for (child = gtk_widget_get_first_child (GTK_WIDGET (self)); + child; + child = gtk_widget_get_next_sibling (child)) + { + if (gtk_column_view_row_child_get_column (child) == column) + return child; + } + + return NULL; +} + static void gtk_column_view_row_widget_update (GtkListItemBase *base, guint position, @@ -150,7 +167,9 @@ static gboolean gtk_column_view_row_widget_focus (GtkWidget *widget, GtkDirectionType direction) { + GtkColumnViewRowWidget *self = GTK_COLUMN_VIEW_ROW_WIDGET (widget); GtkWidget *child, *focus_child; + GtkColumnView *view; /* The idea of this function is the following: * 1. If any child can take focus, do not ever attempt @@ -167,6 +186,18 @@ gtk_column_view_row_widget_focus (GtkWidget *widget, if (focus_child && gtk_widget_child_focus (focus_child, direction)) return TRUE; + view = gtk_column_view_row_widget_get_column_view (self); + if (focus_child == NULL) + { + GtkColumnViewColumn *focus_column = gtk_column_view_get_focus_column (view); + if (focus_column) + { + focus_child = gtk_column_view_row_widget_find_child (self, focus_column); + if (focus_child && gtk_widget_child_focus (focus_child, direction)) + return TRUE; + } + } + for (child = gtk_column_view_next_focus_widget (widget, focus_child, direction); child; child = gtk_column_view_next_focus_widget (widget, child, direction)) @@ -175,6 +206,24 @@ gtk_column_view_row_widget_focus (GtkWidget *widget, return TRUE; } + switch (direction) + { + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_TAB_BACKWARD: + gtk_column_view_set_focus_column (view, NULL); + break; + + case GTK_DIR_LEFT: + case GTK_DIR_RIGHT: + return TRUE; + + default: + g_assert_not_reached (); + case GTK_DIR_UP: + case GTK_DIR_DOWN: + break; + } + if (focus_child) return FALSE; @@ -187,12 +236,31 @@ gtk_column_view_row_widget_focus (GtkWidget *widget, static gboolean gtk_column_view_row_widget_grab_focus (GtkWidget *widget) { - GtkWidget *child; + GtkColumnViewRowWidget *self = GTK_COLUMN_VIEW_ROW_WIDGET (widget); + GtkWidget *child, *focus_child; + GtkColumnViewColumn *focus_column; + GtkColumnView *view; - for (child = gtk_widget_get_first_child (widget); - child; + view = gtk_column_view_row_widget_get_column_view (self); + focus_column = gtk_column_view_get_focus_column (view); + if (focus_column) + { + focus_child = gtk_column_view_row_widget_find_child (self, focus_column); + if (focus_child && gtk_widget_grab_focus (focus_child)) + return TRUE; + } + else + focus_child = NULL; + + for (child = focus_child ? gtk_widget_get_next_sibling (focus_child) : gtk_widget_get_first_child (widget); + child != focus_child; child = gtk_widget_get_next_sibling (child)) { + /* When we started iterating at focus_child, we want to iterate over the rest + * of the children, too */ + if (child == NULL) + continue; + if (gtk_widget_grab_focus (child)) return TRUE; } |