From b7f078f7399995dd1301b87dd6030685bfc0c0da Mon Sep 17 00:00:00 2001
From: Sergey Bugaev <bugaevc@gmail.com>
Date: Tue, 22 Oct 2024 13:27:21 +0300
Subject: [PATCH 1/3] layoutmanager: Skip invisible children when determining
 request mode

We don't generally care about hidden (or native) children when
performing layout, as is indeed suggested by the should_layout () method
name. Specifically for determining request mode, we'd like to return
constant size whenever we can, since this can result in very valueable
performance gains when measuring ancestor widgets. In case we have some
visible constant-size children and some hidden height-for-width ones,
we can still return constant-size.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 gtk/gtklayoutmanager.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c
index 6467b8ee5a..20e974b5ae 100644
--- a/gtk/gtklayoutmanager.c
+++ b/gtk/gtklayoutmanager.c
@@ -122,7 +122,12 @@ gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager,
        child != NULL;
        child = _gtk_widget_get_next_sibling (child))
     {
-      GtkSizeRequestMode res = gtk_widget_get_request_mode (child);
+      GtkSizeRequestMode res;
+
+      if (!gtk_widget_should_layout (child))
+        continue;
+
+      res = gtk_widget_get_request_mode (child);
 
       switch (res)
         {

From ed8c457c3a1db89b450380cfd860f1aede46c0f7 Mon Sep 17 00:00:00 2001
From: Sergey Bugaev <bugaevc@gmail.com>
Date: Thu, 19 Dec 2024 18:59:21 +0300
Subject: [PATCH 2/3] layoutmanager: With wfh == hfw, prefer hfw

We generally much prefer height-for-width over width-for-height, since
the former is typically better supported and faster, and the latter is
known to cause issues, most notably with wrappable labels. So when we
have two children with differing preferences and so have to make an
arbitrary choice between the two, prefer height-for-width.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 gtk/gtklayoutmanager.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c
index 20e974b5ae..47ced92b07 100644
--- a/gtk/gtklayoutmanager.c
+++ b/gtk/gtklayoutmanager.c
@@ -148,8 +148,8 @@ gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager,
  if (hfw == 0 && wfh == 0)
    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
 
- return hfw > wfh ? GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
-                  : GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
+ return hfw >= wfh ? GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH
+                   : GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
 }
 
 static void

From a71bb2165e2057ea51afd615b58f74bc067b62cf Mon Sep 17 00:00:00 2001
From: Sergey Bugaev <bugaevc@gmail.com>
Date: Tue, 26 Nov 2024 10:34:22 +0300
Subject: [PATCH 3/3] stack: Report constant-size in more cases

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 gtk/gtkstack.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index 001bb26d65..a19f9cea7b 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -2328,9 +2328,30 @@ gtk_stack_compute_expand (GtkWidget *widget,
 static GtkSizeRequestMode
 gtk_stack_get_request_mode (GtkWidget *widget)
 {
+  GtkStack *stack = GTK_STACK (widget);
+  GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
   GtkWidget *w;
   int wfh = 0, hfw = 0;
 
+  if (!priv->homogeneous[GTK_ORIENTATION_VERTICAL] &&
+      !priv->homogeneous[GTK_ORIENTATION_HORIZONTAL])
+    {
+      GtkSizeRequestMode lv_mode;
+
+      /* Only the visible child, and perhaps the last visible child
+       * during a transition, matter.  Attempt to return constant-size
+       * when we can.  */
+      if (priv->last_visible_child)
+        lv_mode = gtk_widget_get_request_mode (priv->last_visible_child->widget);
+      else
+        lv_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
+
+      if (lv_mode == GTK_SIZE_REQUEST_CONSTANT_SIZE && priv->visible_child)
+        return gtk_widget_get_request_mode (priv->visible_child->widget);
+      else
+        return lv_mode;
+    }
+
   for (w = gtk_widget_get_first_child (widget);
        w != NULL;
        w = gtk_widget_get_next_sibling (w))