summaryrefslogtreecommitdiff
path: root/gtk/gtkcolumnviewrowwidget.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-03-23 04:37:29 +0100
committerBenjamin Otte <otte@redhat.com>2023-03-23 04:51:50 +0100
commit30d4629043f54b6454cd1b4f5723179bc20a0b0e (patch)
treea0e865459eb5d0e96e33eba7bb87319b90e6b387 /gtk/gtkcolumnviewrowwidget.c
parent78e72ad1deacd152885c60205d620557138e5eaf (diff)
downloadgtk+-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.c74
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;
}