[gtk/wip/baedert/for-master] Revert "stack: Apply transitions in size-allocate"



commit 4d48fa08930dbe6e5c36a2b1b397fd880615f134
Author: Timm Bäder <mail baedert org>
Date:   Fri Jun 12 21:26:02 2020 +0200

    Revert "stack: Apply transitions in size-allocate"
    
    This reverts commit 952df968bfec0d0f59d21629cac722508dea0e51.

 gtk/gtkstack.c | 637 +++++++++++++++++++++++++++++++++------------------------
 1 file changed, 367 insertions(+), 270 deletions(-)
---
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index 5f88479bd6..303059643e 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -138,6 +138,8 @@ typedef struct {
   guint transition_duration;
 
   GtkStackPage *last_visible_child;
+  GskRenderNode *last_visible_node;
+  GtkAllocation last_visible_surface_allocation;
   guint tick_id;
   GtkProgressTracker tracker;
   gboolean first_frame_skipped;
@@ -643,6 +645,8 @@ gtk_stack_finalize (GObject *obj)
 
   gtk_stack_unschedule_ticks (stack);
 
+  g_clear_pointer (&priv->last_visible_node, gsk_render_node_unref);
+
   G_OBJECT_CLASS (gtk_stack_parent_class)->finalize (obj);
 }
 
@@ -855,8 +859,7 @@ static inline gboolean
 is_down_transition (GtkStackTransitionType transition_type)
 {
   return (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_DOWN);
+          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN);
 }
 
 /* Transitions that cause the bin window to move */
