From: Benjamin Otte Date: Wed, 1 Jun 2022 02:29:15 +0000 (+0200) Subject: listview: cull listitems that are out of view X-Git-Tag: archive/raspbian/4.8.3+ds-2+rpi1~3^2~20^2~4^2~139^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=39645d32582892bc4fd3bb55ea5d11af860f0efd;p=gtk4.git listview: cull listitems that are out of view Use set_child_visible(FALSE) on those widgets and don't allocate them. This should usually be the majority of items, so it's quite a worthwhile addition. Idea by Ivan Molodetskikh. Related: #3334 --- diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index bf0657a04f..81c95d1a4d 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -37,6 +37,13 @@ #include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" +/* Allow shadows to overdraw without immediately culling the widget at the viewport + * boundary. + * Choose this so that roughly 1 extra widget gets drawn on each side of the viewport, + * but not more. Icons are 16px, text height is somewhere there, too. + */ +#define GTK_LIST_BASE_CHILD_MAX_OVERDRAW 10 + typedef struct _RubberbandData RubberbandData; struct _RubberbandData @@ -1351,6 +1358,22 @@ gtk_list_base_size_allocate_child (GtkListBase *self, int height) { GtkAllocation child_allocation; + int self_width, self_height; + + self_width = gtk_widget_get_width (GTK_WIDGET (self)); + self_height = gtk_widget_get_height (GTK_WIDGET (self)); + + if (y + height + GTK_LIST_BASE_CHILD_MAX_OVERDRAW <= 0 || + y - GTK_LIST_BASE_CHILD_MAX_OVERDRAW >= self_height || + x + width + GTK_LIST_BASE_CHILD_MAX_OVERDRAW <= 0 || + x - GTK_LIST_BASE_CHILD_MAX_OVERDRAW >= self_width) + { + /* child is fully outside the viewport, hide it and don't allocate it */ + gtk_widget_set_child_visible (child, FALSE); + return; + } + + gtk_widget_set_child_visible (child, TRUE); if (gtk_list_base_get_orientation (GTK_LIST_BASE (self)) == GTK_ORIENTATION_VERTICAL) { @@ -1363,9 +1386,7 @@ gtk_list_base_size_allocate_child (GtkListBase *self, } else { - int mirror_point = gtk_widget_get_width (GTK_WIDGET (self)); - - child_allocation.x = mirror_point - x - width; + child_allocation.x = self_width - x - width; child_allocation.y = y; child_allocation.width = width; child_allocation.height = height; @@ -1382,9 +1403,7 @@ gtk_list_base_size_allocate_child (GtkListBase *self, } else { - int mirror_point = gtk_widget_get_width (GTK_WIDGET (self)); - - child_allocation.x = mirror_point - y - height; + child_allocation.x = self_width - y - height; child_allocation.y = x; child_allocation.width = height; child_allocation.height = width;