[gtk/cherry-pick-0c052c9a] Merge branch 'gridview' into 'main'




commit 1ea2643aa93af085d8567a89a416fb341f7bb0e9
Author: Benjamin Otte <otte benjamin googlemail com>
Date:   Tue Jul 26 01:08:08 2022 +0000

    Merge branch 'gridview' into 'main'
    
    Gridview fix rubberbanding issues
    
    Closes #3462 and #3445
    
    See merge request GNOME/gtk!4688
    
    (cherry picked from commit 0c052c9a3704c315ebf09fff18aba3c019a55ab7)
    
    2bcae546 gridview: Move gtk_grid_view_computer_total_height() up for reuse
    c6f357e4 gridview: Limit rectangle to gridview columns
    1e9a36ff gridview: Allow starting rubberband in empty space below last row
    ba909cf9 gridview: Fix get_items_in_rect() selection
    f3fc8f5b gridview: Return an empty bitset when selecting only empty space
    57c032e6 listbase: Clear selection if rubberband selected an empty set
    aba2d994 gridview: Fix typo in docstring for gtk_grid_view_get_cell_at_y()
    e14b84ff listview: Return an empty bitset when selecting only empty space
    d6fab140 listview: Allow starting rubberband in empty space below last row
    a7bbc258 listview: Fix selection for last item in get_items_in_rect

 gtk/gtkgridview.c | 38 +++++++++++++++++++++-----------------
 gtk/gtklistbase.c | 35 +++++++++++++++++++----------------
 gtk/gtklistview.c |  7 ++++++-
 3 files changed, 46 insertions(+), 34 deletions(-)