@@ -870,11 +873,7 @@ is_window_moving_transition (GtkStackTransitionType transition_type)
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP ||
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN ||
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_LEFT ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_UP ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_DOWN ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_LEFT ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT);
+          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT);
 }
 
 /* Transitions that change direction depending on the relative order of the
@@ -935,15 +934,44 @@ get_simple_transition_type (gboolean               new_child_first,
     }
 }
 
-static double
-get_transition_progress (GtkStack *stack)
+static gint
+get_bin_window_x (GtkStack *stack)
 {
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+  int width;
+  int x = 0;
 
-  if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
-    return 0;
+  width = gtk_widget_get_width (GTK_WIDGET (stack));
+
+  if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
+    {
+      if (is_left_transition (priv->active_transition_type))
+        x = width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      if (is_right_transition (priv->active_transition_type))
+        x = -width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+    }
+
+  return x;
+}
+
+static gint
+get_bin_window_y (GtkStack *stack)
+{
+  GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+  int height;
+  int y = 0;
+
+  height = gtk_widget_get_height (GTK_WIDGET (stack));
 
-  return gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
+  if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
+    {
+      if (is_up_transition (priv->active_transition_type))
+        y = height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      if (is_down_transition(priv->active_transition_type))
+        y = -height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+    }
+
+  return y;
 }
 
 static void
@@ -953,16 +981,20 @@ gtk_stack_progress_updated (GtkStack *stack)
 
   if (!priv->vhomogeneous || !priv->hhomogeneous)
     gtk_widget_queue_resize (GTK_WIDGET (stack));
-  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_CROSSFADE)
-    gtk_widget_queue_draw (GTK_WIDGET (stack));
-  else
+  else if (is_window_moving_transition (priv->active_transition_type))
     gtk_widget_queue_allocate (GTK_WIDGET (stack));
+  else
+    gtk_widget_queue_draw (GTK_WIDGET (stack));
 
-  if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER &&
-      priv->last_visible_child)
+  if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
     {
-      gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
-      priv->last_visible_child = NULL;
+      g_clear_pointer (&priv->last_visible_node, gsk_render_node_unref);
+
+      if (priv->last_visible_child != NULL)
+        {
+          gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
+          priv->last_visible_child = NULL;
+        }
     }
 }
 
@@ -1072,26 +1104,6 @@ effective_transition_type (GtkStack               *stack,
     }
 }
 
-static void
-gtk_stack_get_child_size (GtkStack  *stack,
-                          GtkWidget *child,
-                          int       *out_width,
-                          int       *out_height)
-{
-  GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
-  const int width = gtk_widget_get_width (GTK_WIDGET (stack));
-  const int height = gtk_widget_get_height (GTK_WIDGET (stack));
-  int min_width, min_height;
-
-  gtk_widget_measure (priv->visible_child->widget, GTK_ORIENTATION_HORIZONTAL,
-                      height, &min_width, NULL, NULL, NULL);
-  *out_width = MAX (width, min_width);
-
-  gtk_widget_measure (priv->visible_child->widget, GTK_ORIENTATION_VERTICAL,
-                      *out_width, &min_height, NULL, NULL, NULL);
-  *out_height = MAX (height, min_height);
-}
-
 static void
 gtk_stack_start_transition (GtkStack               *stack,
                             GtkStackTransitionType  transition_type,
@@ -1198,13 +1210,15 @@ set_visible_child (GtkStack               *stack,
     gtk_widget_set_child_visible (priv->last_visible_child->widget, FALSE);
   priv->last_visible_child = NULL;
 
+  g_clear_pointer (&priv->last_visible_node, gsk_render_node_unref);
+
   if (priv->visible_child && priv->visible_child->widget)
     {
       if (gtk_widget_is_visible (widget))
         {
           priv->last_visible_child = priv->visible_child;
-          priv->last_visible_widget_width = gtk_widget_get_width (widget);
-          priv->last_visible_widget_height = gtk_widget_get_height (widget);
+          priv->last_visible_widget_width = gtk_widget_get_allocated_width 
(priv->last_visible_child->widget);
+          priv->last_visible_widget_height = gtk_widget_get_allocated_height 
(priv->last_visible_child->widget);
         }
       else
         {
@@ -1695,7 +1709,6 @@ gtk_stack_set_transition_duration (GtkStack *stack,
     return;
 
   priv->transition_duration = duration;
-
   g_object_notify_by_pspec (G_OBJECT (stack),
                             stack_props[PROP_TRANSITION_DURATION]);
 }
@@ -2046,251 +2059,312 @@ gtk_stack_snapshot_crossfade (GtkWidget   *widget,
 {
   GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
-  const gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
+  gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
 
   gtk_snapshot_push_cross_fade (snapshot, progress);
-  gtk_widget_snapshot_child (widget, priv->last_visible_child->widget, snapshot);
+
+  if (priv->last_visible_node)
+    {
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                              priv->last_visible_surface_allocation.x,
+                              priv->last_visible_surface_allocation.y));
+      gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      gtk_snapshot_restore (snapshot);
+    }
   gtk_snapshot_pop (snapshot);
-  gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+
+  gtk_widget_snapshot_child (widget,
+                             priv->visible_child->widget,
+                             snapshot);
   gtk_snapshot_pop (snapshot);
 }
 
 static void
-gtk_stack_allocate_cube (GtkStack *stack)
+gtk_stack_snapshot_under (GtkWidget   *widget,
+                          GtkSnapshot *snapshot)
 {
+  GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
-  GtkWidget *widget = GTK_WIDGET (stack);
-  const int width = gtk_widget_get_width (widget);
-  const int height = gtk_widget_get_height (widget);
-  double progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
-  int last_widget_width, last_widget_height;
-  int visible_widget_width, visible_widget_height;
-  GskTransform *t;
+  int widget_width, widget_height;
+  gint x, y, width, height, pos_x, pos_y;
 
-  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT)
-    progress = 1 - progress;
 
-  gtk_stack_get_child_size (stack, priv->last_visible_child->widget,
-                            &last_widget_width, &last_widget_height);
+  x = y = 0;
+  width = widget_width = gtk_widget_get_width (widget);
+  height = widget_height = gtk_widget_get_height (widget);
 
-  gtk_stack_get_child_size (stack, priv->visible_child->widget,
-                            &visible_widget_width, &visible_widget_height);
+  pos_x = pos_y = 0;
 
-  if (progress > 0.5)
+  switch ((guint) priv->active_transition_type)
     {
-      t = gsk_transform_translate_3d (NULL, &GRAPHENE_POINT3D_INIT (width / 2.0f, height / 2.0f, 0));
-      t = gsk_transform_perspective (t, 2 * width / 1.0f);
-      t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (0, 0, - width / 2.0f));
-      t = gsk_transform_rotate_3d (t, -90.0f * progress, graphene_vec3_y_axis ());
-      t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (- width / 2.0f,
-                                                                 - height / 2.0f,
-                                                                 width / 2.0f));
-
-      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
-        gtk_widget_allocate (priv->last_visible_child->widget,
-                             last_widget_width, last_widget_height, -1, t);
-      else
-        gtk_widget_allocate (priv->visible_child->widget,
-                             visible_widget_width, visible_widget_height, -1, t);
+    case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
+      y = 0;
+      height = widget_height * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      pos_y = height;
+      break;
+    case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
+      y = widget_height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      height = widget_height - y;
+      pos_y = y - widget_height;
+      break;
+    case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
+      x = widget_width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      width = widget_width - x;
+      pos_x = x - widget_width;
+      break;
+    case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
+      x = 0;
+      width = widget_width * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
+      pos_x = width;
+      break;
+    default:
+      g_assert_not_reached ();
     }
 
-  t = gsk_transform_translate_3d (NULL, &GRAPHENE_POINT3D_INIT (width / 2.0f, height / 2.0f, 0));
-  t = gsk_transform_perspective (t, 2 * width / 1.0f);
-  t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (0, 0, -width / 2.0f));
-  t = gsk_transform_rotate_3d (t, 90 * (1.0 - progress), graphene_vec3_y_axis ());
-  t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (- width / 2.0f, - height / 2.0f, width / 2.0f));
+  gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT(x, y, width, height));
 
-  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
-    gtk_widget_allocate (priv->visible_child->widget,
-                         visible_widget_width, visible_widget_height, -1, t);
-  else
-    gtk_widget_allocate (priv->last_visible_child->widget,
-                         last_widget_width, last_widget_height, -1, t);
+  gtk_widget_snapshot_child (widget,
+                             priv->visible_child->widget,
+                             snapshot);
 
-  if (progress <= 0.5)
+  gtk_snapshot_pop (snapshot);
+
+  if (priv->last_visible_node)
     {
-      t = gsk_transform_translate_3d (NULL, &GRAPHENE_POINT3D_INIT (width / 2.0f, height / 2.0f, 0));
-      t = gsk_transform_perspective (t, 2 * width / 1.0f);
-      t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (0, 0, - width / 2.0f));
-      t = gsk_transform_rotate_3d (t, -90 * progress, graphene_vec3_y_axis ());
-      t = gsk_transform_translate_3d (t, &GRAPHENE_POINT3D_INIT (- width / 2.0f, - height / 2.0, width / 
2.0f));
-      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
-        gtk_widget_allocate (priv->last_visible_child->widget,
-                             last_widget_width, last_widget_height, -1, t);
-      else
-        gtk_widget_allocate (priv->visible_child->widget,
-                             visible_widget_width, visible_widget_height, -1, t);
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (pos_x, pos_y));
+      gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      gtk_snapshot_restore (snapshot);
     }
 }
 
 static void
-gtk_stack_allocate_slide (GtkStack *stack)
+gtk_stack_snapshot_cube (GtkWidget   *widget,
+                         GtkSnapshot *snapshot)
 {
+  GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
-  GtkWidget *widget = GTK_WIDGET (stack);
-  const int width = gtk_widget_get_width (widget);
-  const int height = gtk_widget_get_height (widget);
-  const double progress = get_transition_progress (stack);
-  int new_x, new_y;
-  int old_x, old_y;
-  GtkAllocation child_allocation;
+  double progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
 
-  switch ((guint) priv->active_transition_type)
+  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT)
+    progress = 1 - progress;
+
+  if (priv->last_visible_node && progress > 0.5)
     {
-    case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
-      old_x = - width * progress;
-      old_y = 0;
-      new_x = width - (width * progress);
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
-      old_x = width * progress;
-      old_y = 0;
-      new_x = - width + (width * progress);
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_OVER_LEFT:
-      old_x = 0;
-      old_y = 0;
-      new_x = width - (width * progress);
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_SLIDE_UP:
-      old_x = 0;
-      old_y = - height * progress;
-      new_x = 0;
-      new_y = height - (height * progress);
-      break;
-    case GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN:
-      old_x = 0;
-      old_y = height * progress;
-      new_x = 0;
-      new_y = - height + (height * progress);
-      break;
-    case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
-      new_x = 0;
-      new_y = 0;
-      old_x = 0;
-      old_y = - height * progress;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
-      old_x = 0;
-      old_y = progress * height;
-      new_x = 0;
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_OVER_DOWN:
-      old_x = 0;
-      old_y = 0;
-      new_x = 0;
-      new_y = - height + (height * progress);
-      break;
-    case GTK_STACK_TRANSITION_TYPE_OVER_UP:
-      old_x = 0;
-      old_y = 0;
-      new_x = 0;
-      new_y = height - (height * progress);
-      break;
-    case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
-      old_x = width * progress;
-      old_y = 0;
-      new_x = 0;
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
-      old_x = 0;
-      old_y = 0;
-      new_x = - width + (width * progress);
-      new_y = 0;
-      break;
-    case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
-      new_x = 0;
-      new_y = 0;
-      old_x = - width * progress;
-      old_y = 0;
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 gtk_widget_get_width (widget) / 2.f,
+                                 gtk_widget_get_height (widget) / 2.f,
+                                 0));
+      gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 0, 0,
+                                 - gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_rotate_3d (snapshot, -90 * progress, graphene_vec3_y_axis());
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 - gtk_widget_get_width (widget) / 2.f,
+                                 - gtk_widget_get_height (widget) / 2.f,
+                                 gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                              priv->last_visible_surface_allocation.x,
+                              priv->last_visible_surface_allocation.y));
+      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+        gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      else
+        gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+      gtk_snapshot_restore (snapshot);
     }
 
-  gtk_stack_get_child_size (stack, priv->visible_child->widget,
-                            &child_allocation.width, &child_allocation.height);
-  child_allocation.x = new_x;
-  child_allocation.y = new_y;
-  gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation, -1);
+  gtk_snapshot_save (snapshot);
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             gtk_widget_get_width (widget) / 2.f,
+                             gtk_widget_get_height (widget) / 2.f,
+                             0));
+  gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             0, 0,
+                             - gtk_widget_get_width (widget) / 2.f));
+  gtk_snapshot_rotate_3d (snapshot, 90 * (1.0 - progress), graphene_vec3_y_axis());
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             - gtk_widget_get_width (widget) / 2.f,
+                             - gtk_widget_get_height (widget) / 2.f,
+                             gtk_widget_get_width (widget) / 2.f));
+  gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                          priv->last_visible_surface_allocation.x,
+                          priv->last_visible_surface_allocation.y));
 
-  gtk_stack_get_child_size (stack, priv->last_visible_child->widget,
-                            &child_allocation.width, &child_allocation.height);
-  child_allocation.x = old_x;
-  child_allocation.y = old_y;
-  gtk_widget_size_allocate (priv->last_visible_child->widget, &child_allocation, -1);
+  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+    gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+  else
+    gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+  gtk_snapshot_restore (snapshot);
+
+  if (priv->last_visible_node && progress <= 0.5)
+    {
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 gtk_widget_get_width (widget) / 2.f,
+                                 gtk_widget_get_height (widget) / 2.f,
+                                 0));
+      gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 0, 0,
+                                 - gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_rotate_3d (snapshot, -90 * progress, graphene_vec3_y_axis());
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 - gtk_widget_get_width (widget) / 2.f,
+                                 - gtk_widget_get_height (widget) / 2.f,
+                                 gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                              priv->last_visible_surface_allocation.x,
+                              priv->last_visible_surface_allocation.y));
+      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+        gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      else
+        gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+      gtk_snapshot_restore (snapshot);
+    }
 }
 
 static void
-gtk_stack_snapshot (GtkWidget   *widget,
-                    GtkSnapshot *snapshot)
+gtk_stack_snapshot_slide (GtkWidget   *widget,
+                          GtkSnapshot *snapshot)
 {
   GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
 
-  if (!priv->visible_child)
-    return;
-
-  if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER &&
-      priv->last_visible_child)
+  if (priv->last_visible_node)
     {
-      gtk_snapshot_push_clip (snapshot,
-                              &GRAPHENE_RECT_INIT(
-                                  0, 0,
-                                  gtk_widget_get_width (widget),
-                                  gtk_widget_get_height (widget)
-                              ));
-
-      switch (priv->active_transition_type)
+      int x, y;
+      int width, height;
+
+      width = gtk_widget_get_width (widget);
+      height = gtk_widget_get_height (widget);
+
+      x = get_bin_window_x (stack);
+      y = get_bin_window_y (stack);
+
+      switch ((guint) priv->active_transition_type)
         {
-        case GTK_STACK_TRANSITION_TYPE_CROSSFADE:
-          gtk_stack_snapshot_crossfade (widget, snapshot);
-          break;
         case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
+          x -= width;
+          break;
         case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
+          x += width;
+          break;
         case GTK_STACK_TRANSITION_TYPE_SLIDE_UP:
+          y -= height;
+          break;
         case GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN:
+          y += height;
+          break;
         case GTK_STACK_TRANSITION_TYPE_OVER_UP:
-        case GTK_STACK_TRANSITION_TYPE_OVER_LEFT:
-        case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
         case GTK_STACK_TRANSITION_TYPE_OVER_DOWN:
-        case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT:
-        case GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT:
-        case GTK_STACK_TRANSITION_TYPE_NONE:
-        case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT:
-        case GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN:
-        case GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN:
-        case GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP:
-        case GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT:
-        case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT:
-        case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT:
-          gtk_widget_snapshot_child (widget, priv->last_visible_child->widget, snapshot);
-          gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+          y = 0;
           break;
-        case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
-        case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
-        case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
-        case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
-          gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
-          gtk_widget_snapshot_child (widget, priv->last_visible_child->widget, snapshot);
+        case GTK_STACK_TRANSITION_TYPE_OVER_LEFT:
+        case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
+          x = 0;
           break;
         default:
           g_assert_not_reached ();
+          break;
         }
 
-      gtk_snapshot_pop (snapshot);
-    }
-  else
+      if (priv->last_visible_child != NULL)
+        {
+          if (gtk_widget_get_valign (priv->last_visible_child->widget) == GTK_ALIGN_END &&
+              priv->last_visible_widget_height > height)
+            y -= priv->last_visible_widget_height - height;
+          else if (gtk_widget_get_valign (priv->last_visible_child->widget) == GTK_ALIGN_CENTER)
+            y -= (priv->last_visible_widget_height - height) / 2;
+        }
+
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
+      gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      gtk_snapshot_restore (snapshot);
+     }
+
+  gtk_widget_snapshot_child (widget,
+                             priv->visible_child->widget,
+                             snapshot);
+}
+
+static void
+gtk_stack_snapshot (GtkWidget   *widget,
+                    GtkSnapshot *snapshot)
+{
+  GtkStack *stack = GTK_STACK (widget);
+  GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+
+  if (priv->visible_child)
     {
-      gtk_widget_snapshot_child (widget,
-                                 priv->visible_child->widget,
-                                 snapshot);
+      if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
+        {
+          if (priv->last_visible_node == NULL &&
+              priv->last_visible_child != NULL)
+            {
+              GtkSnapshot *last_visible_snapshot;
+
+              gtk_widget_get_allocation (priv->last_visible_child->widget,
+                                         &priv->last_visible_surface_allocation);
+              last_visible_snapshot = gtk_snapshot_new ();
+              gtk_widget_snapshot (priv->last_visible_child->widget, last_visible_snapshot);
+              priv->last_visible_node = gtk_snapshot_free_to_node (last_visible_snapshot);
+            }
+
+          gtk_snapshot_push_clip (snapshot,
+                                  &GRAPHENE_RECT_INIT(
+                                      0, 0,
+                                      gtk_widget_get_width (widget),
+                                      gtk_widget_get_height (widget)
+                                  ));
+
+          switch (priv->active_transition_type)
+            {
+            case GTK_STACK_TRANSITION_TYPE_CROSSFADE:
+             gtk_stack_snapshot_crossfade (widget, snapshot);
+              break;
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_UP:
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN:
+            case GTK_STACK_TRANSITION_TYPE_OVER_UP:
+            case GTK_STACK_TRANSITION_TYPE_OVER_DOWN:
+            case GTK_STACK_TRANSITION_TYPE_OVER_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
+              gtk_stack_snapshot_slide (widget, snapshot);
+              break;
+            case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
+            case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
+            case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
+             gtk_stack_snapshot_under (widget, snapshot);
+              break;
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT:
+             gtk_stack_snapshot_cube (widget, snapshot);
+              break;
+            case GTK_STACK_TRANSITION_TYPE_NONE:
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT:
+            case GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN:
+            case GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN:
+            case GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP:
+            case GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT:
+            case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT:
+            default:
+              g_assert_not_reached ();
+            }
+
+          gtk_snapshot_pop (snapshot);
+        }
+      else
+        gtk_widget_snapshot_child (widget,
+                                   priv->visible_child->widget,
+                                   snapshot);
     }
 }
 
@@ -2302,51 +2376,71 @@ gtk_stack_size_allocate (GtkWidget *widget,
 {
   GtkStack *stack = GTK_STACK (widget);
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+  GtkAllocation child_allocation;
 
-  if (!priv->visible_child)
-    return;
+  child_allocation.x = get_bin_window_x (stack);
+  child_allocation.y = get_bin_window_y (stack);
 
-  if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER &&
-      priv->last_visible_child)
+  if (priv->last_visible_child)
     {
-      int min_width;
-      int min_height;
+      int min, nat;
 
-      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_CROSSFADE)
-        {
-          /* Last visible child */
-          gtk_stack_get_child_size (stack, priv->last_visible_child->widget, &min_width, &min_height);
-          gtk_widget_allocate (priv->last_visible_child->widget, min_width, min_height, -1, NULL);
+      gtk_widget_measure (priv->last_visible_child->widget, GTK_ORIENTATION_HORIZONTAL,
+                          -1,
+                          &min, &nat, NULL, NULL);
+      child_allocation.width = MAX (min, width);
+      gtk_widget_measure (priv->last_visible_child->widget, GTK_ORIENTATION_VERTICAL,
+                          child_allocation.width,
+                          &min, &nat, NULL, NULL);
+      child_allocation.height = MAX (min, height);
 
