Compare commits
16 Commits
path-itera
...
wip/watson
Author | SHA1 | Date | |
---|---|---|---|
|
c9f4c86b1f | ||
|
945f4a45d5 | ||
|
e56a1ddce3 | ||
|
b1c94375e8 | ||
|
865201f11f | ||
|
f5a8201b0f | ||
|
4bf81e6ab5 | ||
|
a09586175e | ||
|
3fed034b0c | ||
|
c2b97c1b22 | ||
|
5d5ee76a8b | ||
|
abc8b34683 | ||
|
d3961dacad | ||
|
e962ebab82 | ||
|
ed75fa655b | ||
|
44a9c0e36d |
@@ -520,6 +520,7 @@ gtk_private_h_sources = \
|
||||
gtkprintutils.h \
|
||||
gtkprivate.h \
|
||||
gtkpixelcacheprivate.h \
|
||||
gtkprogresstrackerprivate.h \
|
||||
gtkquery.h \
|
||||
gtkrangeprivate.h \
|
||||
gtkrbtree.h \
|
||||
@@ -832,6 +833,7 @@ gtk_base_c_sources = \
|
||||
gtkprivate.c \
|
||||
gtkprivatetypebuiltins.c \
|
||||
gtkprogressbar.c \
|
||||
gtkprogresstracker.c \
|
||||
gtkpixelcache.c \
|
||||
gtkpopover.c \
|
||||
gtkpopovermenu.c \
|
||||
|
@@ -71,7 +71,7 @@ gtk_css_animated_style_is_static (GtkCssStyle *style)
|
||||
|
||||
for (list = animated->animations; list; list = list->next)
|
||||
{
|
||||
if (!_gtk_style_animation_is_static (list->data, animated->current_time))
|
||||
if (!_gtk_style_animation_is_static (list->data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -288,7 +288,10 @@ gtk_css_animated_style_create_css_transitions (GSList *animations,
|
||||
{
|
||||
animation = gtk_css_animated_style_find_transition (GTK_CSS_ANIMATED_STYLE (source), i);
|
||||
if (animation)
|
||||
animations = g_slist_prepend (animations, g_object_ref (animation));
|
||||
{
|
||||
animation = _gtk_style_animation_advance (animation, timestamp);
|
||||
animations = g_slist_prepend (animations, animation);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -301,8 +304,9 @@ gtk_css_animated_style_create_css_transitions (GSList *animations,
|
||||
animation = _gtk_css_transition_new (i,
|
||||
gtk_css_style_get_value (source, i),
|
||||
_gtk_css_array_value_get_nth (timing_functions, i),
|
||||
timestamp + delay * G_USEC_PER_SEC,
|
||||
timestamp + (delay + duration) * G_USEC_PER_SEC);
|
||||
timestamp,
|
||||
duration * G_USEC_PER_SEC,
|
||||
delay * G_USEC_PER_SEC);
|
||||
animations = g_slist_prepend (animations, animation);
|
||||
}
|
||||
|
||||
@@ -367,9 +371,9 @@ gtk_css_animated_style_create_css_animations (GSList *animation
|
||||
|
||||
if (animation)
|
||||
{
|
||||
animation = _gtk_css_animation_copy (GTK_CSS_ANIMATION (animation),
|
||||
timestamp,
|
||||
_gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
|
||||
animation = _gtk_css_animation_advance_with_play_state (GTK_CSS_ANIMATION (animation),
|
||||
timestamp,
|
||||
_gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -400,8 +404,7 @@ gtk_css_animated_style_create_css_animations (GSList *animation
|
||||
/* PUBLIC API */
|
||||
|
||||
static void
|
||||
gtk_css_animated_style_apply_animations (GtkCssAnimatedStyle *style,
|
||||
gint64 timestamp)
|
||||
gtk_css_animated_style_apply_animations (GtkCssAnimatedStyle *style)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
@@ -409,9 +412,8 @@ gtk_css_animated_style_apply_animations (GtkCssAnimatedStyle *style,
|
||||
{
|
||||
GtkStyleAnimation *animation = l->data;
|
||||
|
||||
_gtk_style_animation_set_values (animation,
|
||||
timestamp,
|
||||
GTK_CSS_ANIMATED_STYLE (style));
|
||||
_gtk_style_animation_apply_values (animation,
|
||||
GTK_CSS_ANIMATED_STYLE (style));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,7 +450,7 @@ gtk_css_animated_style_new (GtkCssStyle *base_style,
|
||||
result->current_time = timestamp;
|
||||
result->animations = animations;
|
||||
|
||||
gtk_css_animated_style_apply_animations (result, timestamp);
|
||||
gtk_css_animated_style_apply_animations (result);
|
||||
|
||||
return GTK_CSS_STYLE (result);
|
||||
}
|
||||
@@ -464,18 +466,21 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
|
||||
gtk_internal_return_val_if_fail (GTK_IS_CSS_ANIMATED_STYLE (source), NULL);
|
||||
gtk_internal_return_val_if_fail (GTK_IS_CSS_STYLE (base), NULL);
|
||||
|
||||
if (timestamp == 0)
|
||||
if (timestamp == 0 || timestamp == source->current_time)
|
||||
return g_object_ref (source->style);
|
||||
|
||||
gtk_internal_return_val_if_fail (timestamp > source->current_time, NULL);
|
||||
|
||||
animations = NULL;
|
||||
for (l = source->animations; l; l = l->next)
|
||||
{
|
||||
GtkStyleAnimation *animation = l->data;
|
||||
|
||||
if (_gtk_style_animation_is_finished (animation, timestamp))
|
||||
if (_gtk_style_animation_is_finished (animation))
|
||||
continue;
|
||||
|
||||
animations = g_slist_prepend (animations, g_object_ref (animation));
|
||||
animation = _gtk_style_animation_advance (animation, timestamp);
|
||||
animations = g_slist_prepend (animations, animation);
|
||||
}
|
||||
animations = g_slist_reverse (animations);
|
||||
|
||||
@@ -488,7 +493,7 @@ gtk_css_animated_style_new_advance (GtkCssAnimatedStyle *source,
|
||||
result->current_time = timestamp;
|
||||
result->animations = animations;
|
||||
|
||||
gtk_css_animated_style_apply_animations (result, timestamp);
|
||||
gtk_css_animated_style_apply_animations (result);
|
||||
|
||||
return GTK_CSS_STYLE (result);
|
||||
}
|
||||
|
@@ -22,41 +22,25 @@
|
||||
#include "gtkcssanimationprivate.h"
|
||||
|
||||
#include "gtkcsseasevalueprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
G_DEFINE_TYPE (GtkCssAnimation, _gtk_css_animation, GTK_TYPE_STYLE_ANIMATION)
|
||||
|
||||
/* NB: Return value can be negative (if animation hasn't started yet) */
|
||||
static gint64
|
||||
gtk_css_animation_get_elapsed (GtkCssAnimation *animation,
|
||||
gint64 for_time_us)
|
||||
{
|
||||
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
|
||||
return animation->timestamp;
|
||||
else
|
||||
return for_time_us - animation->timestamp;
|
||||
}
|
||||
/* NB: Return value can be negative and +-Inf */
|
||||
static double
|
||||
gtk_css_animation_get_iteration (GtkCssAnimation *animation,
|
||||
gint64 for_time_us)
|
||||
{
|
||||
return (double) gtk_css_animation_get_elapsed (animation, for_time_us) / animation->duration;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_animation_is_executing_at_iteration (GtkCssAnimation *animation,
|
||||
double iteration)
|
||||
gtk_css_animation_is_executing (GtkCssAnimation *animation)
|
||||
{
|
||||
GtkProgressState state = gtk_progress_tracker_get_state (&animation->tracker);
|
||||
|
||||
switch (animation->fill_mode)
|
||||
{
|
||||
case GTK_CSS_FILL_NONE:
|
||||
return iteration >= 0 && iteration <= animation->iteration_count;
|
||||
return state == GTK_PROGRESS_STATE_DURING;
|
||||
case GTK_CSS_FILL_FORWARDS:
|
||||
return iteration >= 0;
|
||||
return state != GTK_PROGRESS_STATE_BEFORE;
|
||||
case GTK_CSS_FILL_BACKWARDS:
|
||||
return iteration <= animation->iteration_count;
|
||||
return state != GTK_PROGRESS_STATE_AFTER;
|
||||
case GTK_CSS_FILL_BOTH:
|
||||
return TRUE;
|
||||
default:
|
||||
@@ -65,57 +49,58 @@ gtk_css_animation_is_executing_at_iteration (GtkCssAnimation *animation,
|
||||
}
|
||||
|
||||
static double
|
||||
gtk_css_animation_get_progress_from_iteration (GtkCssAnimation *animation,
|
||||
double iteration)
|
||||
gtk_css_animation_get_progress (GtkCssAnimation *animation)
|
||||
{
|
||||
gboolean reverse;
|
||||
double completed;
|
||||
|
||||
iteration = CLAMP (iteration, 0.0, animation->iteration_count);
|
||||
completed = floor (iteration);
|
||||
gboolean reverse, odd_iteration;
|
||||
gint cycle = gtk_progress_tracker_get_iteration_cycle (&animation->tracker);
|
||||
odd_iteration = cycle % 2 > 0;
|
||||
|
||||
switch (animation->direction)
|
||||
{
|
||||
case GTK_CSS_DIRECTION_NORMAL:
|
||||
reverse = completed == iteration && iteration > 0;
|
||||
reverse = FALSE;
|
||||
break;
|
||||
case GTK_CSS_DIRECTION_REVERSE:
|
||||
reverse = !(completed == iteration && iteration > 0);
|
||||
reverse = TRUE;
|
||||
break;
|
||||
case GTK_CSS_DIRECTION_ALTERNATE:
|
||||
reverse = fmod (iteration, 2) >= 1.0;
|
||||
reverse = odd_iteration;
|
||||
break;
|
||||
case GTK_CSS_DIRECTION_ALTERNATE_REVERSE:
|
||||
reverse = !(fmod (iteration, 2) >= 1.0);
|
||||
reverse = !odd_iteration;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (0.0);
|
||||
}
|
||||
|
||||
iteration -= completed;
|
||||
if (reverse)
|
||||
iteration = 1.0 - iteration;
|
||||
return gtk_progress_tracker_get_progress (&animation->tracker, reverse);
|
||||
}
|
||||
|
||||
return iteration;
|
||||
GtkStyleAnimation *
|
||||
gtk_css_animation_advance (GtkStyleAnimation *style_animation,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
|
||||
|
||||
return _gtk_css_animation_advance_with_play_state (animation,
|
||||
timestamp,
|
||||
animation->play_state);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_animation_set_values (GtkStyleAnimation *style_animation,
|
||||
gint64 for_time_us,
|
||||
GtkCssAnimatedStyle *style)
|
||||
gtk_css_animation_apply_values (GtkStyleAnimation *style_animation,
|
||||
GtkCssAnimatedStyle *style)
|
||||
{
|
||||
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
|
||||
double iteration, progress;
|
||||
double progress;
|
||||
guint i;
|
||||
|
||||
iteration = gtk_css_animation_get_iteration (animation, for_time_us);
|
||||
|
||||
if (!gtk_css_animation_is_executing_at_iteration (animation, iteration))
|
||||
if (!gtk_css_animation_is_executing (animation))
|
||||
return;
|
||||
|
||||
progress = gtk_css_animation_get_progress_from_iteration (animation, iteration);
|
||||
progress = gtk_css_animation_get_progress (animation);
|
||||
progress = _gtk_css_ease_value_transform (animation->ease, progress);
|
||||
|
||||
|
||||
for (i = 0; i < _gtk_css_keyframes_get_n_properties (animation->keyframes); i++)
|
||||
{
|
||||
GtkCssValue *value;
|
||||
@@ -133,25 +118,20 @@ gtk_css_animation_set_values (GtkStyleAnimation *style_animation,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_animation_is_finished (GtkStyleAnimation *style_animation,
|
||||
gint64 at_time_us)
|
||||
gtk_css_animation_is_finished (GtkStyleAnimation *style_animation)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_animation_is_static (GtkStyleAnimation *style_animation,
|
||||
gint64 at_time_us)
|
||||
gtk_css_animation_is_static (GtkStyleAnimation *style_animation)
|
||||
{
|
||||
GtkCssAnimation *animation = GTK_CSS_ANIMATION (style_animation);
|
||||
double iteration;
|
||||
|
||||
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
|
||||
return TRUE;
|
||||
|
||||
iteration = gtk_css_animation_get_iteration (animation, at_time_us);
|
||||
|
||||
return iteration >= animation->iteration_count;
|
||||
return gtk_progress_tracker_get_state (&animation->tracker) == GTK_PROGRESS_STATE_AFTER;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -174,7 +154,8 @@ _gtk_css_animation_class_init (GtkCssAnimationClass *klass)
|
||||
|
||||
object_class->finalize = gtk_css_animation_finalize;
|
||||
|
||||
animation_class->set_values = gtk_css_animation_set_values;
|
||||
animation_class->advance = gtk_css_animation_advance;
|
||||
animation_class->apply_values = gtk_css_animation_apply_values;
|
||||
animation_class->is_finished = gtk_css_animation_is_finished;
|
||||
animation_class->is_static = gtk_css_animation_is_static;
|
||||
}
|
||||
@@ -207,17 +188,16 @@ _gtk_css_animation_new (const char *name,
|
||||
|
||||
animation->name = g_strdup (name);
|
||||
animation->keyframes = _gtk_css_keyframes_ref (keyframes);
|
||||
if (play_state == GTK_CSS_PLAY_STATE_PAUSED)
|
||||
animation->timestamp = - delay_us;
|
||||
else
|
||||
animation->timestamp = timestamp + delay_us;
|
||||
|
||||
animation->duration = duration_us;
|
||||
animation->ease = _gtk_css_value_ref (ease);
|
||||
animation->direction = direction;
|
||||
animation->play_state = play_state;
|
||||
animation->fill_mode = fill_mode;
|
||||
animation->iteration_count = iteration_count;
|
||||
|
||||
gtk_progress_tracker_start (&animation->tracker, duration_us, delay_us, iteration_count);
|
||||
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
|
||||
gtk_progress_tracker_skip_frame (&animation->tracker, timestamp);
|
||||
else
|
||||
gtk_progress_tracker_advance_frame (&animation->tracker, timestamp);
|
||||
|
||||
return GTK_STYLE_ANIMATION (animation);
|
||||
}
|
||||
@@ -231,24 +211,28 @@ _gtk_css_animation_get_name (GtkCssAnimation *animation)
|
||||
}
|
||||
|
||||
GtkStyleAnimation *
|
||||
_gtk_css_animation_copy (GtkCssAnimation *animation,
|
||||
gint64 at_time_us,
|
||||
GtkCssPlayState play_state)
|
||||
_gtk_css_animation_advance_with_play_state (GtkCssAnimation *source,
|
||||
gint64 timestamp,
|
||||
GtkCssPlayState play_state)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_CSS_ANIMATION (animation), NULL);
|
||||
GtkCssAnimation *animation;
|
||||
|
||||
if (animation->play_state == play_state)
|
||||
return g_object_ref (animation);
|
||||
g_return_val_if_fail (GTK_IS_CSS_ANIMATION (source), NULL);
|
||||
|
||||
return _gtk_css_animation_new (animation->name,
|
||||
animation->keyframes,
|
||||
at_time_us,
|
||||
- gtk_css_animation_get_elapsed (animation, at_time_us),
|
||||
animation->duration,
|
||||
animation->ease,
|
||||
animation->direction,
|
||||
play_state,
|
||||
animation->fill_mode,
|
||||
animation->iteration_count);
|
||||
animation = g_object_new (GTK_TYPE_CSS_ANIMATION, NULL);
|
||||
|
||||
animation->name = g_strdup (source->name);
|
||||
animation->keyframes = _gtk_css_keyframes_ref (source->keyframes);
|
||||
animation->ease = _gtk_css_value_ref (source->ease);
|
||||
animation->direction = source->direction;
|
||||
animation->play_state = play_state;
|
||||
animation->fill_mode = source->fill_mode;
|
||||
|
||||
gtk_progress_tracker_init_copy (&source->tracker, &animation->tracker);
|
||||
if (animation->play_state == GTK_CSS_PLAY_STATE_PAUSED)
|
||||
gtk_progress_tracker_skip_frame (&animation->tracker, timestamp);
|
||||
else
|
||||
gtk_progress_tracker_advance_frame (&animation->tracker, timestamp);
|
||||
|
||||
return GTK_STYLE_ANIMATION (animation);
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "gtkstyleanimationprivate.h"
|
||||
|
||||
#include "gtkcsskeyframesprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -43,12 +44,10 @@ struct _GtkCssAnimation
|
||||
char *name;
|
||||
GtkCssKeyframes *keyframes;
|
||||
GtkCssValue *ease;
|
||||
gint64 timestamp; /* elapsed time when paused, start time when playing (can be negative) */
|
||||
gint64 duration; /* duration of 1 cycle */
|
||||
double iteration_count;
|
||||
GtkCssDirection direction;
|
||||
GtkCssPlayState play_state;
|
||||
GtkCssFillMode fill_mode;
|
||||
GtkProgressTracker tracker;
|
||||
};
|
||||
|
||||
struct _GtkCssAnimationClass
|
||||
@@ -69,9 +68,9 @@ GtkStyleAnimation * _gtk_css_animation_new (const char *
|
||||
GtkCssFillMode fill_mode,
|
||||
double iteration_count);
|
||||
|
||||
GtkStyleAnimation * _gtk_css_animation_copy (GtkCssAnimation *animation,
|
||||
gint64 at_time_us,
|
||||
GtkCssPlayState play_state);
|
||||
GtkStyleAnimation * _gtk_css_animation_advance_with_play_state (GtkCssAnimation *animation,
|
||||
gint64 timestamp,
|
||||
GtkCssPlayState play_state);
|
||||
|
||||
const char * _gtk_css_animation_get_name (GtkCssAnimation *animation);
|
||||
|
||||
|
@@ -22,60 +22,79 @@
|
||||
#include "gtkcsstransitionprivate.h"
|
||||
|
||||
#include "gtkcsseasevalueprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkCssTransition, _gtk_css_transition, GTK_TYPE_STYLE_ANIMATION)
|
||||
|
||||
static void
|
||||
gtk_css_transition_set_values (GtkStyleAnimation *animation,
|
||||
gint64 for_time_us,
|
||||
GtkCssAnimatedStyle *style)
|
||||
static GtkStyleAnimation *
|
||||
gtk_css_transition_advance (GtkStyleAnimation *style_animation,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GtkCssTransition *transition = GTK_CSS_TRANSITION (animation);
|
||||
GtkCssTransition *source = GTK_CSS_TRANSITION (style_animation);
|
||||
|
||||
GtkCssTransition *transition;
|
||||
|
||||
transition = g_object_new (GTK_TYPE_CSS_TRANSITION, NULL);
|
||||
|
||||
transition->property = source->property;
|
||||
transition->start = _gtk_css_value_ref (source->start);
|
||||
transition->ease = _gtk_css_value_ref (source->ease);
|
||||
|
||||
gtk_progress_tracker_init_copy (&source->tracker, &transition->tracker);
|
||||
gtk_progress_tracker_advance_frame (&transition->tracker, timestamp);
|
||||
|
||||
return GTK_STYLE_ANIMATION (transition);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_transition_apply_values (GtkStyleAnimation *style_animation,
|
||||
GtkCssAnimatedStyle *style)
|
||||
{
|
||||
GtkCssTransition *transition = GTK_CSS_TRANSITION (style_animation);
|
||||
GtkCssValue *value, *end;
|
||||
double progress;
|
||||
GtkProgressState state;
|
||||
|
||||
end = gtk_css_animated_style_get_intrinsic_value (style, transition->property);
|
||||
|
||||
if (transition->start_time >= for_time_us)
|
||||
state = gtk_progress_tracker_get_state (&transition->tracker);
|
||||
|
||||
if (state == GTK_PROGRESS_STATE_BEFORE)
|
||||
value = _gtk_css_value_ref (transition->start);
|
||||
else if (transition->end_time > for_time_us)
|
||||
else if (state == GTK_PROGRESS_STATE_DURING)
|
||||
{
|
||||
progress = (double) (for_time_us - transition->start_time) / (transition->end_time - transition->start_time);
|
||||
progress = gtk_progress_tracker_get_progress (&transition->tracker, FALSE);
|
||||
progress = _gtk_css_ease_value_transform (transition->ease, progress);
|
||||
|
||||
value = _gtk_css_value_transition (transition->start,
|
||||
end,
|
||||
transition->property,
|
||||
progress);
|
||||
if (value == NULL)
|
||||
value = _gtk_css_value_ref (end);
|
||||
}
|
||||
else
|
||||
value = NULL;
|
||||
return;
|
||||
|
||||
if (value)
|
||||
{
|
||||
gtk_css_animated_style_set_animated_value (style, transition->property, value);
|
||||
_gtk_css_value_unref (value);
|
||||
}
|
||||
if (value == NULL)
|
||||
value = _gtk_css_value_ref (end);
|
||||
|
||||
gtk_css_animated_style_set_animated_value (style, transition->property, value);
|
||||
_gtk_css_value_unref (value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_transition_is_finished (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
gtk_css_transition_is_finished (GtkStyleAnimation *animation)
|
||||
{
|
||||
GtkCssTransition *transition = GTK_CSS_TRANSITION (animation);
|
||||
|
||||
return at_time_us >= transition->end_time;
|
||||
return gtk_progress_tracker_get_state (&transition->tracker) == GTK_PROGRESS_STATE_AFTER;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_transition_is_static (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
gtk_css_transition_is_static (GtkStyleAnimation *animation)
|
||||
{
|
||||
GtkCssTransition *transition = GTK_CSS_TRANSITION (animation);
|
||||
|
||||
return at_time_us >= transition->end_time;
|
||||
return gtk_progress_tracker_get_state (&transition->tracker) == GTK_PROGRESS_STATE_AFTER;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -97,7 +116,8 @@ _gtk_css_transition_class_init (GtkCssTransitionClass *klass)
|
||||
|
||||
object_class->finalize = gtk_css_transition_finalize;
|
||||
|
||||
animation_class->set_values = gtk_css_transition_set_values;
|
||||
animation_class->advance = gtk_css_transition_advance;
|
||||
animation_class->apply_values = gtk_css_transition_apply_values;
|
||||
animation_class->is_finished = gtk_css_transition_is_finished;
|
||||
animation_class->is_static = gtk_css_transition_is_static;
|
||||
}
|
||||
@@ -111,22 +131,22 @@ GtkStyleAnimation *
|
||||
_gtk_css_transition_new (guint property,
|
||||
GtkCssValue *start,
|
||||
GtkCssValue *ease,
|
||||
gint64 start_time_us,
|
||||
gint64 end_time_us)
|
||||
gint64 timestamp,
|
||||
gint64 duration_us,
|
||||
gint64 delay_us)
|
||||
{
|
||||
GtkCssTransition *transition;
|
||||
|
||||
g_return_val_if_fail (start != NULL, NULL);
|
||||
g_return_val_if_fail (ease != NULL, NULL);
|
||||
g_return_val_if_fail (start_time_us <= end_time_us, NULL);
|
||||
|
||||
transition = g_object_new (GTK_TYPE_CSS_TRANSITION, NULL);
|
||||
|
||||
transition->property = property;
|
||||
transition->start = _gtk_css_value_ref (start);
|
||||
transition->ease = _gtk_css_value_ref (ease);
|
||||
transition->start_time = start_time_us;
|
||||
transition->end_time = end_time_us;
|
||||
gtk_progress_tracker_start (&transition->tracker, duration_us, delay_us, 1.0);
|
||||
gtk_progress_tracker_advance_frame (&transition->tracker, timestamp);
|
||||
|
||||
return GTK_STYLE_ANIMATION (transition);
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GTK_CSS_TRANSITION_PRIVATE_H__
|
||||
|
||||
#include "gtkstyleanimationprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -38,11 +39,10 @@ struct _GtkCssTransition
|
||||
{
|
||||
GtkStyleAnimation parent;
|
||||
|
||||
guint property;
|
||||
GtkCssValue *start;
|
||||
GtkCssValue *ease;
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
guint property;
|
||||
GtkCssValue *start;
|
||||
GtkCssValue *ease;
|
||||
GtkProgressTracker tracker;
|
||||
};
|
||||
|
||||
struct _GtkCssTransitionClass
|
||||
@@ -55,8 +55,9 @@ GType _gtk_css_transition_get_type (void) G_GNUC_CONST;
|
||||
GtkStyleAnimation * _gtk_css_transition_new (guint property,
|
||||
GtkCssValue *start,
|
||||
GtkCssValue *ease,
|
||||
gint64 start_time_us,
|
||||
gint64 end_time_us);
|
||||
gint64 timestamp,
|
||||
gint64 duration_us,
|
||||
gint64 delay_us);
|
||||
|
||||
guint _gtk_css_transition_get_property (GtkCssTransition *transition);
|
||||
|
||||
|
@@ -70,6 +70,7 @@
|
||||
#include "gtkmagnifierprivate.h"
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkcsscustomgadgetprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#include "a11y/gtkentryaccessible.h"
|
||||
|
||||
@@ -196,10 +197,11 @@ struct _GtkEntryPrivate
|
||||
gdouble progress_pulse_fraction;
|
||||
gdouble progress_pulse_current;
|
||||
|
||||
guint tick_id;
|
||||
gint64 pulse1;
|
||||
gint64 pulse2;
|
||||
gint64 frame1;
|
||||
guint tick_id;
|
||||
GtkProgressTracker tracker;
|
||||
gint64 pulse1;
|
||||
gint64 pulse2;
|
||||
gdouble last_iteration;
|
||||
|
||||
gchar *placeholder_text;
|
||||
|
||||
@@ -10394,31 +10396,30 @@ tick_cb (GtkWidget *widget,
|
||||
{
|
||||
GtkEntry *entry = GTK_ENTRY (widget);
|
||||
GtkEntryPrivate *priv = entry->priv;
|
||||
gint64 frame2;
|
||||
gdouble fraction;
|
||||
gint64 frame_time;
|
||||
gdouble iteration, pulse_iterations, current_iterations, fraction;
|
||||
|
||||
frame2 = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
if (priv->frame1 == 0)
|
||||
priv->frame1 = frame2 - 16667;
|
||||
if (priv->pulse1 == 0)
|
||||
priv->pulse1 = priv->pulse2 - 250 * 1000000;
|
||||
if (priv->pulse2 == 0 && priv->pulse1 == 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker, frame_time);
|
||||
|
||||
g_assert (priv->pulse2 > priv->pulse1);
|
||||
g_assert (frame2 > priv->frame1);
|
||||
|
||||
if (frame2 - priv->pulse2 > 3 * (priv->pulse2 - priv->pulse1))
|
||||
{
|
||||
priv->pulse1 = 0;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
pulse_iterations = (priv->pulse2 - priv->pulse1) / (gdouble) G_USEC_PER_SEC;
|
||||
current_iterations = (frame_time - priv->pulse1) / (gdouble) G_USEC_PER_SEC;
|
||||
|
||||
iteration = gtk_progress_tracker_get_iteration (&priv->tracker);
|
||||
/* Determine the fraction to move the block from one frame
|
||||
* to the next when pulse_fraction is how far the block should
|
||||
* move between two calls to gtk_entry_progress_pulse().
|
||||
*/
|
||||
fraction = priv->progress_pulse_fraction * (frame2 - priv->frame1) / MAX (frame2 - priv->pulse2, priv->pulse2 - priv->pulse1);
|
||||
fraction = priv->progress_pulse_fraction * (iteration - priv->last_iteration) / MAX (pulse_iterations, current_iterations);
|
||||
priv->last_iteration = iteration;
|
||||
|
||||
priv->frame1 = frame2;
|
||||
if (current_iterations > 3 * pulse_iterations)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
/* advance the block */
|
||||
if (priv->progress_pulse_way_back)
|
||||
@@ -10483,6 +10484,9 @@ gtk_entry_start_pulse_mode (GtkEntry *entry)
|
||||
gtk_css_gadget_add_class (priv->progress_gadget, GTK_STYLE_CLASS_PULSE);
|
||||
|
||||
priv->progress_pulse_mode = TRUE;
|
||||
/* How long each pulse should last depends on calls to gtk_entry_progress_pulse.
|
||||
* Just start the tracker to repeat forever with iterations every second. */
|
||||
gtk_progress_tracker_start (&priv->tracker, G_USEC_PER_SEC, 0, INFINITY);
|
||||
priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (entry), tick_cb, NULL, NULL);
|
||||
|
||||
priv->progress_fraction = 0.0;
|
||||
@@ -10491,7 +10495,7 @@ gtk_entry_start_pulse_mode (GtkEntry *entry)
|
||||
|
||||
priv->pulse2 = 0;
|
||||
priv->pulse1 = 0;
|
||||
priv->frame1 = 0;
|
||||
priv->last_iteration = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -10514,9 +10518,13 @@ static void
|
||||
gtk_entry_update_pulse (GtkEntry *entry)
|
||||
{
|
||||
GtkEntryPrivate *priv = entry->priv;
|
||||
gint64 pulse_time = g_get_monotonic_time ();
|
||||
|
||||
if (priv->pulse2 == pulse_time)
|
||||
return;
|
||||
|
||||
priv->pulse1 = priv->pulse2;
|
||||
priv->pulse2 = g_get_monotonic_time ();
|
||||
priv->pulse2 = pulse_time;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -636,6 +636,7 @@ do_pre_parse_initialization (int *argc,
|
||||
char ***argv)
|
||||
{
|
||||
const gchar *env_string;
|
||||
double slowdown;
|
||||
|
||||
if (pre_initialized)
|
||||
return;
|
||||
@@ -673,6 +674,13 @@ do_pre_parse_initialization (int *argc,
|
||||
|
||||
g_string_append (gtk_modules_string, env_string);
|
||||
}
|
||||
|
||||
env_string = g_getenv ("GTK_SLOWDOWN");
|
||||
if (env_string)
|
||||
{
|
||||
slowdown = g_ascii_strtod (env_string, NULL);
|
||||
_gtk_set_slowdown (slowdown);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -110,6 +110,7 @@
|
||||
#include "gtkmenusectionbox.h"
|
||||
#include "gtkroundedboxprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include "wayland/gdkwayland.h"
|
||||
@@ -156,6 +157,7 @@ struct _GtkPopoverPrivate
|
||||
GtkAdjustment *hadj;
|
||||
GdkRectangle pointing_to;
|
||||
GtkPopoverConstraint constraint;
|
||||
GtkProgressTracker tracker;
|
||||
guint prev_focus_unmap_id;
|
||||
guint hierarchy_changed_id;
|
||||
guint size_allocate_id;
|
||||
@@ -173,7 +175,6 @@ struct _GtkPopoverPrivate
|
||||
guint transitions_enabled : 1;
|
||||
guint state : 2;
|
||||
guint visible : 1;
|
||||
gint64 start_time;
|
||||
gint transition_diff;
|
||||
guint tick_id;
|
||||
|
||||
@@ -510,17 +511,6 @@ gtk_popover_apply_modality (GtkPopover *popover,
|
||||
}
|
||||
}
|
||||
|
||||
/* From clutter-easing.c, based on Robert Penner's
|
||||
* infamous easing equations, MIT license.
|
||||
*/
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_animate_cb (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
@@ -528,15 +518,11 @@ show_animate_cb (GtkWidget *widget,
|
||||
{
|
||||
GtkPopover *popover = GTK_POPOVER (widget);
|
||||
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
|
||||
gint64 now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gdouble t;
|
||||
|
||||
if (now < (priv->start_time + TRANSITION_DURATION))
|
||||
t = (now - priv->start_time) / (gdouble) (TRANSITION_DURATION);
|
||||
else
|
||||
t = 1.0;
|
||||
|
||||
t = ease_out_cubic (t);
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker,
|
||||
gdk_frame_clock_get_frame_time (frame_clock));
|
||||
t = gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
|
||||
|
||||
if (priv->state == STATE_SHOWING)
|
||||
{
|
||||
@@ -551,7 +537,7 @@ show_animate_cb (GtkWidget *widget,
|
||||
|
||||
gtk_popover_update_position (popover);
|
||||
|
||||
if (t >= 1.0)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
if (priv->state == STATE_SHOWING)
|
||||
{
|
||||
@@ -573,13 +559,11 @@ static void
|
||||
gtk_popover_start_transition (GtkPopover *popover)
|
||||
{
|
||||
GtkPopoverPrivate *priv = popover->priv;
|
||||
GdkFrameClock *clock;
|
||||
|
||||
if (priv->tick_id != 0)
|
||||
return;
|
||||
|
||||
clock = gtk_widget_get_frame_clock (GTK_WIDGET (popover));
|
||||
priv->start_time = gdk_frame_clock_get_frame_time (clock);
|
||||
gtk_progress_tracker_start (&priv->tracker, TRANSITION_DURATION, 0, 1.0);
|
||||
priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (popover),
|
||||
show_animate_cb,
|
||||
popover, NULL);
|
||||
|
@@ -91,6 +91,10 @@ gboolean _gtk_propagate_captured_event (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GtkWidget *topmost);
|
||||
|
||||
|
||||
gdouble _gtk_get_slowdown ();
|
||||
void _gtk_set_slowdown (gdouble slowdown_factor);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
void _gtk_load_dll_with_libgtk3_manifest (const char *dllname);
|
||||
#endif
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkcsscustomgadgetprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#include "a11y/gtkprogressbaraccessible.h"
|
||||
|
||||
@@ -92,6 +93,7 @@
|
||||
#define MIN_VERTICAL_BAR_WIDTH 7
|
||||
#define MIN_VERTICAL_BAR_HEIGHT 80
|
||||
|
||||
#define DEFAULT_PULSE_DURATION 250000000
|
||||
|
||||
struct _GtkProgressBarPrivate
|
||||
{
|
||||
@@ -110,10 +112,11 @@ struct _GtkProgressBarPrivate
|
||||
|
||||
GtkOrientation orientation;
|
||||
|
||||
guint tick_id;
|
||||
gint64 pulse1;
|
||||
gint64 pulse2;
|
||||
gint64 frame1;
|
||||
guint tick_id;
|
||||
GtkProgressTracker tracker;
|
||||
gint64 pulse1;
|
||||
gint64 pulse2;
|
||||
gdouble last_iteration;
|
||||
|
||||
guint activity_dir : 1;
|
||||
guint activity_mode : 1;
|
||||
@@ -1142,31 +1145,30 @@ tick_cb (GtkWidget *widget,
|
||||
{
|
||||
GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget);
|
||||
GtkProgressBarPrivate *priv = pbar->priv;
|
||||
gint64 frame2;
|
||||
gdouble fraction;
|
||||
gint64 frame_time;
|
||||
gdouble iteration, pulse_iterations, current_iterations, fraction;
|
||||
|
||||
frame2 = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
if (priv->frame1 == 0)
|
||||
priv->frame1 = frame2 - 16667;
|
||||
if (priv->pulse1 == 0)
|
||||
priv->pulse1 = priv->pulse2 - 250 * 1000000;
|
||||
if (priv->pulse2 == 0 && priv->pulse1 == 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker, frame_time);
|
||||
|
||||
g_assert (priv->pulse2 > priv->pulse1);
|
||||
g_assert (frame2 > priv->frame1);
|
||||
|
||||
if (frame2 - priv->pulse2 > 3 * (priv->pulse2 - priv->pulse1))
|
||||
{
|
||||
priv->pulse1 = 0;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
pulse_iterations = (priv->pulse2 - priv->pulse1) / (gdouble) G_USEC_PER_SEC;
|
||||
current_iterations = (frame_time - priv->pulse1) / (gdouble) G_USEC_PER_SEC;
|
||||
|
||||
iteration = gtk_progress_tracker_get_iteration (&priv->tracker);
|
||||
/* Determine the fraction to move the block from one frame
|
||||
* to the next when pulse_fraction is how far the block should
|
||||
* move between two calls to gtk_progress_bar_pulse().
|
||||
*/
|
||||
fraction = priv->pulse_fraction * (frame2 - priv->frame1) / MAX (frame2 - priv->pulse2, priv->pulse2 - priv->pulse1);
|
||||
fraction = priv->pulse_fraction * (iteration - priv->last_iteration) / MAX (pulse_iterations, current_iterations);
|
||||
priv->last_iteration = iteration;
|
||||
|
||||
priv->frame1 = frame2;
|
||||
if (current_iterations > 3 * pulse_iterations)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
/* advance the block */
|
||||
if (priv->activity_dir == 0)
|
||||
@@ -1243,10 +1245,13 @@ gtk_progress_bar_act_mode_enter (GtkProgressBar *pbar)
|
||||
}
|
||||
|
||||
update_node_classes (pbar);
|
||||
/* No fixed schedule for pulses, will adapt after calls to update_pulse. Just
|
||||
* start the tracker to repeat forever with iterations every second.*/
|
||||
gtk_progress_tracker_start (&priv->tracker, G_USEC_PER_SEC, 0, INFINITY);
|
||||
priv->tick_id = gtk_widget_add_tick_callback (widget, tick_cb, NULL, NULL);
|
||||
priv->pulse2 = 0;
|
||||
priv->pulse1 = 0;
|
||||
priv->frame1 = 0;
|
||||
priv->last_iteration = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1406,9 +1411,13 @@ static void
|
||||
gtk_progress_bar_update_pulse (GtkProgressBar *pbar)
|
||||
{
|
||||
GtkProgressBarPrivate *priv = pbar->priv;
|
||||
gint64 pulse_time = g_get_monotonic_time ();
|
||||
|
||||
if (priv->pulse2 == pulse_time)
|
||||
return;
|
||||
|
||||
priv->pulse1 = priv->pulse2;
|
||||
priv->pulse2 = g_get_monotonic_time ();
|
||||
priv->pulse2 = pulse_time;
|
||||
}
|
||||
|
||||
/**
|
||||
|
268
gtk/gtkprogresstracker.c
Normal file
268
gtk/gtkprogresstracker.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright © 2016 Endless Mobile Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthew Watson <mattdangerw@gmail.com>
|
||||
*/
|
||||
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkcsseasevalueprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Progress tracker is small helper for tracking progress through gtk
|
||||
* animations. It's a simple zero-initable struct, meant to be thrown in a
|
||||
* widget's private data without the need for setup or teardown.
|
||||
*
|
||||
* Progress tracker will handle translating frame clock timestamps to a
|
||||
* fractional progress value for interpolating between animation targets.
|
||||
*
|
||||
* Progress tracker will use the GTK_SLOWDOWN environment variable to control
|
||||
* the speed of animations. This can be useful for debugging.
|
||||
*/
|
||||
|
||||
static gdouble gtk_slowdown = 1.0;
|
||||
|
||||
void
|
||||
_gtk_set_slowdown (gdouble factor)
|
||||
{
|
||||
gtk_slowdown = factor;
|
||||
}
|
||||
|
||||
gdouble
|
||||
_gtk_get_slowdown (gdouble factor)
|
||||
{
|
||||
return gtk_slowdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_init_copy:
|
||||
* @source: The source progress tracker
|
||||
* @dest: The destination progress tracker
|
||||
*
|
||||
* Copy all progress tracker state from the source tracker to dest tracker.
|
||||
**/
|
||||
void
|
||||
gtk_progress_tracker_init_copy (GtkProgressTracker *source,
|
||||
GtkProgressTracker *dest)
|
||||
{
|
||||
memcpy (dest, source, sizeof (GtkProgressTracker));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_start:
|
||||
* @tracker: The progress tracker
|
||||
* @duration: Animation duration in us
|
||||
* @delay: Animation delay in us
|
||||
* @iteration_count: Number of iterations to run the animation, must be >= 0
|
||||
*
|
||||
* Begins tracking progress for a new animation. Clears all previous state.
|
||||
**/
|
||||
void
|
||||
gtk_progress_tracker_start (GtkProgressTracker *tracker,
|
||||
guint64 duration,
|
||||
gint64 delay,
|
||||
gdouble iteration_count)
|
||||
{
|
||||
tracker->is_running = TRUE;
|
||||
tracker->last_frame_time = 0;
|
||||
tracker->duration = duration;
|
||||
tracker->iteration = - delay / (gdouble) duration;
|
||||
tracker->iteration_count = iteration_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_finish:
|
||||
* @tracker: The progress tracker
|
||||
*
|
||||
* Stops running the current animation.
|
||||
**/
|
||||
void
|
||||
gtk_progress_tracker_finish (GtkProgressTracker *tracker)
|
||||
{
|
||||
tracker->is_running = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_advance_frame:
|
||||
* @tracker: The progress tracker
|
||||
* @frame_time: The current frame time, usually from the frame clock.
|
||||
*
|
||||
* Increments the progress of the animation forward a frame. If no animation has
|
||||
* been started, does nothing.
|
||||
**/
|
||||
void
|
||||
gtk_progress_tracker_advance_frame (GtkProgressTracker *tracker,
|
||||
guint64 frame_time)
|
||||
{
|
||||
gdouble delta;
|
||||
|
||||
if (!tracker->is_running)
|
||||
return;
|
||||
|
||||
if (tracker->last_frame_time == 0)
|
||||
{
|
||||
tracker->last_frame_time = frame_time;
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame_time < tracker->last_frame_time)
|
||||
{
|
||||
g_warning ("Progress tracker frame set backwards, ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
delta = (frame_time - tracker->last_frame_time) / gtk_slowdown / tracker->duration;
|
||||
tracker->last_frame_time = frame_time;
|
||||
tracker->iteration += delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_skip_frame:
|
||||
* @tracker: The progress tracker
|
||||
* @frame_time: The current frame time, usually from the frame clock.
|
||||
*
|
||||
* Does not update the progress of the animation forward, but records the frame
|
||||
* to calculate future deltas. Calling this each frame will effectively pause
|
||||
* the animation.
|
||||
**/
|
||||
void
|
||||
gtk_progress_tracker_skip_frame (GtkProgressTracker *tracker,
|
||||
guint64 frame_time)
|
||||
{
|
||||
if (!tracker->is_running)
|
||||
return;
|
||||
|
||||
tracker->last_frame_time = frame_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_get_state:
|
||||
* @tracker: The progress tracker
|
||||
*
|
||||
* Returns whether the tracker is before, during or after the currently started
|
||||
* animation. The tracker will only ever be in the before state if the animation
|
||||
* was started with a delay. If no animation has been started, returns
|
||||
* %GTK_PROGRESS_STATE_AFTER.
|
||||
*
|
||||
* Returns: A GtkProgressState
|
||||
**/
|
||||
GtkProgressState
|
||||
gtk_progress_tracker_get_state (GtkProgressTracker *tracker)
|
||||
{
|
||||
if (!tracker->is_running || tracker->iteration > tracker->iteration_count)
|
||||
return GTK_PROGRESS_STATE_AFTER;
|
||||
if (tracker->iteration < 0)
|
||||
return GTK_PROGRESS_STATE_BEFORE;
|
||||
return GTK_PROGRESS_STATE_DURING;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_get_iteration:
|
||||
* @tracker: The progress tracker
|
||||
*
|
||||
* Returns the fractional number of cycles the animation has completed. For
|
||||
* example, it you started an animation with iteration-count of 2 and are half
|
||||
* way through the second animation, this returns 1.5.
|
||||
*
|
||||
* Returns: The current iteration.
|
||||
**/
|
||||
gdouble
|
||||
gtk_progress_tracker_get_iteration (GtkProgressTracker *tracker)
|
||||
{
|
||||
return tracker->is_running ? CLAMP (tracker->iteration, 0.0, tracker->iteration_count) : 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_get_iteration_cycle:
|
||||
* @tracker: The progress tracker
|
||||
*
|
||||
* Returns an integer index of the current iteration cycle tracker is
|
||||
* progressing through. Handles edge cases, such as an iteration value of 2.0
|
||||
* which could be considered the end of the second iteration of the beginning of
|
||||
* the third, in the same way as gtk_progress_tracker_get_progress().
|
||||
*
|
||||
* Returns: The integer count of the current animation cycle.
|
||||
**/
|
||||
guint64
|
||||
gtk_progress_tracker_get_iteration_cycle (GtkProgressTracker *tracker)
|
||||
{
|
||||
gdouble iteration = gtk_progress_tracker_get_iteration (tracker);
|
||||
|
||||
/* Some complexity here. We want an iteration of 0.0 to always map to 0 (start
|
||||
* of the first iteration), but an iteration of 1.0 to also map to 0 (end of
|
||||
* first iteration) and 2.0 to 1 (end of the second iteration).
|
||||
*/
|
||||
if (iteration == 0.0)
|
||||
return 0;
|
||||
|
||||
return (guint64) ceil (iteration) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_get_progress:
|
||||
* @tracker: The progress tracker
|
||||
* @reversed: If progress should be reversed.
|
||||
*
|
||||
* Gets the progress through the current animation iteration, from [0, 1]. Use
|
||||
* to interpolate between animation targets. If reverse is true each iteration
|
||||
* will begin at 1 and end at 0.
|
||||
*
|
||||
* Returns: The progress value.
|
||||
**/
|
||||
gdouble
|
||||
gtk_progress_tracker_get_progress (GtkProgressTracker *tracker,
|
||||
gboolean reversed)
|
||||
{
|
||||
gdouble progress, iteration;
|
||||
guint64 iteration_cycle;
|
||||
|
||||
iteration = gtk_progress_tracker_get_iteration (tracker);
|
||||
iteration_cycle = gtk_progress_tracker_get_iteration_cycle (tracker);
|
||||
|
||||
progress = iteration - iteration_cycle;
|
||||
return reversed ? 1.0 - progress : progress;
|
||||
}
|
||||
|
||||
/* From clutter-easing.c, based on Robert Penner's
|
||||
* infamous easing equations, MIT license.
|
||||
*/
|
||||
static gdouble
|
||||
ease_out_cubic (gdouble t)
|
||||
{
|
||||
gdouble p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_progress_tracker_get_ease_out_cubic:
|
||||
* @tracker: The progress tracker
|
||||
* @reversed: If progress should be reversed before applying the ease function.
|
||||
*
|
||||
* Applies a simple ease out cubic function to the result of
|
||||
* gtk_progress_tracker_get_progress().
|
||||
*
|
||||
* Returns: The eased progress value.
|
||||
**/
|
||||
gdouble
|
||||
gtk_progress_tracker_get_ease_out_cubic (GtkProgressTracker *tracker,
|
||||
gboolean reversed)
|
||||
{
|
||||
gdouble progress = gtk_progress_tracker_get_progress (tracker, reversed);
|
||||
return ease_out_cubic (progress);
|
||||
}
|
75
gtk/gtkprogresstrackerprivate.h
Normal file
75
gtk/gtkprogresstrackerprivate.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright © 2016 Endless Mobile Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthew Watson <mattdangerw@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PROGRESS_TRACKER_PRIVATE_H__
|
||||
#define __GTK_PROGRESS_TRACKER_PRIVATE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "gtkcsseasevalueprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GTK_PROGRESS_STATE_BEFORE,
|
||||
GTK_PROGRESS_STATE_DURING,
|
||||
GTK_PROGRESS_STATE_AFTER,
|
||||
} GtkProgressState;
|
||||
|
||||
typedef struct _GtkProgressTracker GtkProgressTracker;
|
||||
|
||||
struct _GtkProgressTracker
|
||||
{
|
||||
gboolean is_running;
|
||||
guint64 last_frame_time;
|
||||
guint64 duration;
|
||||
gdouble iteration;
|
||||
gdouble iteration_count;
|
||||
};
|
||||
|
||||
void gtk_progress_tracker_init_copy (GtkProgressTracker *source,
|
||||
GtkProgressTracker *dest);
|
||||
|
||||
void gtk_progress_tracker_start (GtkProgressTracker *tracker,
|
||||
guint64 duration,
|
||||
gint64 delay,
|
||||
gdouble iteration_count);
|
||||
|
||||
void gtk_progress_tracker_finish (GtkProgressTracker *tracker);
|
||||
|
||||
void gtk_progress_tracker_advance_frame (GtkProgressTracker *tracker,
|
||||
guint64 frame_time);
|
||||
|
||||
void gtk_progress_tracker_skip_frame (GtkProgressTracker *tracker,
|
||||
guint64 frame_time);
|
||||
|
||||
GtkProgressState gtk_progress_tracker_get_state (GtkProgressTracker *tracker);
|
||||
|
||||
gdouble gtk_progress_tracker_get_iteration (GtkProgressTracker *tracker);
|
||||
|
||||
guint64 gtk_progress_tracker_get_iteration_cycle (GtkProgressTracker *tracker);
|
||||
|
||||
gdouble gtk_progress_tracker_get_progress (GtkProgressTracker *tracker,
|
||||
gboolean reverse);
|
||||
|
||||
gdouble gtk_progress_tracker_get_ease_out_cubic (GtkProgressTracker *tracker,
|
||||
gboolean reverse);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PROGRESS_TRACKER_PRIVATE_H__ */
|
@@ -25,6 +25,7 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
#include "fallback-c89.c"
|
||||
@@ -85,8 +86,7 @@ typedef struct {
|
||||
gdouble target_pos;
|
||||
|
||||
guint tick_id;
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
GtkProgressTracker tracker;
|
||||
} GtkRevealerPrivate;
|
||||
|
||||
static GParamSpec *props[LAST_PROP] = { NULL, };
|
||||
@@ -568,33 +568,6 @@ gtk_revealer_set_position (GtkRevealer *revealer,
|
||||
g_object_notify_by_pspec (G_OBJECT (revealer), props[PROP_CHILD_REVEALED]);
|
||||
}
|
||||
|
||||
/* From clutter-easing.c, based on Robert Penner's
|
||||
* infamous easing equations, MIT license.
|
||||
*/
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_revealer_animate_step (GtkRevealer *revealer,
|
||||
gint64 now)
|
||||
{
|
||||
GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
|
||||
gdouble t;
|
||||
|
||||
if (now < priv->end_time)
|
||||
t = (now - priv->start_time) / (gdouble) (priv->end_time - priv->start_time);
|
||||
else
|
||||
t = 1.0;
|
||||
t = ease_out_cubic (t);
|
||||
|
||||
gtk_revealer_set_position (revealer,
|
||||
priv->source_pos + (t * (priv->target_pos - priv->source_pos)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_revealer_animate_cb (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
@@ -602,11 +575,15 @@ gtk_revealer_animate_cb (GtkWidget *widget,
|
||||
{
|
||||
GtkRevealer *revealer = GTK_REVEALER (widget);
|
||||
GtkRevealerPrivate *priv = gtk_revealer_get_instance_private (revealer);
|
||||
gint64 now;
|
||||
gdouble ease;
|
||||
|
||||
now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
gtk_revealer_animate_step (revealer, now);
|
||||
if (priv->current_pos == priv->target_pos)
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker,
|
||||
gdk_frame_clock_get_frame_time (frame_clock));
|
||||
ease = gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
|
||||
gtk_revealer_set_position (revealer,
|
||||
priv->source_pos + (ease * (priv->target_pos - priv->source_pos)));
|
||||
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
priv->tick_id = 0;
|
||||
return FALSE;
|
||||
@@ -641,12 +618,13 @@ gtk_revealer_start_animation (GtkRevealer *revealer,
|
||||
animations_enabled)
|
||||
{
|
||||
priv->source_pos = priv->current_pos;
|
||||
priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
|
||||
priv->end_time = priv->start_time + (priv->transition_duration * 1000);
|
||||
if (priv->tick_id == 0)
|
||||
priv->tick_id =
|
||||
gtk_widget_add_tick_callback (widget, gtk_revealer_animate_cb, revealer, NULL);
|
||||
gtk_revealer_animate_step (revealer, priv->start_time);
|
||||
gtk_progress_tracker_start (&priv->tracker,
|
||||
priv->transition_duration * 1000,
|
||||
0,
|
||||
1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -45,6 +45,7 @@
|
||||
#include "gtkkineticscrolling.h"
|
||||
#include "a11y/gtkscrolledwindowaccessible.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -193,8 +194,7 @@ typedef struct
|
||||
gdouble current_pos;
|
||||
gdouble source_pos;
|
||||
gdouble target_pos;
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
GtkProgressTracker tracker;
|
||||
guint tick_id;
|
||||
guint over_timeout_id;
|
||||
} Indicator;
|
||||
@@ -4002,40 +4002,22 @@ indicator_set_fade (Indicator *indicator,
|
||||
}
|
||||
}
|
||||
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
indicator_fade_step (Indicator *indicator,
|
||||
gint64 now)
|
||||
{
|
||||
gdouble t;
|
||||
|
||||
if (now < indicator->end_time)
|
||||
t = (now - indicator->start_time) / (gdouble) (indicator->end_time - indicator->start_time);
|
||||
else
|
||||
t = 1.0;
|
||||
t = ease_out_cubic (t);
|
||||
|
||||
indicator_set_fade (indicator,
|
||||
indicator->source_pos + (t * (indicator->target_pos - indicator->source_pos)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
indicator_fade_cb (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
Indicator *indicator = user_data;
|
||||
gint64 now;
|
||||
gdouble t;
|
||||
|
||||
now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
indicator_fade_step (indicator, now);
|
||||
if (indicator->current_pos == indicator->target_pos)
|
||||
gtk_progress_tracker_advance_frame (&indicator->tracker,
|
||||
gdk_frame_clock_get_frame_time (frame_clock));
|
||||
t = gtk_progress_tracker_get_ease_out_cubic (&indicator->tracker, FALSE);
|
||||
|
||||
indicator_set_fade (indicator,
|
||||
indicator->source_pos + (t * (indicator->target_pos - indicator->source_pos)));
|
||||
|
||||
if (gtk_progress_tracker_get_state (&indicator->tracker) == GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
indicator->tick_id = 0;
|
||||
return FALSE;
|
||||
@@ -4065,12 +4047,9 @@ indicator_start_fade (Indicator *indicator,
|
||||
if (gtk_widget_get_mapped (indicator->scrollbar) && animations_enabled)
|
||||
{
|
||||
indicator->source_pos = indicator->current_pos;
|
||||
indicator->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (indicator->scrollbar));
|
||||
indicator->end_time = indicator->start_time + INDICATOR_FADE_OUT_DURATION * 1000;
|
||||
gtk_progress_tracker_start (&indicator->tracker, INDICATOR_FADE_OUT_DURATION * 1000, 0, 1.0);
|
||||
if (indicator->tick_id == 0)
|
||||
indicator->tick_id = gtk_widget_add_tick_callback (indicator->scrollbar, indicator_fade_cb, indicator, NULL);
|
||||
|
||||
indicator_fade_step (indicator, indicator->start_time);
|
||||
}
|
||||
else
|
||||
indicator_set_fade (indicator, target);
|
||||
@@ -4093,8 +4072,9 @@ indicator_stop_fade (Indicator *indicator)
|
||||
}
|
||||
|
||||
gdk_window_hide (indicator->window);
|
||||
gtk_progress_tracker_finish (&indicator->tracker);
|
||||
indicator->current_pos = indicator->source_pos = indicator->target_pos = 0;
|
||||
indicator->start_time = indicator->end_time = indicator->last_scroll_time = 0;
|
||||
indicator->last_scroll_time = 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -4297,8 +4277,9 @@ indicator_reset (Indicator *indicator)
|
||||
|
||||
indicator->scrollbar = NULL;
|
||||
indicator->over = FALSE;
|
||||
gtk_progress_tracker_finish (&indicator->tracker);
|
||||
indicator->current_pos = indicator->source_pos = indicator->target_pos = 0;
|
||||
indicator->start_time = indicator->end_time = indicator->last_scroll_time = 0;
|
||||
indicator->last_scroll_time = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtkcsscustomgadgetprivate.h"
|
||||
#include "gtkcontainerprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
@@ -143,10 +144,9 @@ typedef struct {
|
||||
GtkStackChildInfo *last_visible_child;
|
||||
cairo_surface_t *last_visible_surface;
|
||||
GtkAllocation last_visible_surface_allocation;
|
||||
gdouble transition_pos;
|
||||
guint tick_id;
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
GtkProgressTracker tracker;
|
||||
gboolean first_frame_skipped;
|
||||
|
||||
gint last_visible_widget_width;
|
||||
gint last_visible_widget_height;
|
||||
@@ -765,16 +765,6 @@ gtk_stack_set_child_property (GtkContainer *container,
|
||||
}
|
||||
}
|
||||
|
||||
/* From clutter-easing.c, based on Robert Penner's
|
||||
* infamous easing equations, MIT license.
|
||||
*/
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_left_transition (GtkStackTransitionType transition_type)
|
||||
{
|
||||
@@ -863,12 +853,12 @@ get_bin_window_x (GtkStack *stack,
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
int x = 0;
|
||||
|
||||
if (priv->transition_pos < 1.0)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
if (is_left_transition (priv->active_transition_type))
|
||||
x = allocation->width * (1 - ease_out_cubic (priv->transition_pos));
|
||||
x = allocation->width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
if (is_right_transition (priv->active_transition_type))
|
||||
x = -allocation->width * (1 - ease_out_cubic (priv->transition_pos));
|
||||
x = -allocation->width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
}
|
||||
|
||||
return x;
|
||||
@@ -881,25 +871,22 @@ get_bin_window_y (GtkStack *stack,
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
int y = 0;
|
||||
|
||||
if (priv->transition_pos < 1.0)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
if (is_up_transition (priv->active_transition_type))
|
||||
y = allocation->height * (1 - ease_out_cubic (priv->transition_pos));
|
||||
y = allocation->height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
if (is_down_transition(priv->active_transition_type))
|
||||
y = -allocation->height * (1 - ease_out_cubic (priv->transition_pos));
|
||||
y = -allocation->height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_stack_set_transition_position (GtkStack *stack,
|
||||
gdouble pos)
|
||||
static void
|
||||
gtk_stack_progress_updated (GtkStack *stack)
|
||||
{
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
gboolean done;
|
||||
|
||||
priv->transition_pos = pos;
|
||||
gtk_widget_queue_draw (GTK_WIDGET (stack));
|
||||
|
||||
if (!priv->vhomogeneous || !priv->hhomogeneous)
|
||||
@@ -914,9 +901,7 @@ gtk_stack_set_transition_position (GtkStack *stack,
|
||||
get_bin_window_x (stack, &allocation), get_bin_window_y (stack, &allocation));
|
||||
}
|
||||
|
||||
done = pos >= 1.0;
|
||||
|
||||
if (done)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
if (priv->last_visible_surface != NULL)
|
||||
{
|
||||
@@ -930,8 +915,6 @@ gtk_stack_set_transition_position (GtkStack *stack,
|
||||
priv->last_visible_child = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -941,20 +924,20 @@ gtk_stack_transition_cb (GtkWidget *widget,
|
||||
{
|
||||
GtkStack *stack = GTK_STACK (widget);
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
gint64 now;
|
||||
gdouble t;
|
||||
|
||||
now = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
t = 1.0;
|
||||
if (now < priv->end_time)
|
||||
t = (now - priv->start_time) / (double) (priv->end_time - priv->start_time);
|
||||
if (priv->first_frame_skipped)
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker,
|
||||
gdk_frame_clock_get_frame_time (frame_clock));
|
||||
else
|
||||
priv->first_frame_skipped = TRUE;
|
||||
|
||||
/* Finish animation early if not mapped anymore */
|
||||
if (!gtk_widget_get_mapped (widget))
|
||||
t = 1.0;
|
||||
gtk_progress_tracker_finish (&priv->tracker);
|
||||
|
||||
if (gtk_stack_set_transition_position (stack, t))
|
||||
gtk_stack_progress_updated (GTK_STACK (widget));
|
||||
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
priv->tick_id = 0;
|
||||
g_object_notify_by_pspec (G_OBJECT (stack), stack_props[PROP_TRANSITION_RUNNING]);
|
||||
@@ -1037,17 +1020,20 @@ gtk_stack_start_transition (GtkStack *stack,
|
||||
transition_duration != 0 &&
|
||||
priv->last_visible_child != NULL)
|
||||
{
|
||||
priv->transition_pos = 0.0;
|
||||
priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
|
||||
priv->end_time = priv->start_time + (transition_duration * 1000);
|
||||
priv->active_transition_type = effective_transition_type (stack, transition_type);
|
||||
priv->first_frame_skipped = FALSE;
|
||||
gtk_stack_schedule_ticks (stack);
|
||||
gtk_progress_tracker_start (&priv->tracker,
|
||||
priv->transition_duration * 1000,
|
||||
0,
|
||||
1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_stack_unschedule_ticks (stack);
|
||||
priv->active_transition_type = GTK_STACK_TRANSITION_TYPE_NONE;
|
||||
gtk_stack_set_transition_position (stack, 1.0);
|
||||
gtk_progress_tracker_finish (&priv->tracker);
|
||||
gtk_stack_progress_updated (GTK_STACK (widget));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1962,6 +1948,7 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
|
||||
{
|
||||
GtkStack *stack = GTK_STACK (widget);
|
||||
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
|
||||
gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
|
||||
|
||||
cairo_push_group (cr);
|
||||
gtk_container_propagate_draw (GTK_CONTAINER (stack),
|
||||
@@ -1969,8 +1956,8 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
|
||||
cr);
|
||||
cairo_save (cr);
|
||||
|
||||
/* Multiply alpha by transition pos */
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, priv->transition_pos);
|
||||
/* Multiply alpha by progress */
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, progress);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN);
|
||||
cairo_paint (cr);
|
||||
|
||||
@@ -1980,7 +1967,7 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
|
||||
priv->last_visible_surface_allocation.x,
|
||||
priv->last_visible_surface_allocation.y);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
|
||||
cairo_paint_with_alpha (cr, MAX (1.0 - priv->transition_pos, 0));
|
||||
cairo_paint_with_alpha (cr, MAX (1.0 - progress, 0));
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
@@ -2009,22 +1996,22 @@ gtk_stack_draw_under (GtkWidget *widget,
|
||||
{
|
||||
case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
|
||||
y = 0;
|
||||
height = allocation.height * (ease_out_cubic (priv->transition_pos));
|
||||
height = allocation.height * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
pos_y = height;
|
||||
break;
|
||||
case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
|
||||
y = allocation.height * (1 - ease_out_cubic (priv->transition_pos));
|
||||
y = allocation.height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
height = allocation.height - y;
|
||||
pos_y = y - allocation.height;
|
||||
break;
|
||||
case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
|
||||
x = allocation.width * (1 - ease_out_cubic (priv->transition_pos));
|
||||
x = allocation.width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
width = allocation.width - x;
|
||||
pos_x = x - allocation.width;
|
||||
break;
|
||||
case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
|
||||
x = 0;
|
||||
width = allocation.width * (ease_out_cubic (priv->transition_pos));
|
||||
width = allocation.width * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
|
||||
pos_x = width;
|
||||
break;
|
||||
default:
|
||||
@@ -2155,7 +2142,7 @@ gtk_stack_render (GtkCssGadget *gadget,
|
||||
|
||||
if (priv->visible_child)
|
||||
{
|
||||
if (priv->transition_pos < 1.0)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
if (priv->last_visible_surface == NULL &&
|
||||
priv->last_visible_child != NULL)
|
||||
@@ -2428,13 +2415,13 @@ gtk_stack_measure (GtkCssGadget *gadget,
|
||||
{
|
||||
if (orientation == GTK_ORIENTATION_VERTICAL && !priv->vhomogeneous)
|
||||
{
|
||||
gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 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)
|
||||
{
|
||||
gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 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);
|
||||
}
|
||||
|
@@ -23,23 +23,27 @@
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GtkStyleAnimation, _gtk_style_animation, G_TYPE_OBJECT)
|
||||
|
||||
static GtkStyleAnimation *
|
||||
gtk_style_animation_real_advance (GtkStyleAnimation *animation,
|
||||
gint64 timestamp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_style_animation_real_set_values (GtkStyleAnimation *animation,
|
||||
gint64 for_time_us,
|
||||
GtkCssAnimatedStyle *style)
|
||||
gtk_style_animation_real_apply_values (GtkStyleAnimation *animation,
|
||||
GtkCssAnimatedStyle *style)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_style_animation_real_is_finished (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
gtk_style_animation_real_is_finished (GtkStyleAnimation *animation)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_style_animation_real_is_static (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
gtk_style_animation_real_is_static (GtkStyleAnimation *animation)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -47,7 +51,8 @@ gtk_style_animation_real_is_static (GtkStyleAnimation *animation,
|
||||
static void
|
||||
_gtk_style_animation_class_init (GtkStyleAnimationClass *klass)
|
||||
{
|
||||
klass->set_values = gtk_style_animation_real_set_values;
|
||||
klass->advance = gtk_style_animation_real_advance;
|
||||
klass->apply_values = gtk_style_animation_real_apply_values;
|
||||
klass->is_finished = gtk_style_animation_real_is_finished;
|
||||
klass->is_static = gtk_style_animation_real_is_static;
|
||||
}
|
||||
@@ -57,10 +62,22 @@ _gtk_style_animation_init (GtkStyleAnimation *animation)
|
||||
{
|
||||
}
|
||||
|
||||
GtkStyleAnimation *
|
||||
_gtk_style_animation_advance (GtkStyleAnimation *animation,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GtkStyleAnimationClass *klass;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_STYLE_ANIMATION (animation), NULL);
|
||||
|
||||
klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
|
||||
|
||||
return klass->advance (animation, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_style_animation_set_values (GtkStyleAnimation *animation,
|
||||
gint64 for_time_us,
|
||||
GtkCssAnimatedStyle *style)
|
||||
_gtk_style_animation_apply_values (GtkStyleAnimation *animation,
|
||||
GtkCssAnimatedStyle *style)
|
||||
{
|
||||
GtkStyleAnimationClass *klass;
|
||||
|
||||
@@ -69,12 +86,11 @@ _gtk_style_animation_set_values (GtkStyleAnimation *animation,
|
||||
|
||||
klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
|
||||
|
||||
klass->set_values (animation, for_time_us, style);
|
||||
klass->apply_values (animation, style);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_style_animation_is_finished (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
_gtk_style_animation_is_finished (GtkStyleAnimation *animation)
|
||||
{
|
||||
GtkStyleAnimationClass *klass;
|
||||
|
||||
@@ -82,7 +98,7 @@ _gtk_style_animation_is_finished (GtkStyleAnimation *animation,
|
||||
|
||||
klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
|
||||
|
||||
return klass->is_finished (animation, at_time_us);
|
||||
return klass->is_finished (animation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,8 +113,7 @@ _gtk_style_animation_is_finished (GtkStyleAnimation *animation,
|
||||
* Returns: %TRUE if @animation will not change anymore after @at_time_us
|
||||
**/
|
||||
gboolean
|
||||
_gtk_style_animation_is_static (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us)
|
||||
_gtk_style_animation_is_static (GtkStyleAnimation *animation)
|
||||
{
|
||||
GtkStyleAnimationClass *klass;
|
||||
|
||||
@@ -106,5 +121,5 @@ _gtk_style_animation_is_static (GtkStyleAnimation *animation,
|
||||
|
||||
klass = GTK_STYLE_ANIMATION_GET_CLASS (animation);
|
||||
|
||||
return klass->is_static (animation, at_time_us);
|
||||
return klass->is_static (animation);
|
||||
}
|
||||
|
@@ -43,24 +43,22 @@ struct _GtkStyleAnimationClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* is_finished) (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us);
|
||||
gboolean (* is_static) (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us);
|
||||
void (* set_values) (GtkStyleAnimation *animation,
|
||||
gint64 for_time_us,
|
||||
gboolean (* is_finished) (GtkStyleAnimation *animation);
|
||||
gboolean (* is_static) (GtkStyleAnimation *animation);
|
||||
void (* apply_values) (GtkStyleAnimation *animation,
|
||||
GtkCssAnimatedStyle *style);
|
||||
GtkStyleAnimation * (* advance) (GtkStyleAnimation *animation,
|
||||
gint64 timestamp);
|
||||
};
|
||||
|
||||
GType _gtk_style_animation_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _gtk_style_animation_set_values (GtkStyleAnimation *animation,
|
||||
gint64 for_time_us,
|
||||
GtkStyleAnimation * _gtk_style_animation_advance (GtkStyleAnimation *animation,
|
||||
gint64 timestamp);
|
||||
void _gtk_style_animation_apply_values (GtkStyleAnimation *animation,
|
||||
GtkCssAnimatedStyle *style);
|
||||
gboolean _gtk_style_animation_is_finished (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us);
|
||||
gboolean _gtk_style_animation_is_static (GtkStyleAnimation *animation,
|
||||
gint64 at_time_us);
|
||||
gboolean _gtk_style_animation_is_finished (GtkStyleAnimation *animation);
|
||||
gboolean _gtk_style_animation_is_static (GtkStyleAnimation *animation);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -67,6 +67,7 @@
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkcssshadowsvalueprivate.h"
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include "gtkprogresstrackerprivate.h"
|
||||
|
||||
#include "fallback-c89.c"
|
||||
|
||||
@@ -86,9 +87,8 @@ struct _GtkSwitchPrivate
|
||||
GtkCssGadget *slider_gadget;
|
||||
|
||||
double handle_pos;
|
||||
gint64 start_time;
|
||||
gint64 end_time;
|
||||
guint tick_id;
|
||||
GtkProgressTracker tracker;
|
||||
|
||||
guint state : 1;
|
||||
guint is_active : 1;
|
||||
@@ -131,17 +131,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkSwitch, gtk_switch, GTK_TYPE_WIDGET,
|
||||
gtk_switch_activatable_interface_init));
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
/* From clutter-easing.c, based on Robert Penner's
|
||||
* infamous easing equations, MIT license.
|
||||
*/
|
||||
static gdouble
|
||||
ease_out_cubic (gdouble t)
|
||||
{
|
||||
gdouble p = t - 1;
|
||||
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_switch_end_toggle_animation (GtkSwitch *sw)
|
||||
{
|
||||
@@ -161,20 +150,16 @@ gtk_switch_on_frame_clock_update (GtkWidget *widget,
|
||||
{
|
||||
GtkSwitch *sw = GTK_SWITCH (widget);
|
||||
GtkSwitchPrivate *priv = sw->priv;
|
||||
gint64 now;
|
||||
|
||||
now = gdk_frame_clock_get_frame_time (clock);
|
||||
gtk_progress_tracker_advance_frame (&priv->tracker,
|
||||
gdk_frame_clock_get_frame_time (clock));
|
||||
|
||||
if (now < priv->end_time)
|
||||
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
|
||||
{
|
||||
gdouble t;
|
||||
|
||||
t = (now - priv->start_time) / (gdouble) (priv->end_time - priv->start_time);
|
||||
t = ease_out_cubic (t);
|
||||
if (priv->is_active)
|
||||
priv->handle_pos = 1.0 - t;
|
||||
priv->handle_pos = 1.0 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
|
||||
else
|
||||
priv->handle_pos = t;
|
||||
priv->handle_pos = gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -200,9 +185,7 @@ gtk_switch_begin_toggle_animation (GtkSwitch *sw)
|
||||
|
||||
if (animate)
|
||||
{
|
||||
GdkFrameClock *clock = gtk_widget_get_frame_clock (GTK_WIDGET (sw));
|
||||
priv->start_time = gdk_frame_clock_get_frame_time (clock);
|
||||
priv->end_time = priv->start_time + 1000 * ANIMATION_DURATION;
|
||||
gtk_progress_tracker_start (&priv->tracker, 1000 * ANIMATION_DURATION, 0, 1.0);
|
||||
if (priv->tick_id == 0)
|
||||
priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (sw),
|
||||
gtk_switch_on_frame_clock_update,
|
||||
|
@@ -31,12 +31,16 @@
|
||||
#include "gtkwindow.h"
|
||||
#include "gtkcssproviderprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include "x11/gdkx.h"
|
||||
#endif
|
||||
|
||||
#include "gdk/gdk-private.h"
|
||||
|
||||
#define EPSILON 1e-10
|
||||
|
||||
struct _GtkInspectorVisualPrivate
|
||||
{
|
||||
GtkWidget *visual_box;
|
||||
@@ -51,6 +55,8 @@ struct _GtkInspectorVisualPrivate
|
||||
GtkWidget *animation_switch;
|
||||
GtkWidget *font_scale_scale;
|
||||
GtkAdjustment *scale_adjustment;
|
||||
GtkAdjustment *slowdown_adjustment;
|
||||
GtkWidget *slowdown_entry;
|
||||
GtkAdjustment *cursor_size_adjustment;
|
||||
GtkAdjustment *font_scale_adjustment;
|
||||
|
||||
@@ -561,6 +567,62 @@ init_animation (GtkInspectorVisual *vis)
|
||||
G_BINDING_BIDIRECTIONAL|G_BINDING_SYNC_CREATE);
|
||||
}
|
||||
|
||||
static void
|
||||
update_slowdown (GtkInspectorVisual *vis,
|
||||
gdouble slowdown,
|
||||
gboolean update_adjustment,
|
||||
gboolean update_entry)
|
||||
{
|
||||
_gtk_set_slowdown (slowdown);
|
||||
|
||||
if (update_adjustment)
|
||||
gtk_adjustment_set_value (vis->priv->slowdown_adjustment,
|
||||
log2 (slowdown));
|
||||
|
||||
if (update_entry)
|
||||
{
|
||||
gchar *str = g_strdup_printf ("%0.*f", 2, slowdown);
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (vis->priv->slowdown_entry), str);
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
slowdown_adjustment_changed (GtkAdjustment *adjustment,
|
||||
GtkInspectorVisual *vis)
|
||||
{
|
||||
gdouble value = gtk_adjustment_get_value (adjustment);
|
||||
gdouble previous = CLAMP (log2 (_gtk_get_slowdown ()),
|
||||
gtk_adjustment_get_lower (adjustment),
|
||||
gtk_adjustment_get_upper (adjustment));
|
||||
|
||||
if (fabs (value - previous) > EPSILON)
|
||||
update_slowdown (vis, exp2 (value), FALSE, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
slowdown_entry_activated (GtkEntry *entry,
|
||||
GtkInspectorVisual *vis)
|
||||
{
|
||||
gdouble slowdown;
|
||||
gchar *err = NULL;
|
||||
|
||||
slowdown = g_strtod (gtk_entry_get_text (entry), &err);
|
||||
if (err != NULL)
|
||||
update_slowdown (vis, slowdown, TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
init_slowdown (GtkInspectorVisual *vis)
|
||||
{
|
||||
update_slowdown (vis, _gtk_get_slowdown (), TRUE, TRUE);
|
||||
g_signal_connect (vis->priv->slowdown_adjustment, "value-changed",
|
||||
G_CALLBACK (slowdown_adjustment_changed), vis);
|
||||
g_signal_connect (vis->priv->slowdown_entry, "activate",
|
||||
G_CALLBACK (slowdown_entry_activated), vis);
|
||||
}
|
||||
|
||||
static void
|
||||
update_touchscreen (GtkSwitch *sw)
|
||||
{
|
||||
@@ -743,6 +805,7 @@ gtk_inspector_visual_init (GtkInspectorVisual *vis)
|
||||
init_rendering_mode (vis);
|
||||
init_updates (vis);
|
||||
init_animation (vis);
|
||||
init_slowdown (vis);
|
||||
init_touchscreen (vis);
|
||||
init_gl (vis);
|
||||
}
|
||||
@@ -786,6 +849,8 @@ gtk_inspector_visual_class_init (GtkInspectorVisualClass *klass)
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, hidpi_spin);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, scale_adjustment);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, animation_switch);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, slowdown_adjustment);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, slowdown_entry);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, touchscreen_switch);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, visual_box);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorVisual, debug_box);
|
||||
|
@@ -12,6 +12,12 @@
|
||||
<property name="step-increment">0.01</property>
|
||||
<property name="page-increment">0.01</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="slowdown_adjustment">
|
||||
<property name="lower">-3</property>
|
||||
<property name="upper">3</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="cursor_size_adjustment">
|
||||
<property name="lower">24</property>
|
||||
<property name="upper">64</property>
|
||||
@@ -382,6 +388,50 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="visible">True</property>
|
||||
<property name="activatable">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="margin">10</property>
|
||||
<property name="spacing">20</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="slowdown_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Slowdown</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="xalign">0.0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="slowdown_scale">
|
||||
<property name="visible">1</property>
|
||||
<property name="can_focus">1</property>
|
||||
<property name="adjustment">slowdown_adjustment</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="draw_value">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="slowdown_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="width-chars">4</property>
|
||||
<property name="input-purpose">number</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
Reference in New Issue
Block a user