mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 18:30:08 +00:00
Add gdk_frame_clock_begin/end_updating()
Add an API to start or stop continually updating the frame clock. This is a slight convenience for applcations and avoids the problem of getting one more frame run after an animation stops, but the primary motivation for this is because it looks like we might have to use timeBeginPeriod()/timeEndPeriod() on Windows to get reasonably accurate timing, and for that we'll need to know if there is an animation running. https://bugzilla.gnome.org/show_bug.cgi?id=693934
This commit is contained in:
parent
1da329b2bd
commit
1db87c897f
@ -188,6 +188,8 @@ gdk_events_pending
|
||||
gdk_event_type_get_type
|
||||
gdk_filter_return_get_type
|
||||
gdk_flush
|
||||
gdk_frame_clock_begin_updating
|
||||
gdk_frame_clock_end_updating
|
||||
gdk_frame_clock_get_current_timings
|
||||
gdk_frame_clock_get_frame_counter
|
||||
gdk_frame_clock_get_frame_time
|
||||
|
@ -285,7 +285,12 @@ gdk_frame_clock_get_frame_time (GdkFrameClock *frame_clock)
|
||||
* corresponding the requested phase will be emitted the next
|
||||
* time the frame clock processes. Multiple calls to
|
||||
* gdk_frame_clock_request_phase() will be combined togethe
|
||||
* and only one frame processed.
|
||||
* and only one frame processed. If you are displaying animated
|
||||
* content and want to continually request the
|
||||
* %GDK_FRAME_CLOCK_PHASE_UPDATE phase for a period of time,
|
||||
* you should use gdk_frame_clock_begin_updating() instead, since
|
||||
* this allows GTK+ to adjust system parameters to get maximally
|
||||
* smooth animations.
|
||||
*
|
||||
* Since: 3.8
|
||||
*/
|
||||
@ -298,6 +303,43 @@ gdk_frame_clock_request_phase (GdkFrameClock *frame_clock,
|
||||
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->request_phase (frame_clock, phase);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_frame_clock_begin_updating:
|
||||
* @frame_clock: a #GdkFrameClock
|
||||
*
|
||||
* Starts updates for an animation. Until a matching call to
|
||||
* gdk_frame_clock_end_updating() is made, the frame clock will continually
|
||||
* request a new frame with the %GDK_FRAME_CLOCK_PHASE_UPDATE phase.
|
||||
* This function may be called multiple times and frames will be
|
||||
* requested until gdk_frame_clock_end_updating() is called the same
|
||||
* number of times.
|
||||
*
|
||||
* Since: 3.8
|
||||
*/
|
||||
void
|
||||
gdk_frame_clock_begin_updating (GdkFrameClock *frame_clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->begin_updating (frame_clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_frame_clock_end_updating:
|
||||
* @frame_clock: a #GdkFrameClock
|
||||
*
|
||||
* Stops updates for an animation. See the documentation for
|
||||
* gdk_frame_clock_begin_updating().
|
||||
*
|
||||
* Since: 3.8
|
||||
*/
|
||||
void
|
||||
gdk_frame_clock_end_updating (GdkFrameClock *frame_clock)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
GDK_FRAME_CLOCK_GET_CLASS (frame_clock)->end_updating (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_freeze (GdkFrameClock *clock)
|
||||
|
@ -82,6 +82,11 @@ GDK_AVAILABLE_IN_3_8
|
||||
void gdk_frame_clock_request_phase (GdkFrameClock *frame_clock,
|
||||
GdkFrameClockPhase phase);
|
||||
|
||||
GDK_AVAILABLE_IN_3_8
|
||||
void gdk_frame_clock_begin_updating (GdkFrameClock *frame_clock);
|
||||
GDK_AVAILABLE_IN_3_8
|
||||
void gdk_frame_clock_end_updating (GdkFrameClock *frame_clock);
|
||||
|
||||
/* Frame history */
|
||||
GDK_AVAILABLE_IN_3_8
|
||||
gint64 gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock);
|
||||
|
@ -45,6 +45,7 @@ struct _GdkFrameClockIdlePrivate
|
||||
guint flush_idle_id;
|
||||
guint paint_idle_id;
|
||||
guint freeze_count;
|
||||
guint updating_count;
|
||||
|
||||
GdkFrameClockPhase requested;
|
||||
GdkFrameClockPhase phase;
|
||||
@ -192,12 +193,26 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock)
|
||||
return priv->frame_time;
|
||||
}
|
||||
|
||||
#define RUN_FLUSH_IDLE(priv) \
|
||||
((priv)->freeze_count == 0 && \
|
||||
((priv)->requested & GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0)
|
||||
|
||||
/* The reason why we track updating_count separately here and don't
|
||||
* just add GDK_FRAME_CLOCK_PHASE_UPDATE into ->request on every frame
|
||||
* is so that we can avoid doing one more frame when an animation
|
||||
* is cancelled.
|
||||
*/
|
||||
#define RUN_PAINT_IDLE(priv) \
|
||||
((priv)->freeze_count == 0 && \
|
||||
(((priv)->requested & ~GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0 || \
|
||||
(priv)->updating_count > 0))
|
||||
|
||||
static void
|
||||
maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
{
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
if (priv->freeze_count == 0 && priv->requested != 0)
|
||||
if (RUN_FLUSH_IDLE (priv) || RUN_PAINT_IDLE (priv))
|
||||
{
|
||||
guint min_interval = 0;
|
||||
|
||||
@ -208,8 +223,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
min_interval = (min_interval_us + 500) / 1000;
|
||||
}
|
||||
|
||||
if (priv->flush_idle_id == 0 &&
|
||||
(priv->requested & GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0)
|
||||
if (priv->flush_idle_id == 0 && RUN_FLUSH_IDLE (priv))
|
||||
{
|
||||
priv->flush_idle_id = gdk_threads_add_timeout_full (GDK_PRIORITY_EVENTS + 1,
|
||||
min_interval,
|
||||
@ -218,9 +232,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
if (priv->paint_idle_id == 0 &&
|
||||
!priv->in_paint_idle &&
|
||||
(priv->requested & ~GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0)
|
||||
if (priv->paint_idle_id == 0 && RUN_PAINT_IDLE (priv))
|
||||
{
|
||||
priv->paint_idle_id = gdk_threads_add_timeout_full (GDK_PRIORITY_REDRAW,
|
||||
min_interval,
|
||||
@ -231,6 +243,24 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_stop_idle (GdkFrameClockIdle *clock_idle)
|
||||
{
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
if (priv->flush_idle_id != 0 && !RUN_FLUSH_IDLE (priv))
|
||||
{
|
||||
g_source_remove (priv->flush_idle_id);
|
||||
priv->flush_idle_id = 0;
|
||||
}
|
||||
|
||||
if (priv->paint_idle_id != 0 && !RUN_PAINT_IDLE (priv))
|
||||
{
|
||||
g_source_remove (priv->paint_idle_id);
|
||||
priv->paint_idle_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gint64
|
||||
compute_min_next_frame_time (GdkFrameClockIdle *clock_idle,
|
||||
gint64 last_frame_time)
|
||||
@ -265,7 +295,8 @@ gdk_frame_clock_flush_idle (void *data)
|
||||
|
||||
g_signal_emit_by_name (G_OBJECT (clock), "flush-events");
|
||||
|
||||
if ((priv->requested & ~GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0)
|
||||
if ((priv->requested & ~GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS) != 0 ||
|
||||
priv->updating_count > 0)
|
||||
priv->phase = GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT;
|
||||
else
|
||||
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
|
||||
@ -287,7 +318,8 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
priv->min_next_frame_time = 0;
|
||||
|
||||
skip_to_resume_events =
|
||||
(priv->requested & ~(GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS | GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS)) == 0;
|
||||
(priv->requested & ~(GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS | GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS)) == 0 &&
|
||||
priv->updating_count == 0;
|
||||
|
||||
if (priv->phase > GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT)
|
||||
{
|
||||
@ -325,7 +357,8 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
case GDK_FRAME_CLOCK_PHASE_UPDATE:
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
if (priv->requested & GDK_FRAME_CLOCK_PHASE_UPDATE)
|
||||
if ((priv->requested & GDK_FRAME_CLOCK_PHASE_UPDATE) != 0 ||
|
||||
priv->updating_count > 0)
|
||||
{
|
||||
priv->requested &= ~GDK_FRAME_CLOCK_PHASE_UPDATE;
|
||||
g_signal_emit_by_name (G_OBJECT (clock), "update");
|
||||
@ -435,26 +468,36 @@ gdk_frame_clock_idle_request_phase (GdkFrameClock *clock,
|
||||
maybe_start_idle (clock_idle);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_idle_begin_updating (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
priv->updating_count++;
|
||||
maybe_start_idle (clock_idle);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_idle_end_updating (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
g_return_if_fail (priv->updating_count > 0);
|
||||
|
||||
priv->updating_count--;
|
||||
maybe_stop_idle (clock_idle);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_frame_clock_idle_freeze (GdkFrameClock *clock)
|
||||
{
|
||||
GdkFrameClockIdlePrivate *priv = GDK_FRAME_CLOCK_IDLE (clock)->priv;
|
||||
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
|
||||
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
|
||||
|
||||
priv->freeze_count++;
|
||||
|
||||
if (priv->freeze_count == 1)
|
||||
{
|
||||
if (priv->flush_idle_id)
|
||||
{
|
||||
g_source_remove (priv->flush_idle_id);
|
||||
priv->flush_idle_id = 0;
|
||||
}
|
||||
if (priv->paint_idle_id)
|
||||
{
|
||||
g_source_remove (priv->paint_idle_id);
|
||||
priv->paint_idle_id = 0;
|
||||
}
|
||||
}
|
||||
maybe_stop_idle (clock_idle);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -489,6 +532,8 @@ gdk_frame_clock_idle_class_init (GdkFrameClockIdleClass *klass)
|
||||
|
||||
frame_clock_class->get_frame_time = gdk_frame_clock_idle_get_frame_time;
|
||||
frame_clock_class->request_phase = gdk_frame_clock_idle_request_phase;
|
||||
frame_clock_class->begin_updating = gdk_frame_clock_idle_begin_updating;
|
||||
frame_clock_class->end_updating = gdk_frame_clock_idle_end_updating;
|
||||
frame_clock_class->freeze = gdk_frame_clock_idle_freeze;
|
||||
frame_clock_class->thaw = gdk_frame_clock_idle_thaw;
|
||||
|
||||
|
@ -49,6 +49,8 @@ struct _GdkFrameClockClass
|
||||
|
||||
void (* request_phase) (GdkFrameClock *clock,
|
||||
GdkFrameClockPhase phase);
|
||||
void (* begin_updating) (GdkFrameClock *clock);
|
||||
void (* end_updating) (GdkFrameClock *clock);
|
||||
|
||||
void (* freeze) (GdkFrameClock *clock);
|
||||
void (* thaw) (GdkFrameClock *clock);
|
||||
|
@ -739,9 +739,6 @@ gtk_style_context_update (GdkFrameClock *clock,
|
||||
GtkStyleContext *context)
|
||||
{
|
||||
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
|
||||
|
||||
/* A little blech to request one more than we need */
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -762,6 +759,7 @@ gtk_style_context_disconnect_update (GtkStyleContext *context)
|
||||
g_signal_handler_disconnect (priv->frame_clock,
|
||||
priv->frame_clock_update_id);
|
||||
priv->frame_clock_update_id = 0;
|
||||
gdk_frame_clock_end_updating (priv->frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -776,7 +774,7 @@ gtk_style_context_connect_update (GtkStyleContext *context)
|
||||
"update",
|
||||
G_CALLBACK (gtk_style_context_update),
|
||||
context);
|
||||
gdk_frame_clock_request_phase (priv->frame_clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
gdk_frame_clock_begin_updating (priv->frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4554,6 +4554,7 @@ unref_tick_callback_info (GtkWidget *widget,
|
||||
g_signal_handlers_disconnect_by_func (frame_clock,
|
||||
(gpointer) gtk_widget_on_frame_clock_update,
|
||||
widget);
|
||||
gdk_frame_clock_end_updating (frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4596,10 +4597,6 @@ gtk_widget_on_frame_clock_update (GdkFrameClock *frame_clock,
|
||||
unref_tick_callback_info (widget, info, l);
|
||||
l = next;
|
||||
}
|
||||
|
||||
if (priv->tick_callbacks != NULL)
|
||||
gdk_frame_clock_request_phase (frame_clock,
|
||||
GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
}
|
||||
|
||||
static guint tick_callback_id;
|
||||
@ -4651,8 +4648,7 @@ gtk_widget_add_tick_callback (GtkWidget *widget,
|
||||
g_signal_connect (frame_clock, "update",
|
||||
G_CALLBACK (gtk_widget_on_frame_clock_update),
|
||||
widget);
|
||||
gdk_frame_clock_request_phase (frame_clock,
|
||||
GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
gdk_frame_clock_begin_updating (frame_clock);
|
||||
}
|
||||
|
||||
info = g_slice_new0 (GtkTickCallbackInfo);
|
||||
@ -4702,8 +4698,7 @@ gtk_widget_connect_frame_clock (GtkWidget *widget,
|
||||
g_signal_connect (frame_clock, "update",
|
||||
G_CALLBACK (gtk_widget_on_frame_clock_update),
|
||||
widget);
|
||||
gdk_frame_clock_request_phase (frame_clock,
|
||||
GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
gdk_frame_clock_begin_updating (frame_clock);
|
||||
}
|
||||
|
||||
if (priv->context)
|
||||
@ -4720,9 +4715,12 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget,
|
||||
_gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
|
||||
|
||||
if (priv->tick_callbacks)
|
||||
g_signal_handlers_disconnect_by_func (frame_clock,
|
||||
(gpointer) gtk_widget_on_frame_clock_update,
|
||||
widget);
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (frame_clock,
|
||||
(gpointer) gtk_widget_on_frame_clock_update,
|
||||
widget);
|
||||
gdk_frame_clock_end_updating (frame_clock);
|
||||
}
|
||||
|
||||
if (priv->context)
|
||||
gtk_style_context_set_frame_clock (priv->context, NULL);
|
||||
|
@ -350,8 +350,6 @@ on_update (GdkFrameClock *frame_clock,
|
||||
|
||||
gtk_widget_queue_draw (window);
|
||||
}
|
||||
|
||||
gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
}
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
@ -393,7 +391,7 @@ main(int argc, char **argv)
|
||||
frame_clock = gtk_widget_get_frame_clock (window);
|
||||
g_signal_connect (frame_clock, "update",
|
||||
G_CALLBACK (on_update), NULL);
|
||||
gdk_frame_clock_request_phase (frame_clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
gdk_frame_clock_begin_updating (frame_clock);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user