-          /* visible child */
-          gtk_stack_get_child_size (stack, priv->visible_child->widget, &min_width, &min_height);
-          gtk_widget_allocate (priv->visible_child->widget, min_width, min_height, -1, NULL);
-        }
-      else if (is_window_moving_transition (priv->active_transition_type))
-        {
-          gtk_stack_allocate_slide (stack);
-        }
-      else if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT ||
-               priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT ||
-               priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT)
+      gtk_widget_size_allocate (priv->last_visible_child->widget, &child_allocation, -1);
+
+      if (!gdk_rectangle_equal (&priv->last_visible_surface_allocation,
+                                &child_allocation))
         {
-          gtk_stack_allocate_cube (stack);
+          g_clear_pointer (&priv->last_visible_node, gsk_render_node_unref);
         }
-      else
-        {
-          g_assert_not_reached ();
-        }
-
     }
-  else
+
+  child_allocation.width = width;
+  child_allocation.height = height;
+
+  if (priv->visible_child)
     {
       int min_width;
       int min_height;
 
-      gtk_stack_get_child_size (stack, priv->visible_child->widget, &min_width, &min_height);
-      gtk_widget_allocate (priv->visible_child->widget, min_width, min_height, -1, NULL);
-    }
+      gtk_widget_measure (priv->visible_child->widget, GTK_ORIENTATION_HORIZONTAL,
+                          height, &min_width, NULL, NULL, NULL);
+      child_allocation.width = MAX (child_allocation.width, min_width);
+
+      gtk_widget_measure (priv->visible_child->widget, GTK_ORIENTATION_VERTICAL,
+                          child_allocation.width, &min_height, NULL, NULL, NULL);
+      child_allocation.height = MAX (child_allocation.height, min_height);
+
+      if (child_allocation.width > width)
+        {
+          GtkAlign halign = gtk_widget_get_halign (priv->visible_child->widget);
+
+          if (halign == GTK_ALIGN_CENTER || halign == GTK_ALIGN_FILL)
+            child_allocation.x = (width - child_allocation.width) / 2;
+          else if (halign == GTK_ALIGN_END)
+            child_allocation.x = (width - child_allocation.width);
+        }
 
