[libadwaita/wip/exalm/swipeable-animations: 4/7] leaflet: Port child transitions to AdwAnimation
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/swipeable-animations: 4/7] leaflet: Port child transitions to AdwAnimation
- Date: Sun, 5 Dec 2021 14:13:10 +0000 (UTC)
commit ac4890e106393fb560798ea19e0db8c6cc3e1344
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Sun Dec 5 06:17:38 2021 +0500
leaflet: Port child transitions to AdwAnimation
src/adw-leaflet.c | 269 ++++++++++++++++++------------------------------------
1 file changed, 90 insertions(+), 179 deletions(-)
---
diff --git a/src/adw-leaflet.c b/src/adw-leaflet.c
index 372b8c2f..c1dd16b3 100644
--- a/src/adw-leaflet.c
+++ b/src/adw-leaflet.c
@@ -7,7 +7,6 @@
#include "config.h"
-#include "gtkprogresstrackerprivate.h"
#include "adw-animation-util.h"
#include "adw-enums-private.h"
#include "adw-fold-threshold-policy.h"
@@ -160,15 +159,12 @@ struct _AdwLeaflet {
guint duration;
double progress;
- double start_progress;
- double end_progress;
gboolean is_gesture_active;
gboolean is_cancelled;
- guint tick_id;
- GtkProgressTracker tracker;
- gboolean first_frame_skipped;
+ gboolean transition_running;
+ AdwAnimation *animation;
int last_visible_widget_width;
int last_visible_widget_height;
@@ -536,8 +532,7 @@ get_child_window_x (AdwLeaflet *self,
gboolean is_rtl;
int rtl_multiplier;
- if (!self->child_transition.is_gesture_active &&
- gtk_progress_tracker_get_state (&self->child_transition.tracker) == GTK_PROGRESS_STATE_AFTER)
+ if (!self->child_transition.transition_running)
return 0;
if (self->child_transition.active_direction != GTK_PAN_DIRECTION_LEFT &&
@@ -577,8 +572,7 @@ get_child_window_y (AdwLeaflet *self,
AdwLeafletPage *page,
int height)
{
- if (!self->child_transition.is_gesture_active &&
- gtk_progress_tracker_get_state (&self->child_transition.tracker) == GTK_PROGRESS_STATE_AFTER)
+ if (!self->child_transition.transition_running)
return 0;
if (self->child_transition.active_direction != GTK_PAN_DIRECTION_UP &&
@@ -611,151 +605,60 @@ get_child_window_y (AdwLeaflet *self,
}
static void
-child_progress_updated (AdwLeaflet *self)
+set_child_transition_running (AdwLeaflet *self,
+ gboolean running)
{
- gtk_widget_queue_draw (GTK_WIDGET (self));
-
- if (!self->homogeneous)
- gtk_widget_queue_resize (GTK_WIDGET (self));
- else
- gtk_widget_queue_allocate (GTK_WIDGET (self));
-
- if (!self->child_transition.is_gesture_active &&
- gtk_progress_tracker_get_state (&self->child_transition.tracker) == GTK_PROGRESS_STATE_AFTER) {
- if (self->child_transition.is_cancelled) {
- if (self->last_visible_child != NULL) {
- if (self->folded) {
- gtk_widget_set_child_visible (self->last_visible_child->widget, TRUE);
- gtk_widget_set_child_visible (self->visible_child->widget, FALSE);
- }
- self->visible_child = self->last_visible_child;
- self->last_visible_child = NULL;
- }
-
- self->child_transition.is_cancelled = FALSE;
-
- g_object_freeze_notify (G_OBJECT (self));
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VISIBLE_CHILD]);
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VISIBLE_CHILD_NAME]);
- g_object_thaw_notify (G_OBJECT (self));
- } else {
- if (self->last_visible_child != NULL) {
- if (self->folded)
- gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
- self->last_visible_child = NULL;
- }
- }
-
- gtk_widget_queue_allocate (GTK_WIDGET (self));
- self->child_transition.swipe_direction = 0;
- }
-}
-
-static gboolean
-child_transition_cb (GtkWidget *widget,
- GdkFrameClock *frame_clock,
- gpointer user_data)
-{
- AdwLeaflet *self = ADW_LEAFLET (user_data);
- double progress;
-
- if (self->child_transition.first_frame_skipped) {
- gtk_progress_tracker_advance_frame (&self->child_transition.tracker,
- gdk_frame_clock_get_frame_time (frame_clock));
- progress = gtk_progress_tracker_get_ease_out_cubic (&self->child_transition.tracker, FALSE);
- self->child_transition.progress =
- adw_lerp (self->child_transition.start_progress,
- self->child_transition.end_progress, progress);
- } else
- self->child_transition.first_frame_skipped = TRUE;
-
- /* Finish animation early if not mapped anymore */
- if (!gtk_widget_get_mapped (widget))
- gtk_progress_tracker_finish (&self->child_transition.tracker);
-
- child_progress_updated (self);
-
- if (gtk_progress_tracker_get_state (&self->child_transition.tracker) == GTK_PROGRESS_STATE_AFTER) {
- self->child_transition.tick_id = 0;
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TRANSITION_RUNNING]);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-schedule_child_ticks (AdwLeaflet *self)
-{
- if (self->child_transition.tick_id == 0) {
- self->child_transition.tick_id =
- gtk_widget_add_tick_callback (GTK_WIDGET (self),
- child_transition_cb,
- self, NULL);
- if (!self->child_transition.is_gesture_active)
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TRANSITION_RUNNING]);
- }
-}
+ if (self->child_transition.transition_running == running)
+ return;
-static void
-unschedule_child_ticks (AdwLeaflet *self)
-{
- if (self->child_transition.tick_id != 0) {
- gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->child_transition.tick_id);
- self->child_transition.tick_id = 0;
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TRANSITION_RUNNING]);
- }
+ self->child_transition.transition_running = running;
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TRANSITION_RUNNING]);
}
static void
-stop_child_transition (AdwLeaflet *self)
+child_transition_cb (AdwLeaflet *self,
+ double value)
{
- unschedule_child_ticks (self);
- gtk_progress_tracker_finish (&self->child_transition.tracker);
- if (self->last_visible_child != NULL) {
- gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
- self->last_visible_child = NULL;
- }
+ self->child_transition.progress = value;
- self->child_transition.swipe_direction = 0;
+ if (!self->homogeneous)
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+ else
+ gtk_widget_queue_allocate (GTK_WIDGET (self));
}
static void
-start_child_transition (AdwLeaflet *self,
- guint transition_duration,
- GtkPanDirection transition_direction)
+child_transition_done_cb (AdwLeaflet *self)
{
- GtkWidget *widget = GTK_WIDGET (self);
+ if (self->child_transition.is_cancelled) {
+ if (self->last_visible_child != NULL) {
+ if (self->folded) {
+ gtk_widget_set_child_visible (self->last_visible_child->widget, TRUE);
+ gtk_widget_set_child_visible (self->visible_child->widget, FALSE);
+ }
+ self->visible_child = self->last_visible_child;
+ self->last_visible_child = NULL;
+ }
- if (gtk_widget_get_mapped (widget) &&
- ((adw_get_enable_animations (widget) &&
- transition_duration != 0) ||
- self->child_transition.is_gesture_active) &&
- self->last_visible_child != NULL &&
- /* Don't animate child transition when a mode transition is ongoing. */
- adw_animation_get_state (self->mode_transition.animation) != ADW_ANIMATION_PLAYING) {
- self->child_transition.active_direction = transition_direction;
- self->child_transition.first_frame_skipped = FALSE;
- self->child_transition.start_progress = 0;
- self->child_transition.end_progress = 1;
- self->child_transition.progress = 0;
self->child_transition.is_cancelled = FALSE;
- if (!self->child_transition.is_gesture_active) {
- schedule_child_ticks (self);
- gtk_progress_tracker_start (&self->child_transition.tracker,
- transition_duration * 1000,
- 0,
- 1.0);
+ g_object_freeze_notify (G_OBJECT (self));
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VISIBLE_CHILD]);
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VISIBLE_CHILD_NAME]);
+ g_object_thaw_notify (G_OBJECT (self));
+ } else {
+ if (self->last_visible_child != NULL) {
+ if (self->folded)
+ gtk_widget_set_child_visible (self->last_visible_child->widget, FALSE);
+ self->last_visible_child = NULL;
}
}
- else {
- unschedule_child_ticks (self);
- gtk_progress_tracker_finish (&self->child_transition.tracker);
- }
- child_progress_updated (self);
+ adw_animation_reset (self->child_transition.animation);
+
+ set_child_transition_running (self, FALSE);
+
+ self->child_transition.swipe_direction = 0;
}
static void
@@ -829,9 +732,8 @@ set_visible_child (AdwLeaflet *self,
(gpointer *)&self->visible_child->last_focus);
}
- if (self->last_visible_child)
- gtk_widget_set_child_visible (self->last_visible_child->widget, !self->folded);
- self->last_visible_child = NULL;
+ if (self->child_transition.transition_running)
+ adw_animation_skip (self->child_transition.animation);
if (self->visible_child && self->visible_child->widget) {
if (gtk_widget_is_visible (widget)) {
@@ -881,7 +783,21 @@ set_visible_child (AdwLeaflet *self,
else
gtk_widget_queue_resize (widget);
- start_child_transition (self, transition_duration, transition_direction);
+ self->child_transition.active_direction = transition_direction;
+ self->child_transition.progress = 0;
+ self->child_transition.is_cancelled = FALSE;
+
+ if (!self->child_transition.is_gesture_active) {
+ adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ 0);
+ adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ 1);
+ adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ transition_duration);
+
+ set_child_transition_running (self, TRUE);
+ adw_animation_play (self->child_transition.animation);
+ }
}
if (self->pages) {
@@ -922,7 +838,7 @@ start_mode_transition (AdwLeaflet *self,
if (adw_timed_animation_get_value_to (ADW_TIMED_ANIMATION (self->mode_transition.animation)) == target)
return;
- stop_child_transition (self);
+ adw_animation_skip (self->child_transition.animation);
adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->mode_transition.animation),
self->mode_transition.current_pos);
@@ -1520,10 +1436,8 @@ prepare_cb (AdwSwipeTracker *tracker,
{
self->child_transition.swipe_direction = direction;
- if (self->child_transition.tick_id > 0) {
- gtk_widget_remove_tick_callback (GTK_WIDGET (self),
- self->child_transition.tick_id);
- self->child_transition.tick_id = 0;
+ if (self->child_transition.transition_running) {
+ adw_animation_pause (self->child_transition.animation);
self->child_transition.is_gesture_active = TRUE;
self->child_transition.is_cancelled = FALSE;
} else {
@@ -1537,7 +1451,7 @@ prepare_cb (AdwSwipeTracker *tracker,
set_visible_child (self, page, self->transition_type,
self->child_transition.duration);
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD_TRANSITION_RUNNING]);
+ set_child_transition_running (self, TRUE);
}
}
}
@@ -1547,8 +1461,7 @@ update_swipe_cb (AdwSwipeTracker *tracker,
double progress,
AdwLeaflet *self)
{
- self->child_transition.progress = ABS (progress);
- child_progress_updated (self);
+ child_transition_cb (self, ABS (progress));
}
static void
@@ -1560,24 +1473,17 @@ end_swipe_cb (AdwSwipeTracker *tracker,
if (!self->child_transition.is_gesture_active)
return;
- self->child_transition.start_progress = self->child_transition.progress;
- self->child_transition.end_progress = ABS (to);
+ adw_timed_animation_set_value_from (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ self->child_transition.progress);
+ adw_timed_animation_set_value_to (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ ABS (to));
self->child_transition.is_cancelled = (to == 0);
- self->child_transition.first_frame_skipped = TRUE;
-
- schedule_child_ticks (self);
- if (adw_get_enable_animations (GTK_WIDGET (self)) && duration != 0) {
- gtk_progress_tracker_start (&self->child_transition.tracker,
- duration * 1000,
- 0,
- 1.0);
- } else {
- self->child_transition.progress = self->child_transition.end_progress;
- gtk_progress_tracker_finish (&self->child_transition.tracker);
- }
+
+ adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ duration);
+ adw_animation_play (self->child_transition.animation);
self->child_transition.is_gesture_active = FALSE;
- child_progress_updated (self);
gtk_widget_queue_draw (GTK_WIDGET (self));
}
@@ -1803,8 +1709,7 @@ allocate_shadow (AdwLeaflet *self,
double shadow_progress, mode_progress;
GtkPanDirection shadow_direction;
- is_transition = self->child_transition.is_gesture_active ||
- gtk_progress_tracker_get_state (&self->child_transition.tracker) !=
GTK_PROGRESS_STATE_AFTER ||
+ is_transition = self->child_transition.transition_running ||
adw_animation_get_state (self->mode_transition.animation) == ADW_ANIMATION_PLAYING;
overlap_child = get_top_overlap_child (self);
@@ -2003,8 +1908,7 @@ adw_leaflet_snapshot (GtkWidget *widget,
overlap_child = get_top_overlap_child (self);
- is_transition = self->child_transition.is_gesture_active ||
- gtk_progress_tracker_get_state (&self->child_transition.tracker) !=
GTK_PROGRESS_STATE_AFTER ||
+ is_transition = self->child_transition.transition_running ||
adw_animation_get_state (self->mode_transition.animation) == ADW_ANIMATION_PLAYING;
if (!is_transition ||
@@ -2187,6 +2091,7 @@ adw_leaflet_dispose (GObject *object)
leaflet_remove (self, child, TRUE);
g_clear_object (&self->mode_transition.animation);
+ g_clear_object (&self->child_transition.animation);
G_OBJECT_CLASS (adw_leaflet_parent_class)->dispose (object);
}
@@ -2202,8 +2107,6 @@ adw_leaflet_finalize (GObject *object)
g_object_remove_weak_pointer (G_OBJECT (self->pages),
(gpointer *) &self->pages);
- unschedule_child_ticks (self);
-
G_OBJECT_CLASS (adw_leaflet_parent_class)->finalize (object);
}
@@ -2543,6 +2446,14 @@ adw_leaflet_init (AdwLeaflet *self)
self->mode_transition.animation =
adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
self->mode_transition.duration, target);
+
+ target = adw_callback_animation_target_new ((AdwAnimationTargetFunc) child_transition_cb,
+ self, NULL);
+ self->child_transition.animation =
+ adw_timed_animation_new (GTK_WIDGET (self), 0, 1,
+ self->child_transition.duration, target);
+ g_signal_connect_swapped (self->child_transition.animation, "done",
+ G_CALLBACK (child_transition_done_cb), self);
}
static void
@@ -2589,8 +2500,7 @@ adw_leaflet_get_snap_points (AdwSwipeable *swipeable,
int n;
double *points, lower, upper;
- if (self->child_transition.tick_id > 0 ||
- self->child_transition.is_gesture_active) {
+ if (self->child_transition.transition_running) {
int current_direction;
gboolean is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
@@ -2642,8 +2552,7 @@ adw_leaflet_get_progress (AdwSwipeable *swipeable)
gboolean new_first = FALSE;
GList *children;
- if (!self->child_transition.is_gesture_active &&
- gtk_progress_tracker_get_state (&self->child_transition.tracker) == GTK_PROGRESS_STATE_AFTER)
+ if (!self->child_transition.transition_running)
return 0;
for (children = self->children; children; children = children->next) {
@@ -2687,8 +2596,7 @@ adw_leaflet_get_swipe_area (AdwSwipeable *swipeable,
if (self->transition_type == ADW_LEAFLET_TRANSITION_TYPE_SLIDE)
return;
- if (self->child_transition.is_gesture_active ||
- gtk_progress_tracker_get_state (&self->child_transition.tracker) != GTK_PROGRESS_STATE_AFTER)
+ if (self->child_transition.transition_running)
progress = self->child_transition.progress;
if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
@@ -3291,6 +3199,10 @@ adw_leaflet_set_child_transition_duration (AdwLeaflet *self,
return;
self->child_transition.duration = duration;
+
+ adw_timed_animation_set_duration (ADW_TIMED_ANIMATION (self->child_transition.animation),
+ duration);
+
g_object_notify_by_pspec (G_OBJECT (self),
props[PROP_CHILD_TRANSITION_DURATION]);
}
@@ -3409,8 +3321,7 @@ adw_leaflet_get_child_transition_running (AdwLeaflet *self)
{
g_return_val_if_fail (ADW_IS_LEAFLET (self), FALSE);
- return (self->child_transition.tick_id != 0 ||
- self->child_transition.is_gesture_active);
+ return self->child_transition.transition_running;
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]