diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index dc9fe60a08..83258b5de1 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -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)