+      if (child_allocation.height > height)
+        {
+          GtkAlign valign = gtk_widget_get_valign (priv->visible_child->widget);
+
+          if (valign == GTK_ALIGN_CENTER || valign == GTK_ALIGN_FILL)
+            child_allocation.y = (height - child_allocation.height) / 2;
+          else if (valign == GTK_ALIGN_END)
+            child_allocation.y = (height - child_allocation.height);
+        }
+
+      gtk_widget_size_allocate (priv->visible_child->widget, &child_allocation, -1);
+    }
 }
 
 #define LERP(a, b, t) ((a) + (((b) - (a)) * (1.0 - (t))))
@@ -2363,9 +2457,12 @@ gtk_stack_measure (GtkWidget      *widget,
   GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
   GtkStackPage *child_info;
   GtkWidget *child;
-  int child_min, child_nat;
+  gint child_min, child_nat;
   GList *l;
 
+  *minimum = 0;
+  *natural = 0;
+
   for (l = priv->children; l != NULL; l = l->next)
     {
       child_info = l->data;
@@ -2389,13 +2486,13 @@ gtk_stack_measure (GtkWidget      *widget,
     {
       if (orientation == GTK_ORIENTATION_VERTICAL && !priv->vhomogeneous)
         {
-          double t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, 
FALSE) : 1.0;
+          gdouble t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, 
FALSE) : 1.0;
           *minimum = LERP (*minimum, priv->last_visible_widget_height, t);
           *natural = LERP (*natural, priv->last_visible_widget_height, t);
         }
       if (orientation == GTK_ORIENTATION_HORIZONTAL && !priv->hhomogeneous)
         {
-          double t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, 
FALSE) : 1.0;
+          gdouble t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, 
FALSE) : 1.0;
           *minimum = LERP (*minimum, priv->last_visible_widget_width, t);
           *natural = LERP (*natural, priv->last_visible_widget_width, t);
         }


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