mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
Add repaint functions
Sometimes it is necessary for third party code to have a function called during the redraw process, so that you can update the scenegraph before it is painted.
This commit is contained in:
parent
5cde6a598f
commit
87465355d3
@ -2816,3 +2816,162 @@ clutter_get_font_map (void)
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _ClutterRepaintFunction
|
||||||
|
{
|
||||||
|
guint id;
|
||||||
|
GSourceFunc func;
|
||||||
|
gpointer data;
|
||||||
|
GDestroyNotify notify;
|
||||||
|
} ClutterRepaintFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_remove_repaint_func:
|
||||||
|
* @handle_id: an unsigned integer greater than zero
|
||||||
|
*
|
||||||
|
* Removes the repaint function with @handle_id as its id
|
||||||
|
*
|
||||||
|
* Since: 1.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_threads_remove_repaint_func (guint handle_id)
|
||||||
|
{
|
||||||
|
ClutterRepaintFunction *repaint_func;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
g_return_if_fail (handle_id > 0);
|
||||||
|
|
||||||
|
context = CLUTTER_CONTEXT ();
|
||||||
|
l = context->repaint_funcs;
|
||||||
|
while (l != NULL)
|
||||||
|
{
|
||||||
|
repaint_func = l->data;
|
||||||
|
|
||||||
|
if (repaint_func->id == handle_id)
|
||||||
|
{
|
||||||
|
context->repaint_funcs =
|
||||||
|
g_list_remove_link (context->repaint_funcs, l);
|
||||||
|
|
||||||
|
g_list_free (l);
|
||||||
|
|
||||||
|
if (repaint_func->notify)
|
||||||
|
repaint_func->notify (repaint_func->data);
|
||||||
|
|
||||||
|
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_add_repaint_func:
|
||||||
|
* @func: the function to be called within the paint cycle
|
||||||
|
* @data: data to be passed to the function, or %NULL
|
||||||
|
* @notify: function to be called when removing the repaint
|
||||||
|
* function, or %NULL
|
||||||
|
*
|
||||||
|
* Adds a function to be called whenever Clutter is repainting a Stage.
|
||||||
|
* If the function returns %FALSE it is automatically removed from the
|
||||||
|
* list of repaint functions and will not be called again.
|
||||||
|
*
|
||||||
|
* This function is guaranteed to be called from within the same thread
|
||||||
|
* that called clutter_main(), and while the Clutter lock is being held.
|
||||||
|
*
|
||||||
|
* A repaint function is useful to ensure that an update of the scenegraph
|
||||||
|
* is performed before the scenegraph is repainted; for instance, uploading
|
||||||
|
* a frame from a video into a #ClutterTexture.
|
||||||
|
*
|
||||||
|
* When the repaint function is removed (either because it returned %FALSE
|
||||||
|
* or because clutter_threads_remove_repaint_func() has been called) the
|
||||||
|
* @notify function will be called, if any is set.
|
||||||
|
*
|
||||||
|
* Return value: the ID (greater than 0) of the repaint function. You
|
||||||
|
* can use the returned integer to remove the repaint function by
|
||||||
|
* calling clutter_threads_remove_repaint_func().
|
||||||
|
*
|
||||||
|
* Since: 1.0
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
clutter_threads_add_repaint_func (GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
static guint repaint_id = 1;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
ClutterRepaintFunction *repaint_func;
|
||||||
|
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
context = CLUTTER_CONTEXT ();
|
||||||
|
|
||||||
|
/* XXX lock the context */
|
||||||
|
|
||||||
|
repaint_func = g_slice_new (ClutterRepaintFunction);
|
||||||
|
|
||||||
|
repaint_func->id = repaint_id++;
|
||||||
|
repaint_func->func = func;
|
||||||
|
repaint_func->data = data;
|
||||||
|
repaint_func->notify = notify;
|
||||||
|
|
||||||
|
context->repaint_funcs = g_list_prepend (context->repaint_funcs,
|
||||||
|
repaint_func);
|
||||||
|
|
||||||
|
/* XXX unlock the context */
|
||||||
|
|
||||||
|
return repaint_func->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _clutter_run_repaint_functions:
|
||||||
|
*
|
||||||
|
* Executes the repaint functions added using the
|
||||||
|
* clutter_threads_add_repaint_func() function.
|
||||||
|
*
|
||||||
|
* Must be called before calling clutter_redraw() and
|
||||||
|
* with the Clutter thread lock held.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_clutter_run_repaint_functions (void)
|
||||||
|
{
|
||||||
|
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||||
|
ClutterRepaintFunction *repaint_func;
|
||||||
|
GList *reinvoke_list, *l;
|
||||||
|
|
||||||
|
if (context->repaint_funcs == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
reinvoke_list = NULL;
|
||||||
|
|
||||||
|
/* consume the whole list while we execute the functions */
|
||||||
|
while (context->repaint_funcs)
|
||||||
|
{
|
||||||
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
repaint_func = context->repaint_funcs->data;
|
||||||
|
|
||||||
|
l = context->repaint_funcs;
|
||||||
|
context->repaint_funcs =
|
||||||
|
g_list_remove_link (context->repaint_funcs, context->repaint_funcs);
|
||||||
|
|
||||||
|
g_list_free (l);
|
||||||
|
|
||||||
|
res = repaint_func->func (repaint_func->data);
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
reinvoke_list = g_list_prepend (reinvoke_list, repaint_func);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (repaint_func->notify)
|
||||||
|
repaint_func->notify (repaint_func->data);
|
||||||
|
|
||||||
|
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reinvoke_list)
|
||||||
|
context->repaint_funcs = reinvoke_list;
|
||||||
|
}
|
||||||
|
@ -109,34 +109,38 @@ gboolean clutter_get_show_fps (void);
|
|||||||
gulong clutter_get_timestamp (void);
|
gulong clutter_get_timestamp (void);
|
||||||
|
|
||||||
/* Threading functions */
|
/* Threading functions */
|
||||||
void clutter_threads_init (void);
|
void clutter_threads_init (void);
|
||||||
void clutter_threads_enter (void);
|
void clutter_threads_enter (void);
|
||||||
void clutter_threads_leave (void);
|
void clutter_threads_leave (void);
|
||||||
void clutter_threads_set_lock_functions (GCallback enter_fn,
|
void clutter_threads_set_lock_functions (GCallback enter_fn,
|
||||||
GCallback leave_fn);
|
GCallback leave_fn);
|
||||||
guint clutter_threads_add_idle (GSourceFunc func,
|
guint clutter_threads_add_idle (GSourceFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
guint clutter_threads_add_idle_full (gint priority,
|
guint clutter_threads_add_idle_full (gint priority,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
guint clutter_threads_add_timeout (guint interval,
|
guint clutter_threads_add_timeout (guint interval,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
guint clutter_threads_add_timeout_full (gint priority,
|
guint clutter_threads_add_timeout_full (gint priority,
|
||||||
guint interval,
|
guint interval,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
guint clutter_threads_add_frame_source (guint fps,
|
guint clutter_threads_add_frame_source (guint fps,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
guint clutter_threads_add_frame_source_full
|
guint clutter_threads_add_frame_source_full (gint priority,
|
||||||
(gint priority,
|
guint fps,
|
||||||
guint fps,
|
GSourceFunc func,
|
||||||
GSourceFunc func,
|
gpointer data,
|
||||||
gpointer data,
|
GDestroyNotify notify);
|
||||||
GDestroyNotify notify);
|
|
||||||
|
guint clutter_threads_add_repaint_func (GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
void clutter_threads_remove_repaint_func (guint handler_id);
|
||||||
|
|
||||||
void clutter_set_motion_events_enabled (gboolean enable);
|
void clutter_set_motion_events_enabled (gboolean enable);
|
||||||
gboolean clutter_get_motion_events_enabled (void);
|
gboolean clutter_get_motion_events_enabled (void);
|
||||||
@ -158,7 +162,7 @@ void clutter_clear_glyph_cache (void);
|
|||||||
void clutter_set_font_flags (ClutterFontFlags flags);
|
void clutter_set_font_flags (ClutterFontFlags flags);
|
||||||
ClutterFontFlags clutter_get_font_flags (void);
|
ClutterFontFlags clutter_get_font_flags (void);
|
||||||
|
|
||||||
ClutterInputDevice* clutter_get_input_device_for_id (gint id);
|
ClutterInputDevice *clutter_get_input_device_for_id (gint id);
|
||||||
|
|
||||||
void clutter_grab_pointer_for_device (ClutterActor *actor,
|
void clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||||
gint id);
|
gint id);
|
||||||
|
@ -132,6 +132,8 @@ struct _ClutterMainContext
|
|||||||
|
|
||||||
ClutterMasterClock *master_clock;
|
ClutterMasterClock *master_clock;
|
||||||
gulong redraw_count;
|
gulong redraw_count;
|
||||||
|
|
||||||
|
GList *repaint_funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
||||||
@ -238,6 +240,8 @@ void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
|||||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||||
gboolean enable);
|
gboolean enable);
|
||||||
|
|
||||||
|
void _clutter_run_repaint_functions (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
||||||
|
@ -403,6 +403,12 @@ redraw_update_idle (gpointer user_data)
|
|||||||
master_clock = _clutter_master_clock_get_default ();
|
master_clock = _clutter_master_clock_get_default ();
|
||||||
_clutter_master_clock_advance (master_clock);
|
_clutter_master_clock_advance (master_clock);
|
||||||
|
|
||||||
|
/* run the (eventual) repaint functions; since those might end up queuing
|
||||||
|
* a relayout or a redraw we need to execute them before maybe_relayout()
|
||||||
|
*/
|
||||||
|
CLUTTER_NOTE (PAINT, "Repaint functions");
|
||||||
|
_clutter_run_repaint_functions ();
|
||||||
|
|
||||||
/* clutter_redraw() will also call maybe_relayout(), but since a relayout
|
/* clutter_redraw() will also call maybe_relayout(), but since a relayout
|
||||||
* can queue a redraw, we want to do the relayout before we clear the
|
* can queue a redraw, we want to do the relayout before we clear the
|
||||||
* update_idle to avoid painting the stage twice. Calling maybe_relayout()
|
* update_idle to avoid painting the stage twice. Calling maybe_relayout()
|
||||||
@ -457,8 +463,7 @@ static void
|
|||||||
set_offscreen_while_unrealized (ClutterActor *actor,
|
set_offscreen_while_unrealized (ClutterActor *actor,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
CLUTTER_STAGE (actor)->priv->is_offscreen =
|
CLUTTER_STAGE (actor)->priv->is_offscreen = GPOINTER_TO_INT (data);
|
||||||
GPOINTER_TO_INT (data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user