listbase: Select focus before moving cursor
We have built-in keybindings for cursor arrow keys. They move the focus in the pointed direction and may also select the new focus child. However, some views allow selection but start with no item selected; such is the case of nautilus, and 'colors' in GTK Demo. In these views, pressing an arrow key to initiate the cursor actually moves it to the next position instead of the first position. At best, this means we need to take an a extra step to move the cursor into the first position. At worst, if there is only one child, the cursor arrow keys don't work at all and the only way to reach the child is with the Tab key or a pointer. Instead, let's select the focus item if unselected but selectable. This was the behavior of GtkTreeView in such cases, which can be tested in GTK Demo -> Tree View -> Tree Store. Fixes https://gitlab.gnome.org/GNOME/nautilus/-/issues/2618 and https://gitlab.gnome.org/GNOME/nautilus/-/issues/3078
This commit is contained in:
committed by
Peter Eisenmann
parent
c8aff694a8
commit
178ccd3b98
@@ -1142,6 +1142,34 @@ gtk_list_base_move_cursor_to_end (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_selecting_unselected_cursor (GtkListBase *self,
|
||||
guint position,
|
||||
gboolean select,
|
||||
gboolean modify,
|
||||
gboolean extend)
|
||||
{
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
GtkSelectionModel *model;
|
||||
|
||||
/* If Ctrl is pressed, we don't want to reset the selection. */
|
||||
if (!select || modify)
|
||||
return FALSE;
|
||||
|
||||
model = gtk_list_item_manager_get_model (priv->item_manager);
|
||||
|
||||
/* Selection of current position is not needed if it's already selected or if
|
||||
* there is nothing to select. */
|
||||
if (model == NULL || gtk_selection_model_is_selected (model, position))
|
||||
return FALSE;
|
||||
|
||||
/* Reset cursor to current position trying to select it as well. */
|
||||
activate_listitem_select_action (priv, position, FALSE, extend);
|
||||
|
||||
/* Report whether the model allowed the selection change. */
|
||||
return gtk_selection_model_is_selected (model, position);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_base_move_cursor (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
@@ -1156,6 +1184,12 @@ gtk_list_base_move_cursor (GtkWidget *widget,
|
||||
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
|
||||
|
||||
old_pos = gtk_list_base_get_focus_position (self);
|
||||
|
||||
/* When the focus is on an unselected item while we're selecting, we want to
|
||||
* not move focus but select the focused item instead if we can. */
|
||||
if (handle_selecting_unselected_cursor (self, old_pos, select, modify, extend))
|
||||
return TRUE;
|
||||
|
||||
new_pos = gtk_list_base_move_focus (self, old_pos, orientation, amount);
|
||||
|
||||
if (old_pos != new_pos)
|
||||
|
||||
Reference in New Issue
Block a user