[gtk/wip/antoniof/listbase-rubberband-better-fix] listbase: Cancel rubberband if not handling drag




commit bed37db4feff639992a471c0443133d28c88a35c
Author: António Fernandes <antoniof gnome org>
Date:   Fri Jun 24 09:05:29 2022 +0100

    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 dc4540fae98d4f707ce1030b0f8d161c987646e0

 gtk/gtklistbase.c | 48 ++++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c
index b5d0d35a7a..16f49da6c0 100644
--- a/gtk/gtklistbase.c
+++ b/gtk/gtklistbase.c
@@ -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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]