forked from AuroraMiddleware/gtk
Add an UPDATE phase and GdkFrameClockTarget, use for GtkStyleContext
Switch GtkStyleContext to using GdkFrameClock. To do this, add a new UPDATE phase to GdkFrameClock. Add a GdkFrameClockTarget interface with a single set_clock() method, and use this to deal with the fact that GtkWidget only has a frame clock when realized. https://bugzilla.gnome.org/show_bug.cgi?id=685460
This commit is contained in:
parent
7dfa412188
commit
344a69880a
@ -28,6 +28,19 @@
|
||||
|
||||
#include "gdkframeclock.h"
|
||||
|
||||
G_DEFINE_INTERFACE (GdkFrameClockTarget, gdk_frame_clock_target, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_frame_clock_target_default_init (GdkFrameClockTargetInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
void gdk_frame_clock_target_set_clock (GdkFrameClockTarget *target,
|
||||
GdkFrameClock *clock)
|
||||
{
|
||||
GDK_FRAME_CLOCK_TARGET_GET_IFACE (target)->set_clock (target, clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* SECTION:frameclock
|
||||
* @Short_description: Frame clock syncs painting to a window or display
|
||||
@ -79,6 +92,7 @@ G_DEFINE_INTERFACE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
|
||||
enum {
|
||||
FRAME_REQUESTED,
|
||||
BEFORE_PAINT,
|
||||
UPDATE,
|
||||
LAYOUT,
|
||||
PAINT,
|
||||
AFTER_PAINT,
|
||||
@ -123,6 +137,21 @@ gdk_frame_clock_default_init (GdkFrameClockInterface *iface)
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkFrameClock::update:
|
||||
* @clock: the frame clock emitting the signal
|
||||
*
|
||||
* FIXME.
|
||||
*/
|
||||
signals[UPDATE] =
|
||||
g_signal_new (g_intern_static_string ("update"),
|
||||
GDK_TYPE_FRAME_CLOCK,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GdkFrameClock::layout:
|
||||
* @clock: the frame clock emitting the signal
|
||||
|
@ -35,20 +35,41 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkFrameClock GdkFrameClock;
|
||||
typedef struct _GdkFrameClockInterface GdkFrameClockInterface;
|
||||
typedef struct _GdkFrameClockTarget GdkFrameClockTarget;
|
||||
typedef struct _GdkFrameClockTargetInterface GdkFrameClockTargetInterface;
|
||||
|
||||
#define GDK_TYPE_FRAME_CLOCK_TARGET (gdk_frame_clock_target_get_type ())
|
||||
#define GDK_FRAME_CLOCK_TARGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_FRAME_CLOCK_TARGET, GdkFrameClockTarget))
|
||||
#define GDK_IS_FRAME_CLOCK_TARGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_FRAME_CLOCK_TARGET))
|
||||
#define GDK_FRAME_CLOCK_TARGET_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GDK_TYPE_FRAME_CLOCK_TARGET, GdkFrameClockTargetInterface))
|
||||
|
||||
struct _GdkFrameClockTargetInterface
|
||||
{
|
||||
GTypeInterface base_iface;
|
||||
|
||||
void (*set_clock) (GdkFrameClockTarget *target,
|
||||
GdkFrameClock *clock);
|
||||
};
|
||||
|
||||
GType gdk_frame_clock_target_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void gdk_frame_clock_target_set_clock (GdkFrameClockTarget *target,
|
||||
GdkFrameClock *clock);
|
||||
|
||||
#define GDK_TYPE_FRAME_CLOCK (gdk_frame_clock_get_type ())
|
||||
#define GDK_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_FRAME_CLOCK, GdkFrameClock))
|
||||
#define GDK_IS_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_FRAME_CLOCK))
|
||||
#define GDK_FRAME_CLOCK_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GDK_TYPE_FRAME_CLOCK, GdkFrameClockInterface))
|
||||
|
||||
typedef struct _GdkFrameClock GdkFrameClock;
|
||||
typedef struct _GdkFrameClockInterface GdkFrameClockInterface;
|
||||
|
||||
typedef enum {
|
||||
GDK_FRAME_CLOCK_PHASE_NONE = 0,
|
||||
GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT = 1 << 0,
|
||||
GDK_FRAME_CLOCK_PHASE_LAYOUT = 1 << 1,
|
||||
GDK_FRAME_CLOCK_PHASE_PAINT = 1 << 2,
|
||||
GDK_FRAME_CLOCK_PHASE_AFTER_PAINT = 1 << 3
|
||||
GDK_FRAME_CLOCK_PHASE_UPDATE = 1 << 1,
|
||||
GDK_FRAME_CLOCK_PHASE_LAYOUT = 1 << 2,
|
||||
GDK_FRAME_CLOCK_PHASE_PAINT = 1 << 3,
|
||||
GDK_FRAME_CLOCK_PHASE_AFTER_PAINT = 1 << 4
|
||||
} GdkFrameClockPhase;
|
||||
|
||||
struct _GdkFrameClockInterface
|
||||
@ -67,6 +88,7 @@ struct _GdkFrameClockInterface
|
||||
/* signals */
|
||||
/* void (* frame_requested) (GdkFrameClock *clock); */
|
||||
/* void (* before_paint) (GdkFrameClock *clock); */
|
||||
/* void (* update) (GdkFrameClock *clock); */
|
||||
/* void (* layout) (GdkFrameClock *clock); */
|
||||
/* void (* paint) (GdkFrameClock *clock); */
|
||||
/* void (* after_paint) (GdkFrameClock *clock); */
|
||||
|
@ -189,7 +189,16 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
* they don't get repeated if you freeze/thaw while
|
||||
* in them. */
|
||||
g_signal_emit_by_name (G_OBJECT (clock), "before-paint");
|
||||
priv->phase = GDK_FRAME_CLOCK_PHASE_LAYOUT;
|
||||
priv->phase = GDK_FRAME_CLOCK_PHASE_UPDATE;
|
||||
}
|
||||
case GDK_FRAME_CLOCK_PHASE_UPDATE:
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
if (priv->requested & GDK_FRAME_CLOCK_PHASE_UPDATE)
|
||||
{
|
||||
priv->requested &= ~GDK_FRAME_CLOCK_PHASE_UPDATE;
|
||||
g_signal_emit_by_name (G_OBJECT (clock), "update");
|
||||
}
|
||||
}
|
||||
case GDK_FRAME_CLOCK_PHASE_LAYOUT:
|
||||
if (priv->freeze_count == 0)
|
||||
|
@ -358,20 +358,21 @@ struct _GtkStyleContextPrivate
|
||||
|
||||
GtkStyleCascade *cascade;
|
||||
|
||||
GtkStyleContext *animation_list_prev;
|
||||
GtkStyleContext *animation_list_next;
|
||||
|
||||
GtkStyleContext *parent;
|
||||
GSList *children;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *widget;
|
||||
GtkWidgetPath *widget_path;
|
||||
GHashTable *style_data;
|
||||
GtkStyleInfo *info;
|
||||
|
||||
GdkFrameClock *frame_clock;
|
||||
guint frame_clock_update_id;
|
||||
|
||||
GtkCssChange relevant_changes;
|
||||
GtkCssChange pending_changes;
|
||||
|
||||
const GtkBitmask *invalidating_context;
|
||||
guint animating : 1;
|
||||
guint invalid : 1;
|
||||
};
|
||||
|
||||
@ -388,11 +389,11 @@ enum {
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
static GtkStyleContext *_running_animations = NULL;
|
||||
guint _running_animations_timer_id = 0;
|
||||
|
||||
static void gtk_style_context_finalize (GObject *object);
|
||||
|
||||
static void frame_clock_target_iface_init (GdkFrameClockTargetInterface *target);
|
||||
|
||||
static void gtk_style_context_impl_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
@ -404,7 +405,11 @@ static void gtk_style_context_impl_get_property (GObject *object,
|
||||
static StyleData *style_data_lookup (GtkStyleContext *context);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
|
||||
static void gtk_style_context_disconnect_update (GtkStyleContext *context);
|
||||
static void gtk_style_context_connect_update (GtkStyleContext *context);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_FRAME_CLOCK_TARGET, frame_clock_target_iface_init))
|
||||
|
||||
static void
|
||||
gtk_style_context_real_changed (GtkStyleContext *context)
|
||||
@ -469,6 +474,25 @@ gtk_style_context_class_init (GtkStyleContextClass *klass)
|
||||
g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_style_context_set_clock (GdkFrameClockTarget *target,
|
||||
GdkFrameClock *clock)
|
||||
{
|
||||
GtkStyleContext *context = GTK_STYLE_CONTEXT (target);
|
||||
GtkStyleContextPrivate *priv = context->priv;
|
||||
|
||||
gtk_style_context_disconnect_update (context);
|
||||
priv->frame_clock = clock;
|
||||
if (priv->animating)
|
||||
gtk_style_context_connect_update (context);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_clock_target_iface_init (GdkFrameClockTargetInterface *iface)
|
||||
{
|
||||
iface->set_clock = gtk_style_context_set_clock;
|
||||
}
|
||||
|
||||
static StyleData *
|
||||
style_data_new (void)
|
||||
{
|
||||
@ -724,19 +748,14 @@ gtk_style_context_init (GtkStyleContext *style_context)
|
||||
_gtk_style_cascade_get_for_screen (priv->screen));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_style_context_do_animations (gpointer unused)
|
||||
static void
|
||||
gtk_style_context_update (GdkFrameClock *clock,
|
||||
GtkStyleContext *context)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
|
||||
|
||||
for (context = _running_animations;
|
||||
context != NULL;
|
||||
context = context->priv->animation_list_next)
|
||||
{
|
||||
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
/* A little blech to request one more than we need */
|
||||
gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -744,8 +763,35 @@ gtk_style_context_is_animating (GtkStyleContext *context)
|
||||
{
|
||||
GtkStyleContextPrivate *priv = context->priv;
|
||||
|
||||
return priv->animation_list_prev != NULL
|
||||
|| _running_animations == context;
|
||||
return priv->animating;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_style_context_disconnect_update (GtkStyleContext *context)
|
||||
{
|
||||
GtkStyleContextPrivate *priv = context->priv;
|
||||
|
||||
if (priv->frame_clock && priv->frame_clock_update_id)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->frame_clock,
|
||||
priv->frame_clock_update_id);
|
||||
priv->frame_clock_update_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_style_context_connect_update (GtkStyleContext *context)
|
||||
{
|
||||
GtkStyleContextPrivate *priv = context->priv;
|
||||
|
||||
if (priv->frame_clock && priv->frame_clock_update_id == 0)
|
||||
{
|
||||
priv->frame_clock_update_id = g_signal_connect (priv->frame_clock,
|
||||
"update",
|
||||
G_CALLBACK (gtk_style_context_update),
|
||||
context);
|
||||
gdk_frame_clock_request_phase (priv->frame_clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -756,25 +802,14 @@ gtk_style_context_stop_animating (GtkStyleContext *context)
|
||||
if (!gtk_style_context_is_animating (context))
|
||||
return;
|
||||
|
||||
if (priv->animation_list_prev == NULL)
|
||||
priv->animating = FALSE;
|
||||
|
||||
gtk_style_context_disconnect_update (context);
|
||||
if (priv->widget)
|
||||
{
|
||||
_running_animations = priv->animation_list_next;
|
||||
|
||||
if (_running_animations == NULL)
|
||||
{
|
||||
/* we were the last animation */
|
||||
g_source_remove (_running_animations_timer_id);
|
||||
_running_animations_timer_id = 0;
|
||||
}
|
||||
gtk_widget_remove_frame_clock_target (priv->widget,
|
||||
GDK_FRAME_CLOCK_TARGET (context));
|
||||
}
|
||||
else
|
||||
priv->animation_list_prev->priv->animation_list_next = priv->animation_list_next;
|
||||
|
||||
if (priv->animation_list_next)
|
||||
priv->animation_list_next->priv->animation_list_prev = priv->animation_list_prev;
|
||||
|
||||
priv->animation_list_next = NULL;
|
||||
priv->animation_list_prev = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -785,18 +820,13 @@ gtk_style_context_start_animating (GtkStyleContext *context)
|
||||
if (gtk_style_context_is_animating (context))
|
||||
return;
|
||||
|
||||
if (_running_animations == NULL)
|
||||
priv->animating = TRUE;
|
||||
|
||||
gtk_style_context_connect_update (context);
|
||||
if (priv->widget)
|
||||
{
|
||||
_running_animations_timer_id = gdk_threads_add_timeout (25,
|
||||
gtk_style_context_do_animations,
|
||||
NULL);
|
||||
_running_animations = context;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->animation_list_next = _running_animations;
|
||||
_running_animations->priv->animation_list_prev = context;
|
||||
_running_animations = context;
|
||||
gtk_widget_add_frame_clock_target (priv->widget,
|
||||
GDK_FRAME_CLOCK_TARGET (context));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -409,6 +409,9 @@ struct _GtkWidgetPrivate
|
||||
/* The widget's parent */
|
||||
GtkWidget *parent;
|
||||
|
||||
/* Animations and other things to update on clock ticks */
|
||||
GList *frame_clock_targets;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
/* Number of gtk_widget_push_verify_invariants () */
|
||||
guint verifying_invariants_count;
|
||||
@ -4533,6 +4536,7 @@ gtk_widget_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
cairo_region_t *region;
|
||||
GList *tmp_list;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (widget->priv->anchored ||
|
||||
@ -4588,6 +4592,12 @@ gtk_widget_realize (GtkWidget *widget)
|
||||
if (GTK_IS_CONTAINER (widget))
|
||||
_gtk_container_maybe_start_idle_sizer (GTK_CONTAINER (widget));
|
||||
|
||||
for (tmp_list = priv->frame_clock_targets; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
GdkFrameClock *frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
gdk_frame_clock_target_set_clock (tmp_list->data, frame_clock);
|
||||
}
|
||||
|
||||
gtk_widget_pop_verify_invariants (widget);
|
||||
}
|
||||
}
|
||||
@ -10533,6 +10543,10 @@ gtk_widget_real_destroy (GtkWidget *object)
|
||||
|
||||
gtk_grab_remove (widget);
|
||||
|
||||
g_list_foreach (priv->frame_clock_targets, (GFunc)g_object_unref, NULL);
|
||||
g_list_free (priv->frame_clock_targets);
|
||||
priv->frame_clock_targets = NULL;
|
||||
|
||||
if (priv->style)
|
||||
g_object_unref (priv->style);
|
||||
priv->style = gtk_widget_get_default_style ();
|
||||
@ -14582,3 +14596,65 @@ gtk_widget_insert_action_group (GtkWidget *widget,
|
||||
else
|
||||
g_action_muxer_remove (muxer, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_add_frame_clock_target:
|
||||
* @widget: a #GtkWidget
|
||||
* @target: the #GdkClockTarget
|
||||
*
|
||||
* Associates a #GdkClockTarget with the widget. When the widget
|
||||
* is realized and gets a #GdkFrameClock the clock target will be
|
||||
* added to that frame clock.
|
||||
*/
|
||||
void
|
||||
gtk_widget_add_frame_clock_target (GtkWidget *widget,
|
||||
GdkFrameClockTarget *target)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
priv = widget->priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK_TARGET (target));
|
||||
|
||||
priv->frame_clock_targets = g_list_prepend (priv->frame_clock_targets, target);
|
||||
g_object_ref (target);
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
GdkFrameClock *clock;
|
||||
clock = gtk_widget_get_frame_clock (widget);
|
||||
gdk_frame_clock_target_set_clock (target, clock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_remove_frame_clock_target:
|
||||
* @widget: a #GtkWidget
|
||||
* @target: the #GdkClockTarget
|
||||
*
|
||||
* Removes a #GdkClockTarget previously added with
|
||||
* gtk_widget_add_frame_clock_target.
|
||||
*/
|
||||
void
|
||||
gtk_widget_remove_frame_clock_target (GtkWidget *widget,
|
||||
GdkFrameClockTarget *target)
|
||||
{
|
||||
GtkWidgetPrivate *priv;
|
||||
GList *tmp_list;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK_TARGET (target));
|
||||
|
||||
priv = widget->priv;
|
||||
|
||||
tmp_list = g_list_find (priv->frame_clock_targets, target);
|
||||
if (tmp_list == NULL)
|
||||
return;
|
||||
|
||||
priv->frame_clock_targets = g_list_delete_link (priv->frame_clock_targets, tmp_list);
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gdk_frame_clock_target_set_clock (target, NULL);
|
||||
|
||||
g_object_unref (target);
|
||||
}
|
||||
|
@ -905,6 +905,13 @@ void gtk_widget_insert_action_group (GtkWidg
|
||||
const gchar *name,
|
||||
GActionGroup *group);
|
||||
|
||||
GDK_AVAILABLE_IN_3_2
|
||||
void gtk_widget_add_frame_clock_target (GtkWidget *widget,
|
||||
GdkFrameClockTarget *target);
|
||||
GDK_AVAILABLE_IN_3_2
|
||||
void gtk_widget_remove_frame_clock_target (GtkWidget *widget,
|
||||
GdkFrameClockTarget *target);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_WIDGET_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user