---
diff --git a/gtk/gtkgridview.c b/gtk/gtkgridview.c
index 9b903dc5e0..fbd3a65327 100644
--- a/gtk/gtkgridview.c
+++ b/gtk/gtkgridview.c
@@ -204,7 +204,7 @@ cell_augment (GtkRbTree *tree,
  *   index of the returned row
  * @offset: (out caller-allocates) (optional): stores the offset
  *   in pixels between y and top of cell.
- * @offset: (out caller-allocates) (optional): stores the height
+ * @size: (out caller-allocates) (optional): stores the height
  *   of the cell
  *
  * Gets the Cell that occupies the leftmost position in the row at offset
@@ -413,6 +413,19 @@ gtk_grid_view_get_allocation_across (GtkListBase *base,
   return TRUE;
 }
 
+static int
+gtk_grid_view_compute_total_height (GtkGridView *self)
+{
+  Cell *cell;
+  CellAugment *aug;
+
+  cell = gtk_list_item_manager_get_root (self->item_manager);
+  if (cell == NULL)
+    return 0;
+  aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
+  return aug->size;
+}
+
 static gboolean
 gtk_grid_view_get_position_from_allocation (GtkListBase           *base,
                                             int                    across,
@@ -428,6 +441,7 @@ gtk_grid_view_get_position_from_allocation (GtkListBase           *base,
     return FALSE;
 
   n_items = gtk_list_base_get_n_items (base);
+  along = CLAMP (along, 0, gtk_grid_view_compute_total_height (self) - 1);
   if (!gtk_grid_view_get_cell_at_y (self,
                                     along,
                                     &pos,
@@ -467,16 +481,19 @@ gtk_grid_view_get_items_in_rect (GtkListBase        *base,
 
   result = gtk_bitset_new_empty ();
 
+  if (rect->y >= gtk_grid_view_compute_total_height (self))
+    return result;
+
   n_items = gtk_list_base_get_n_items (base);
   if (n_items == 0)
     return result;
 
-  first_column = floor (rect->x / self->column_width);
-  last_column = floor ((rect->x + rect->width) / self->column_width);
+  first_column = fmax (floor (rect->x / self->column_width), 0);
+  last_column = fmin (floor ((rect->x + rect->width) / self->column_width), self->n_columns - 1);
   if (!gtk_grid_view_get_cell_at_y (self, rect->y, &first_row, NULL, NULL))
     first_row = rect->y < 0 ? 0 : n_items - 1;
   if (!gtk_grid_view_get_cell_at_y (self, rect->y + rect->height, &last_row, NULL, NULL))
-    last_row = rect->y < 0 ? 0 : n_items - 1;
+    last_row = rect->y + rect->height < 0 ? 0 : n_items - 1;
 
   gtk_bitset_add_rectangle (result,
                             first_row + first_column,
@@ -722,19 +739,6 @@ cell_set_size (Cell  *cell,
   gtk_rb_tree_node_mark_dirty (cell);
 }
 
-static int
-gtk_grid_view_compute_total_height (GtkGridView *self)
-{
-  Cell *cell;
-  CellAugment *aug;
-
-  cell = gtk_list_item_manager_get_root (self->item_manager);
-  if (cell == NULL)
-    return 0;
-  aug = gtk_list_item_manager_get_item_augment (self->item_manager, cell);
-  return aug->size;
-}
-
 static void
 gtk_grid_view_size_allocate (GtkWidget *widget,
                              int        width,
diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c
index e4013df05c..67b839035f 100644
--- a/gtk/gtklistbase.c
+++ b/gtk/gtklistbase.c
@@ -1566,25 +1566,28 @@ gtk_list_base_stop_rubberband (GtkListBase *self,
         return;
 
       rubberband_selection = gtk_list_base_get_items_in_rect (self, &rect);
-      if (gtk_bitset_is_empty (rubberband_selection))
-        {
-          gtk_bitset_unref (rubberband_selection);
-          return;
-        }
 
       if (modify && extend) /* Ctrl + Shift */
         {
-          GtkBitset *current;
-          guint min = gtk_bitset_get_minimum (rubberband_selection);
-          guint max = gtk_bitset_get_maximum (rubberband_selection);
-          /* toggle the rubberband, keep the rest */
-          current = gtk_selection_model_get_selection_in_range (model, min, max - min + 1);
-          selected = gtk_bitset_copy (current);
-          gtk_bitset_unref (current);
-          gtk_bitset_intersect (selected, rubberband_selection);
-          gtk_bitset_difference (selected, rubberband_selection);
-
-          mask = gtk_bitset_ref (rubberband_selection);
+          if (gtk_bitset_is_empty (rubberband_selection))
+            {
+              selected = gtk_bitset_ref (rubberband_selection);
+              mask = gtk_bitset_ref (rubberband_selection);
+            }
+          else
+            {
+              GtkBitset *current;
+              guint min = gtk_bitset_get_minimum (rubberband_selection);
+              guint max = gtk_bitset_get_maximum (rubberband_selection);
+              /* toggle the rubberband, keep the rest */
+              current = gtk_selection_model_get_selection_in_range (model, min, max - min + 1);
+              selected = gtk_bitset_copy (current);
+              gtk_bitset_unref (current);
+              gtk_bitset_intersect (selected, rubberband_selection);
+              gtk_bitset_difference (selected, rubberband_selection);
+
+              mask = gtk_bitset_ref (rubberband_selection);
+            }
         }
       else if (modify) /* Ctrl */
         {
diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c
index e968f8437a..51c823cc13 100644
--- a/gtk/gtklistview.c
+++ b/gtk/gtklistview.c
@@ -377,6 +377,9 @@ gtk_list_view_get_items_in_rect (GtkListBase                 *base,
 
   result = gtk_bitset_new_empty ();
 
+  if (rect->y >= gtk_list_view_get_list_height (self))
+    return result;
+
   n_items = gtk_list_base_get_n_items (base);
   if (n_items == 0)
     return result;
@@ -390,7 +393,7 @@ gtk_list_view_get_items_in_rect (GtkListBase                 *base,
   if (row)
     last = gtk_list_item_manager_get_item_position (self->item_manager, row);
   else
-    last = rect->y < 0 ? 0 : n_items - 1;
+    last = rect->y + rect->height < 0 ? 0 : n_items - 1;
 
   gtk_bitset_add_range_closed (result, first, last);
   return result;
@@ -425,6 +428,8 @@ gtk_list_view_get_position_from_allocation (GtkListBase           *base,
   if (across >= self->list_width)
     return FALSE;
 
+  along = CLAMP (along, 0, gtk_list_view_get_list_height (self) - 1);
+
   row = gtk_list_view_get_row_at_y (self, along, &remaining);
   if (row == NULL)
     return FALSE;


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