[libadwaita/wip/exalm/spring-animation-swipes: 1/3] Add spring animations




commit 3dd88d0423b60610771d8da258cefb1d57ced95b
Author: Manuel Genovés <manuel genoves gmail com>
Date:   Wed Dec 1 00:56:54 2021 +0100

    Add spring animations

 src/adw-spring-animation.c | 501 +++++++++++++++++++++++++++++++++++++++++++++
 src/adw-spring-animation.h |  67 ++++++
 src/adw-spring-params.c    | 111 ++++++++++
 src/adw-spring-params.h    |  47 +++++
 src/adwaita.h              |   2 +
 src/meson.build            |   4 +
 6 files changed, 732 insertions(+)
---
diff --git a/src/adw-spring-animation.c b/src/adw-spring-animation.c
new file mode 100644
index 00000000..041441e0
--- /dev/null
+++ b/src/adw-spring-animation.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "adw-spring-animation.h"
+#include "adw-spring-params.h"
+
+#include "adw-animation-private.h"
+#include "adw-animation-util.h"
+
+#define DELTA 0.001
+
+struct _AdwSpringAnimation
+{
+  AdwAnimation parent_instance;
+
+  double value_from;
+  double value_to;
+
+  AdwSpringParams *spring_params;
+
+  double initial_velocity;
+  double epsilon;
+
+  guint estimated_duration; /*ms*/
+};
+
+struct _AdwSpringAnimationClass
+{
+  AdwAnimationClass parent_class;
+};
+
+G_DEFINE_TYPE (AdwSpringAnimation, adw_spring_animation, ADW_TYPE_ANIMATION)
+
+enum {
+  PROP_0,
+  PROP_VALUE_FROM,
+  PROP_VALUE_TO,
+  PROP_SPRING_PARAMS,
+  PROP_INITIAL_VELOCITY,
+  PROP_EPSILON,
+  PROP_ESTIMATED_DURATION,
+  LAST_PROP,
+};
+
+static GParamSpec *props[LAST_PROP];
+
+/* Based on RBBSpringAnimation from RBBAnimation, MIT license.
+ * https://github.com/robb/RBBAnimation/blob/master/RBBAnimation/RBBSpringAnimation.m
+ */
+static double
+oscillate (AdwAnimation *animation,
+           guint         time)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
+
+  double b = adw_spring_params_get_damping (self->spring_params);
+  double m = adw_spring_params_get_mass (self->spring_params);
+  double k = adw_spring_params_get_stiffness (self->spring_params);
+  double v0 = self->initial_velocity;
+
+  double t = time / 1000.0;
+
+  double beta = b / (2 * m);
+  double omega0 = sqrt (k / m);
+
+  double x0 = -1;
+
+  double envelope = exp (-beta * t);
+
+  /*
+   * Solutions of the form C1*e^(lambda1*x) + C2*e^(lambda2*x)
+   * for the differential equation m*ẍ+b*ẋ+kx = 0
+   */
+
+  /* Underdamped */
+  if (beta < omega0) {
+    double omega1 = sqrt ((omega0 * omega0) - (beta * beta));
+
+    return -x0 + envelope * (x0 * cos (omega1 * t) + ((beta * x0 + v0) / omega1) * sin (omega1 * t));
+  }
+
+  /* Overdamped */
+  if (beta > omega0) {
+    double omega2 = sqrt ((beta * beta) - (omega0 * omega0));
+
+    return -x0 + envelope * (x0 * cosh (omega2 * t) + ((beta * x0 + v0) / omega2) * sinh (omega2 * t));
+  }
+
+  /* Critically damped */
+  return -x0 + envelope * (x0 + (beta * x0 + v0) * t);
+}
+
+static guint
+adw_spring_animation_estimate_duration (AdwAnimation *animation)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
+
+  double damping = adw_spring_params_get_damping (self->spring_params);
+  double mass = adw_spring_params_get_mass (self->spring_params);
+  double stiffness = adw_spring_params_get_stiffness (self->spring_params);
+
+  double beta = damping / (2 * mass);
+  double omega0;
+  double x0, y0;
+  double x1, y1;
+  double m;
+
+  if (beta <= 0)
+    return ADW_DURATION_INFINITE;
+
+  omega0 = sqrt (stiffness / mass);
+
+  /*
+   * As first ansatz for the overdamped solution,
+   * and general estimation for the oscillating ones
+   * we take the value of the envelope when it's < epsilon
+   */
+  x0 = -log (self->epsilon) / beta;
+
+  if (beta <= omega0)
+    return x0 * 1000;
+
+  /*
+   * Since the overdamped solution decays way slower than the envelope
+   * we need to use the value of the oscillation itself.
+   * Newton's root finding method is a good candidate in this particular case:
+   * https://en.wikipedia.org/wiki/Newton%27s_method
+   */
+  y0 = oscillate (animation, x0);
+  m = (oscillate (animation, x0 + DELTA) - y0) / DELTA;
+
+  x1 = (1 - y0 + m * x0) / m;
+  y1 = oscillate (animation, x1);
+
+  while (ABS (1 - y1) > self->epsilon) {
+    x0 = x1;
+    y0 = y1;
+
+    m = (oscillate (animation, x0 + DELTA) - y0) / DELTA;
+
+    x1 = (1 - y0 + m * x0) / m;
+    y1 = oscillate (animation, x1);
+  }
+
+  return x1 * 1000;
+}
+
+static void
+set_estimated_duration (AdwSpringAnimation *self)
+{
+  if (!self->spring_params)
+    return;
+
+  self->estimated_duration = adw_spring_animation_estimate_duration (ADW_ANIMATION (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ESTIMATED_DURATION]);
+}
+
+static double
+adw_spring_animation_calculate_value (AdwAnimation *animation,
+                                      guint         t)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (animation);
+
+  if (t >= self->estimated_duration)
+    return self->value_to;
+
+  return adw_lerp (self->value_from, self->value_to, oscillate (animation, t));
+}
+
+static void
+adw_spring_animation_constructed (GObject *object)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (object);
+
+  G_OBJECT_CLASS (adw_spring_animation_parent_class)->constructed (object);
+
+  set_estimated_duration (self);
+}
+
+static void
+adw_spring_animation_dispose (GObject *object)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (object);
+
+  adw_spring_params_unref (self->spring_params);
+
+  G_OBJECT_CLASS (adw_spring_animation_parent_class)->dispose (object);
+}
+
+static void
+adw_spring_animation_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (object);
+
+  switch (prop_id) {
+  case PROP_VALUE_FROM:
+    g_value_set_double (value, adw_spring_animation_get_value_from (self));
+    break;
+
+  case PROP_VALUE_TO:
+    g_value_set_double (value, adw_spring_animation_get_value_to (self));
+    break;
+
+  case PROP_SPRING_PARAMS:
+    g_value_set_boxed (value, adw_spring_animation_get_spring_params (self));
+    break;
+
+  case PROP_INITIAL_VELOCITY:
+    g_value_set_double (value, adw_spring_animation_get_initial_velocity (self));
+    break;
+
+  case PROP_EPSILON:
+    g_value_set_double (value, adw_spring_animation_get_epsilon (self));
+    break;
+
+  case PROP_ESTIMATED_DURATION:
+    g_value_set_uint (value, adw_spring_animation_get_estimated_duration (self));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_spring_animation_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  AdwSpringAnimation *self = ADW_SPRING_ANIMATION (object);
+
+  switch (prop_id) {
+  case PROP_VALUE_FROM:
+    adw_spring_animation_set_value_from (self, g_value_get_double (value));
+    break;
+
+  case PROP_VALUE_TO:
+    adw_spring_animation_set_value_to (self, g_value_get_double (value));
+    break;
+
+  case PROP_SPRING_PARAMS:
+    adw_spring_animation_set_spring_params (self, g_value_get_boxed (value));
+    break;
+
+  case PROP_INITIAL_VELOCITY:
+    adw_spring_animation_set_initial_velocity (self, g_value_get_double (value));
+    break;
+
+  case PROP_EPSILON:
+    adw_spring_animation_set_epsilon (self, g_value_get_double (value));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+adw_spring_animation_class_init (AdwSpringAnimationClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  AdwAnimationClass *animation_class = ADW_ANIMATION_CLASS (klass);
+
+  object_class->constructed = adw_spring_animation_constructed;
+  object_class->dispose = adw_spring_animation_dispose;
+  object_class->set_property = adw_spring_animation_set_property;
+  object_class->get_property = adw_spring_animation_get_property;
+
+  animation_class->estimate_duration = adw_spring_animation_estimate_duration;
+  animation_class->calculate_value = adw_spring_animation_calculate_value;
+
+  props[PROP_VALUE_FROM] =
+    g_param_spec_double ("value-from",
+                         "Initial value",
+                         "The value to animate from",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_VALUE_TO] =
+    g_param_spec_double ("value-to",
+                         "Final value",
+                         "The value to animate to",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_SPRING_PARAMS] =
+    g_param_spec_boxed ("spring-params",
+                        "Spring parameters",
+                        "Physical parameters describing the spring",
+                        ADW_TYPE_SPRING_PARAMS,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_INITIAL_VELOCITY] =
+    g_param_spec_double ("initial-velocity",
+                         "Initial velocity",
+                         "The initial velocity to start te animation with",
+                         -G_MAXDOUBLE,
+                         G_MAXDOUBLE,
+                         0,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_EPSILON] =
+    g_param_spec_double ("epsilon",
+                         "Epsilon",
+                         "Precision of the spring",
+                         0,
+                         G_MAXDOUBLE,
+                         0.001,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+
+  props[PROP_ESTIMATED_DURATION] =
+    g_param_spec_uint ("estimated-duration",
+                       "Estimated duration",
+                       "Estimated duration of the animation in milliseconds",
+                       0,
+                       ADW_DURATION_INFINITE,
+                       0,
+                       G_PARAM_READABLE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+adw_spring_animation_init (AdwSpringAnimation *self)
+{
+}
+
+AdwAnimation *
+adw_spring_animation_new (GtkWidget          *widget,
+                         double              from,
+                         double              to,
+                         AdwSpringParams    *spring_params,
+                         AdwAnimationTarget *target)
+{
+  AdwAnimation *animation;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+  g_return_val_if_fail (spring_params != NULL, NULL);
+  g_return_val_if_fail (ADW_IS_ANIMATION_TARGET (target), NULL);
+
+  animation = g_object_new (ADW_TYPE_SPRING_ANIMATION,
+                            "widget", widget,
+                            "value-from", from,
+                            "value-to", to,
+                            "spring-params", spring_params,
+                            "target", target,
+                            NULL);
+  g_object_unref (target);
+  adw_spring_params_unref (spring_params);
+
+  return animation;
+}
+
+double
+adw_spring_animation_get_value_from (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0.0);
+
+  return self->value_from;
+}
+
+void
+adw_spring_animation_set_value_from (AdwSpringAnimation *self,
+                                     double             value)
+{
+  g_return_if_fail (ADW_IS_SPRING_ANIMATION (self));
+
+  if (self->value_from == value)
+    return;
+
+  self->value_from = value;
+
+  set_estimated_duration (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_FROM]);
+}
+
+double
+adw_spring_animation_get_value_to (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0.0);
+
+  return self->value_to;
+}
+
+void
+adw_spring_animation_set_value_to (AdwSpringAnimation *self,
+                                   double             value)
+{
+  g_return_if_fail (ADW_IS_SPRING_ANIMATION (self));
+
+  if (self->value_to == value)
+    return;
+
+  self->value_to = value;
+
+  set_estimated_duration (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VALUE_TO]);
+}
+
+AdwSpringParams *
+adw_spring_animation_get_spring_params (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), NULL);
+
+  return self->spring_params;
+}
+
+void
+adw_spring_animation_set_spring_params (AdwSpringAnimation *self,
+                                        AdwSpringParams    *spring_params)
+{
+  g_return_if_fail (ADW_IS_SPRING_ANIMATION (self));
+  g_return_if_fail (spring_params != NULL);
+
+  if (self->spring_params == spring_params)
+    return;
+
+  if (self->spring_params != NULL)
+    adw_spring_params_unref (self->spring_params);
+
+  self->spring_params = spring_params;
+
+  adw_spring_params_ref (self->spring_params);
+
+  set_estimated_duration (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SPRING_PARAMS]);
+}
+
+double
+adw_spring_animation_get_initial_velocity (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0.0);
+
+  return self->initial_velocity;
+}
+
+void
+adw_spring_animation_set_initial_velocity (AdwSpringAnimation *self,
+                                           double              value)
+{
+  g_return_if_fail (ADW_IS_SPRING_ANIMATION (self));
+
+  if (self->initial_velocity == value)
+    return;
+
+  self->initial_velocity = value;
+
+  set_estimated_duration (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_INITIAL_VELOCITY]);
+}
+
+double
+adw_spring_animation_get_epsilon (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0.0);
+
+  return self->epsilon;
+}
+
+void
+adw_spring_animation_set_epsilon (AdwSpringAnimation *self,
+                                  double              value)
+{
+  g_return_if_fail (ADW_IS_SPRING_ANIMATION (self));
+  g_return_if_fail (value > 0.0);
+
+  if (self->epsilon == value)
+    return;
+
+  self->epsilon = value;
+
+  set_estimated_duration (self);
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_EPSILON]);
+}
+
+guint
+adw_spring_animation_get_estimated_duration (AdwSpringAnimation *self)
+{
+  g_return_val_if_fail (ADW_IS_SPRING_ANIMATION (self), 0);
+
+  return self->estimated_duration;
+}
diff --git a/src/adw-spring-animation.h b/src/adw-spring-animation.h
new file mode 100644
index 00000000..ceff798b
--- /dev/null
+++ b/src/adw-spring-animation.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-version.h"
+
+#include <gtk/gtk.h>
+
+#include "adw-animation.h"
+#include "adw-spring-params.h"
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_SPRING_ANIMATION (adw_spring_animation_get_type())
+
+ADW_AVAILABLE_IN_ALL
+GDK_DECLARE_INTERNAL_TYPE (AdwSpringAnimation, adw_spring_animation, ADW, SPRING_ANIMATION, AdwAnimation)
+
+ADW_AVAILABLE_IN_ALL
+AdwAnimation *adw_spring_animation_new (GtkWidget          *widget,
+                                        double              from,
+                                        double              to,
+                                        AdwSpringParams    *spring_params,
+                                        AdwAnimationTarget *target) G_GNUC_WARN_UNUSED_RESULT;
+
+ADW_AVAILABLE_IN_ALL
+double adw_spring_animation_get_value_from (AdwSpringAnimation *self);
+ADW_AVAILABLE_IN_ALL
+void   adw_spring_animation_set_value_from (AdwSpringAnimation *self,
+                                            double             value);
+
+ADW_AVAILABLE_IN_ALL
+double adw_spring_animation_get_value_to (AdwSpringAnimation *self);
+ADW_AVAILABLE_IN_ALL
+void   adw_spring_animation_set_value_to (AdwSpringAnimation *self,
+                                          double             value);
+
+ADW_AVAILABLE_IN_ALL
+AdwSpringParams *adw_spring_animation_get_spring_params (AdwSpringAnimation *self);
+ADW_AVAILABLE_IN_ALL
+void             adw_spring_animation_set_spring_params (AdwSpringAnimation *self,
+                                                         AdwSpringParams    *spring_params);
+
+ADW_AVAILABLE_IN_ALL
+double adw_spring_animation_get_initial_velocity (AdwSpringAnimation *self);
+ADW_AVAILABLE_IN_ALL
+void   adw_spring_animation_set_initial_velocity (AdwSpringAnimation *self,
+                                                  double              value);
+
+ADW_AVAILABLE_IN_ALL
+double adw_spring_animation_get_epsilon (AdwSpringAnimation *self);
+ADW_AVAILABLE_IN_ALL
+void   adw_spring_animation_set_epsilon (AdwSpringAnimation *self,
+                                         double              value);
+
+ADW_AVAILABLE_IN_ALL
+guint adw_spring_animation_get_estimated_duration (AdwSpringAnimation *self);
+
+G_END_DECLS
diff --git a/src/adw-spring-params.c b/src/adw-spring-params.c
new file mode 100644
index 00000000..80a1a1ec
--- /dev/null
+++ b/src/adw-spring-params.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+
+#include "adw-spring-params.h"
+
+#include <math.h>
+
+G_DEFINE_BOXED_TYPE (AdwSpringParams, adw_spring_params,
+                     adw_spring_params_ref, adw_spring_params_unref)
+
+struct _AdwSpringParams
+{
+  gatomicrefcount ref_count;
+
+  double damping;
+  double mass;
+  double stiffness;
+};
+
+AdwSpringParams *
+adw_spring_params_new (double damping_ratio,
+                       double mass,
+                       double stiffness)
+{
+  double critical_damping;
+  double damping;
+
+  g_return_val_if_fail (damping_ratio >= 0.0, NULL);
+
+  critical_damping = 2 * sqrt (mass * stiffness);
+  damping = damping_ratio * critical_damping;
+
+  return adw_spring_params_new_full (damping, mass, stiffness);
+}
+
+AdwSpringParams *
+adw_spring_params_new_full (double damping,
+                            double mass,
+                            double stiffness)
+{
+  AdwSpringParams *self;
+
+  g_return_val_if_fail (damping >= 0.0, NULL);
+  g_return_val_if_fail (mass > 0.0, NULL);
+  g_return_val_if_fail (stiffness > 0.0, NULL);
+
+  self = g_slice_new0 (AdwSpringParams);
+
+  g_atomic_ref_count_init (&self->ref_count);
+
+  self->damping = damping;
+  self->mass = mass;
+  self->stiffness = stiffness;
+
+  return self;
+}
+
+AdwSpringParams *
+adw_spring_params_new_default (void)
+{
+  return adw_spring_params_new_full (10, 1, 100);
+}
+
+AdwSpringParams *
+adw_spring_params_ref (AdwSpringParams *self)
+{
+  g_return_val_if_fail (self != NULL, NULL);
+
+  g_atomic_ref_count_inc (&self->ref_count);
+
+  return self;
+}
+
+void
+adw_spring_params_unref (AdwSpringParams *self)
+{
+  g_return_if_fail (self != NULL);
+
+  if (g_atomic_ref_count_dec (&self->ref_count))
+    g_slice_free (AdwSpringParams, self);
+}
+
+
+double
+adw_spring_params_get_damping (AdwSpringParams *self)
+{
+  g_return_val_if_fail (self != NULL, 0.0);
+
+  return self->damping;
+}
+
+double
+adw_spring_params_get_mass (AdwSpringParams *self)
+{
+  g_return_val_if_fail (self != NULL, 0.0);
+
+  return self->mass;
+}
+
+double
+adw_spring_params_get_stiffness (AdwSpringParams *self)
+{
+  g_return_val_if_fail (self != NULL, 0.0);
+
+  return self->stiffness;
+}
diff --git a/src/adw-spring-params.h b/src/adw-spring-params.h
new file mode 100644
index 00000000..eeb3e9fe
--- /dev/null
+++ b/src/adw-spring-params.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Manuel Genovés <manuel genoves gmail com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#include "adw-version.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_SPRING_PARAMS (adw_spring_params_get_type())
+
+typedef struct _AdwSpringParams AdwSpringParams;
+
+ADW_AVAILABLE_IN_ALL
+GType adw_spring_params_get_type (void) G_GNUC_CONST;
+
+ADW_AVAILABLE_IN_ALL
+AdwSpringParams *adw_spring_params_new_full (double damping,
+                                             double mass,
+                                             double stiffness) G_GNUC_WARN_UNUSED_RESULT;
+ADW_AVAILABLE_IN_ALL
+AdwSpringParams *adw_spring_params_new (double damping_ratio,
+                                        double mass,
+                                        double stiffness) G_GNUC_WARN_UNUSED_RESULT;
+ADW_AVAILABLE_IN_ALL
+AdwSpringParams *adw_spring_params_new_default (void) G_GNUC_WARN_UNUSED_RESULT;
+
+ADW_AVAILABLE_IN_ALL
+AdwSpringParams *adw_spring_params_ref   (AdwSpringParams *self);
+ADW_AVAILABLE_IN_ALL
+void             adw_spring_params_unref (AdwSpringParams *self);
+
+ADW_AVAILABLE_IN_ALL
+double adw_spring_params_get_damping   (AdwSpringParams *self);
+ADW_AVAILABLE_IN_ALL
+double adw_spring_params_get_mass      (AdwSpringParams *self);
+ADW_AVAILABLE_IN_ALL
+double adw_spring_params_get_stiffness (AdwSpringParams *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (AdwSpringParams, adw_spring_params_unref)
+
+G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 62e2e154..3371b1c9 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -52,6 +52,8 @@ G_BEGIN_DECLS
 #include "adw-preferences-row.h"
 #include "adw-preferences-window.h"
 #include "adw-split-button.h"
+#include "adw-spring-animation.h"
+#include "adw-spring-params.h"
 #include "adw-squeezer.h"
 #include "adw-status-page.h"
 #include "adw-style-manager.h"
diff --git a/src/meson.build b/src/meson.build
index 041e4df5..10a38153 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -111,6 +111,8 @@ src_headers = [
   'adw-preferences-row.h',
   'adw-preferences-window.h',
   'adw-split-button.h',
+  'adw-spring-animation.h',
+  'adw-spring-params.h',
   'adw-squeezer.h',
   'adw-status-page.h',
   'adw-style-manager.h',
@@ -177,6 +179,8 @@ src_sources = [
   'adw-settings.c',
   'adw-shadow-helper.c',
   'adw-split-button.c',
+  'adw-spring-animation.c',
+  'adw-spring-params.c',
   'adw-squeezer.c',
   'adw-style-manager.c',
   'adw-status-page.c',


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