Commit bed37db4 authored by António Fernandes's avatar António Fernandes 🐚
Browse files

listbase: Cancel rubberband if not handling drag

If the drag events are claimed by another gesture (e.g. a GtkDragSource
in an item widget), list base still commits a rubberband selection, for
a rubberband which wasn't even visible yet. This is a problem for the
GNOME Files application which needs both rubberbanding and drag-n-drop.

My previous fix[0] was enough for the case where the event sequence is
claimed right before the first GtkDragGesture::drag-update emission,
but it's useless if the event is claimed later (e.g. after the drag
treashold), because a rubberband already exists by that time.

Therefore, the complete solution requres checking whether the event
sequence is no longer being handled by our gesture, and commit the
selection changes only if it is, but otherwise cleanup the rubberband.

This is what GtkFlowBox does already, so let's do the same here.

[0] commit dc4540fa
parent 0660bb83
Pipeline #411297 passed with stages
in 13 minutes and 47 seconds
......@@ -1553,25 +1553,16 @@ gtk_list_base_start_rubberband (GtkListBase *self,
}
static void
gtk_list_base_stop_rubberband (GtkListBase *self,
gboolean modify,
gboolean extend)
gtk_list_base_apply_rubberband_selection (GtkListBase *self,
gboolean modify,
gboolean extend)
{
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
GtkListItemManagerItem *item;
GtkSelectionModel *model;
if (!priv->rubberband)
return;
for (item = gtk_list_item_manager_get_first (priv->item_manager);
item != NULL;
item = gtk_rb_tree_node_get_next (item))
{
if (item->widget)
gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);
}
model = gtk_list_item_manager_get_model (priv->item_manager);
if (model != NULL)
{
......@@ -1629,6 +1620,24 @@ gtk_list_base_stop_rubberband (GtkListBase *self,
gtk_bitset_unref (mask);
gtk_bitset_unref (rubberband_selection);
}
}
static void
gtk_list_base_stop_rubberband (GtkListBase *self)
{
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
GtkListItemManagerItem *item;
if (!priv->rubberband)
return;
for (item = gtk_list_item_manager_get_first (priv->item_manager);
item != NULL;
item = gtk_rb_tree_node_get_next (item))
{
if (item->widget)
gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);
}
gtk_list_item_tracker_free (priv->item_manager, priv->rubberband->start_tracker);
g_clear_pointer (&priv->rubberband->widget, gtk_widget_unparent);
......@@ -1740,15 +1749,18 @@ gtk_list_base_drag_end (GtkGestureDrag *gesture,
double offset_y,
GtkListBase *self)
{
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
GdkEventSequence *sequence;
gboolean modify, extend;
if (!priv->rubberband)
return;
sequence = gtk_gesture_get_last_updated_sequence (GTK_GESTURE (gesture));
if (gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
{
gtk_list_base_drag_update (gesture, offset_x, offset_y, self);
get_selection_modifiers (GTK_GESTURE (gesture), &modify, &extend);
gtk_list_base_apply_rubberband_selection (self, modify, extend);
}
gtk_list_base_drag_update (gesture, offset_x, offset_y, self);
get_selection_modifiers (GTK_GESTURE (gesture), &modify, &extend);
gtk_list_base_stop_rubberband (self, modify, extend);
gtk_list_base_stop_rubberband (self);
}
void
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment