[gtk/wip/coreyberla/rubberband] listbase: Make sure items are in rubberband before adding




commit 8c9642a63e2bb5106f8a6d42d6b62b7c2ac6f705
Author: Corey Berla <corey berla me>
Date:   Mon Sep 19 10:22:45 2022 -0700

    listbase: Make sure items are in rubberband before adding
    
    The current implementation of get_items_in_rect uses the
    item's coordinates to decides whether an item is in the
    rubberband's rectangle or not.  This is usually fine,
    except if the widget is not the same size as the list item
    (i.e. if there are margins around the widget).  The widget is
    visible to the user (not the item), so let's make sure that
    the widget is really inside of the rubberband.
    
    Fixes: https://gitlab.gnome.org/GNOME/nautilus/-/issues/2436

 gtk/gtklistbase.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
---
diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c
index 86f408a562..d8eec2182e 100644
--- a/gtk/gtklistbase.c
+++ b/gtk/gtklistbase.c
@@ -1578,12 +1578,32 @@ gtk_list_base_stop_rubberband (GtkListBase *self,
       GtkBitset *selected, *mask;
       GdkRectangle rect;
       GtkBitset *rubberband_selection;
+      guint pos;
 
       if (!gtk_list_base_get_rubberband_coords (self, &rect))
         return;
 
       rubberband_selection = gtk_list_base_get_items_in_rect (self, &rect);
 
+      pos = 0;
+      for (item = gtk_list_item_manager_get_first (priv->item_manager);
+           item != NULL;
+           item = gtk_rb_tree_node_get_next (item))
+      {
+        if (item->widget)
+          {
+            GtkAllocation widget_allocation;
+            /* Make sure we are actually selecting the widget (i.e. if it has margins) */
+            gtk_widget_get_allocation (item->widget, &widget_allocation);
+
+            if (gtk_bitset_contains (rubberband_selection, pos) &&
+                !gdk_rectangle_intersect (&rect, &widget_allocation, NULL))
+              gtk_bitset_remove (rubberband_selection, pos);
+          }
+
+        pos += item->n_items;
+      }
+
       if (modify && extend) /* Ctrl + Shift */
         {
           if (gtk_bitset_is_empty (rubberband_selection))
@@ -1662,7 +1682,12 @@ gtk_list_base_update_rubberband_selection (GtkListBase *self)
     {
       if (item->widget)
         {
-          if (gtk_bitset_contains (rubberband_selection, pos))
+          GtkAllocation widget_allocation;
+          /* Make sure we are actually selecting the widget (i.e. if it has margins) */
+          gtk_widget_get_allocation (item->widget, &widget_allocation);
+
+          if (gtk_bitset_contains (rubberband_selection, pos) &&
+              gdk_rectangle_intersect (&rect, &widget_allocation, NULL))
             gtk_widget_set_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE, FALSE);
           else
             gtk_widget_unset_state_flags (item->widget, GTK_STATE_FLAG_ACTIVE);


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