mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
Merge clutter.git/threading branch
This commit is contained in:
parent
f5b4b96394
commit
4befcd0a64
37
ChangeLog
37
ChangeLog
@ -1,3 +1,40 @@
|
|||||||
|
2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
Merge the clutter.git/threading branch.
|
||||||
|
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-main.h:
|
||||||
|
* clutter/clutter-private.h: Add threading locking and unlocking
|
||||||
|
functions, to mark a critical section and access the Clutter API
|
||||||
|
from differen threads. Add an initialisation function and a function
|
||||||
|
to override the default lock aquisition and release functions, for
|
||||||
|
bindings and application-specific locking handling. Add MT-safe
|
||||||
|
versions of g_idle_add() and g_timeout_add() which will call the
|
||||||
|
functions under the main Clutter lock and without races. The
|
||||||
|
Clutter thread-safe implementation is basically the same used by
|
||||||
|
GDK, so the same caveats apply.
|
||||||
|
|
||||||
|
* clutter/clutter-actor.c:
|
||||||
|
* clutter/clutter-timeline.c:
|
||||||
|
* clutter/clutter-timeout-pool.c: Use the new threading API when
|
||||||
|
invoking idle and timeouts.
|
||||||
|
|
||||||
|
* clutter/eglnative/clutter-event-egl.c:
|
||||||
|
* clutter/eglx/clutter-event-egl.c:
|
||||||
|
* clutter/glx/clutter-event-glx.c:
|
||||||
|
* clutter/sdl/clutter-event-sdl.c: Acquire and release the main
|
||||||
|
Clutter lock when preparing, checking and dispatching the events
|
||||||
|
on the queue in every backend.
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/test-threads.c: Add a test case, showing how to use the
|
||||||
|
threading API and write thread-safe Clutter applications.
|
||||||
|
|
||||||
|
2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
* configure.ac: Bump up to 0.5.0 and start the new development
|
||||||
|
branch.
|
||||||
|
|
||||||
2007-08-07 Emmanuele Bassi <ebassi@openedhand.com>
|
2007-08-07 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
* configure.ac: Bump up to 0.4.0.
|
* configure.ac: Bump up to 0.4.0.
|
||||||
|
@ -1210,9 +1210,10 @@ clutter_actor_queue_redraw (ClutterActor *self)
|
|||||||
|
|
||||||
if (!ctx->update_idle)
|
if (!ctx->update_idle)
|
||||||
{
|
{
|
||||||
CLUTTER_TIMESTAMP (SCHEDULER,
|
CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for actor: %p", self);
|
||||||
"Adding ideler for actor: %p", self);
|
|
||||||
ctx->update_idle = g_idle_add_full (G_PRIORITY_DEFAULT + 10,
|
ctx->update_idle =
|
||||||
|
clutter_threads_add_idle_full (G_PRIORITY_DEFAULT + 10,
|
||||||
redraw_update_idle,
|
redraw_update_idle,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +48,21 @@
|
|||||||
|
|
||||||
#include "cogl.h"
|
#include "cogl.h"
|
||||||
|
|
||||||
|
/* main context */
|
||||||
static ClutterMainContext *ClutterCntx = NULL;
|
static ClutterMainContext *ClutterCntx = NULL;
|
||||||
|
|
||||||
|
/* main lock and locking/unlocking functions */
|
||||||
|
static GMutex *clutter_threads_mutex = NULL;
|
||||||
|
static GCallback clutter_threads_lock = NULL;
|
||||||
|
static GCallback clutter_threads_unlock = NULL;
|
||||||
|
|
||||||
static gboolean clutter_is_initialized = FALSE;
|
static gboolean clutter_is_initialized = FALSE;
|
||||||
static gboolean clutter_show_fps = FALSE;
|
static gboolean clutter_show_fps = FALSE;
|
||||||
static gboolean clutter_fatal_warnings = FALSE;
|
static gboolean clutter_fatal_warnings = FALSE;
|
||||||
|
|
||||||
|
static guint clutter_main_loop_level = 0;
|
||||||
|
static GSList *main_loops = NULL;
|
||||||
|
|
||||||
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
#ifdef CLUTTER_ENABLE_DEBUG
|
||||||
@ -75,9 +84,12 @@ static const GDebugKey clutter_debug_keys[] = {
|
|||||||
/**
|
/**
|
||||||
* clutter_get_show_fps:
|
* clutter_get_show_fps:
|
||||||
*
|
*
|
||||||
* FIXME
|
* Returns whether Clutter should print out the frames per second on the
|
||||||
|
* console. You can enable this setting either using the
|
||||||
|
* <literal>CLUTTER_SHOW_FPS</literal> environment variable or passing
|
||||||
|
* the <literal>--clutter-show-fps</literal> command line argument. *
|
||||||
*
|
*
|
||||||
* Return value: FIXME
|
* Return value: %TRUE if Clutter should show the FPS.
|
||||||
*
|
*
|
||||||
* Since: 0.4
|
* Since: 0.4
|
||||||
*/
|
*/
|
||||||
@ -91,7 +103,8 @@ clutter_get_show_fps (void)
|
|||||||
/**
|
/**
|
||||||
* clutter_redraw:
|
* clutter_redraw:
|
||||||
*
|
*
|
||||||
* FIXME
|
* Forces a redraw of the entire stage. Applications should never use this
|
||||||
|
* function, but queue a redraw using clutter_actor_queue_redraw().
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_redraw (void)
|
clutter_redraw (void)
|
||||||
@ -161,8 +174,11 @@ clutter_redraw (void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_do_event
|
* clutter_do_event
|
||||||
|
* @event: a #ClutterEvent.
|
||||||
*
|
*
|
||||||
* This function should never be called by applications.
|
* Processes an event. This function should never be called by applications.
|
||||||
|
*
|
||||||
|
* Since: 0.4
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_do_event (ClutterEvent *event)
|
clutter_do_event (ClutterEvent *event)
|
||||||
@ -215,12 +231,9 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
void
|
void
|
||||||
clutter_main_quit (void)
|
clutter_main_quit (void)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
g_return_if_fail (main_loops != NULL);
|
||||||
|
|
||||||
g_return_if_fail (context->main_loops != NULL);
|
g_main_loop_quit (main_loops->data);
|
||||||
|
|
||||||
if (g_main_loop_is_running (context->main_loops->data))
|
|
||||||
g_main_loop_quit (context->main_loops->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,9 +246,7 @@ clutter_main_quit (void)
|
|||||||
gint
|
gint
|
||||||
clutter_main_level (void)
|
clutter_main_level (void)
|
||||||
{
|
{
|
||||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
return clutter_main_loop_level;
|
||||||
|
|
||||||
return context->main_loop_level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -258,24 +269,25 @@ clutter_main (void)
|
|||||||
|
|
||||||
CLUTTER_MARK ();
|
CLUTTER_MARK ();
|
||||||
|
|
||||||
context->main_loop_level++;
|
clutter_main_loop_level++;
|
||||||
|
|
||||||
loop = g_main_loop_new (NULL, TRUE);
|
loop = g_main_loop_new (NULL, TRUE);
|
||||||
context->main_loops = g_slist_prepend (context->main_loops, loop);
|
main_loops = g_slist_prepend (main_loops, loop);
|
||||||
|
|
||||||
if (g_main_loop_is_running (context->main_loops->data))
|
if (g_main_loop_is_running (main_loops->data))
|
||||||
{
|
{
|
||||||
/* FIXME - add thread locking around this call */
|
clutter_threads_leave ();
|
||||||
g_main_loop_run (loop);
|
g_main_loop_run (loop);
|
||||||
|
clutter_threads_enter ();
|
||||||
}
|
}
|
||||||
|
|
||||||
context->main_loops = g_slist_remove (context->main_loops, loop);
|
main_loops = g_slist_remove (main_loops, loop);
|
||||||
|
|
||||||
g_main_loop_unref (loop);
|
g_main_loop_unref (loop);
|
||||||
|
|
||||||
context->main_loop_level--;
|
clutter_main_loop_level--;
|
||||||
|
|
||||||
if (context->main_loop_level == 0)
|
if (clutter_main_loop_level == 0)
|
||||||
{
|
{
|
||||||
/* this will take care of destroying the stage */
|
/* this will take care of destroying the stage */
|
||||||
g_object_unref (context->backend);
|
g_object_unref (context->backend);
|
||||||
@ -287,6 +299,326 @@ clutter_main (void)
|
|||||||
CLUTTER_MARK ();
|
CLUTTER_MARK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_threads_impl_lock (void)
|
||||||
|
{
|
||||||
|
if (clutter_threads_mutex)
|
||||||
|
g_mutex_lock (clutter_threads_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_threads_impl_unlock (void)
|
||||||
|
{
|
||||||
|
if (clutter_threads_mutex)
|
||||||
|
g_mutex_unlock (clutter_threads_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_init:
|
||||||
|
*
|
||||||
|
* Initialises the Clutter threading mechanism, so that Clutter API can be
|
||||||
|
* called by multiple threads, using clutter_threads_enter() and
|
||||||
|
* clutter_threads_leave() to mark the critical sections.
|
||||||
|
*
|
||||||
|
* You must call g_thread_init() before this function.
|
||||||
|
*
|
||||||
|
* This function must be called before clutter_init().
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_threads_init (void)
|
||||||
|
{
|
||||||
|
if (!g_thread_supported ())
|
||||||
|
g_error ("g_thread_init() must be called before clutter_threads_init()");
|
||||||
|
|
||||||
|
clutter_threads_mutex = g_mutex_new ();
|
||||||
|
|
||||||
|
if (!clutter_threads_lock)
|
||||||
|
clutter_threads_lock = clutter_threads_impl_lock;
|
||||||
|
|
||||||
|
if (!clutter_threads_unlock)
|
||||||
|
clutter_threads_unlock = clutter_threads_impl_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_set_lock_functions:
|
||||||
|
* @enter_fn: function called when aquiring the Clutter main lock
|
||||||
|
* @leave_fn: function called when releasing the Clutter main lock
|
||||||
|
*
|
||||||
|
* Allows the application to replace the standard method that
|
||||||
|
* Clutter uses to protect its data structures. Normally, Clutter
|
||||||
|
* creates a single #GMutex that is locked by clutter_threads_enter(),
|
||||||
|
* and released by clutter_threads_leave(); using this function an
|
||||||
|
* application provides, instead, a function @enter_fn that is
|
||||||
|
* called by clutter_threads_enter() and a function @leave_fn that is
|
||||||
|
* called by clutter_threads_leave().
|
||||||
|
*
|
||||||
|
* The functions must provide at least same locking functionality
|
||||||
|
* as the default implementation, but can also do extra application
|
||||||
|
* specific processing.
|
||||||
|
*
|
||||||
|
* As an example, consider an application that has its own recursive
|
||||||
|
* lock that when held, holds the Clutter lock as well. When Clutter
|
||||||
|
* unlocks the Clutter lock when entering a recursive main loop, the
|
||||||
|
* application must temporarily release its lock as well.
|
||||||
|
*
|
||||||
|
* Most threaded Clutter apps won't need to use this method.
|
||||||
|
*
|
||||||
|
* This method must be called before clutter_threads_init(), and cannot
|
||||||
|
* be called multiple times.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_threads_set_lock_functions (GCallback enter_fn,
|
||||||
|
GCallback leave_fn)
|
||||||
|
{
|
||||||
|
g_return_if_fail (clutter_threads_lock == NULL &&
|
||||||
|
clutter_threads_unlock == NULL);
|
||||||
|
|
||||||
|
clutter_threads_lock = enter_fn;
|
||||||
|
clutter_threads_unlock = leave_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GSourceFunc func;
|
||||||
|
gpointer data;
|
||||||
|
GDestroyNotify notify;
|
||||||
|
} ClutterThreadsDispatch;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_threads_dispatch (gpointer data)
|
||||||
|
{
|
||||||
|
ClutterThreadsDispatch *dispatch = data;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
|
if (!g_source_is_destroyed (g_main_current_source ()))
|
||||||
|
ret = dispatch->func (dispatch->data);
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_threads_dispatch_free (gpointer data)
|
||||||
|
{
|
||||||
|
ClutterThreadsDispatch *dispatch = data;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
|
if (dispatch->notify)
|
||||||
|
dispatch->notify (dispatch->data);
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
g_slice_free (ClutterThreadsDispatch, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_add_idle_full:
|
||||||
|
* @priority: the priority of the timeout source. Typically this will be in the
|
||||||
|
* range between #G_PRIORITY_DEFAULT_IDLE and #G_PRIORITY_HIGH_IDLE
|
||||||
|
* @func: function to call
|
||||||
|
* @data: data to pass to the function
|
||||||
|
* @notify: functio to call when the idle source is removed
|
||||||
|
*
|
||||||
|
* Adds a function to be called whenever there are no higher priority
|
||||||
|
* events pending. If the function returns %FALSE it is automatically
|
||||||
|
* removed from the list of event sources and will not be called again.
|
||||||
|
*
|
||||||
|
* This variant of g_idle_add_full() calls @function with the Clutter lock
|
||||||
|
* held. It can be thought of a MT-safe version for Clutter actors for the
|
||||||
|
* following use case, where you have to worry about idle_callback()
|
||||||
|
* running in thread A and accessing @self after it has been finalized
|
||||||
|
* in thread B:
|
||||||
|
*
|
||||||
|
* <informalexample><programlisting>
|
||||||
|
* static gboolean
|
||||||
|
* idle_callback (gpointer data)
|
||||||
|
* {
|
||||||
|
* // clutter_threads_enter(); would be needed for g_idle_add()
|
||||||
|
*
|
||||||
|
* SomeActor *self = data;
|
||||||
|
* /<!-- -->* do stuff with self *<!-- -->/
|
||||||
|
*
|
||||||
|
* self->idle_id = 0;
|
||||||
|
*
|
||||||
|
* // clutter_threads_leave(); would be needed for g_idle_add()
|
||||||
|
* return FALSE;
|
||||||
|
* }
|
||||||
|
* static void
|
||||||
|
* some_actor_do_stuff_later (SomeActor *self)
|
||||||
|
* {
|
||||||
|
* self->idle_id = clutter_threads_add_idle (idle_callback, self)
|
||||||
|
* // using g_idle_add() here would require thread protection in the callback
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* static void
|
||||||
|
* some_actor_finalize (GObject *object)
|
||||||
|
* {
|
||||||
|
* SomeActor *self = SOME_ACTOR (object);
|
||||||
|
* if (self->idle_id)
|
||||||
|
* g_source_remove (self->idle_id);
|
||||||
|
* G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
|
* }
|
||||||
|
* </programlisting></informalexample>
|
||||||
|
*
|
||||||
|
* Return value: the ID (greater than 0) of the event source.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
clutter_threads_add_idle_full (gint priority,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
ClutterThreadsDispatch *dispatch;
|
||||||
|
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
dispatch = g_slice_new (ClutterThreadsDispatch);
|
||||||
|
dispatch->func = func;
|
||||||
|
dispatch->data = data;
|
||||||
|
dispatch->notify = notify;
|
||||||
|
|
||||||
|
return g_idle_add_full (priority,
|
||||||
|
clutter_threads_dispatch, dispatch,
|
||||||
|
clutter_threads_dispatch_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_add_idle:
|
||||||
|
* @func: function to call
|
||||||
|
* @data: data to pass to the function
|
||||||
|
*
|
||||||
|
* Simple wrapper around clutter_threads_add_idle_full()
|
||||||
|
*
|
||||||
|
* Return value: the ID (greater than 0) of the event source.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
clutter_threads_add_idle (GSourceFunc func,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
return clutter_threads_add_idle_full (G_PRIORITY_DEFAULT_IDLE,
|
||||||
|
func, data,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_add_timeout_full:
|
||||||
|
* @priority: the priority of the timeout source. Typically this will be in the
|
||||||
|
* range between #G_PRIORITY_DEFAULT and #G_PRIORITY_HIGH.
|
||||||
|
* @interval: the time between calls to the function, in milliseconds
|
||||||
|
* @func: function to call
|
||||||
|
* @data: data to pass to the function
|
||||||
|
* @notify: function to call when the timeout source is removed
|
||||||
|
*
|
||||||
|
* Sets a function to be called at regular intervals holding the Clutter lock,
|
||||||
|
* with the given priority. The function is called repeatedly until it
|
||||||
|
* returns %FALSE, at which point the timeout is automatically destroyed
|
||||||
|
* and the function will not be called again. The @notify function is
|
||||||
|
* called when the timeout is destroyed. The first call to the
|
||||||
|
* function will be at the end of the first @interval.
|
||||||
|
*
|
||||||
|
* Note that timeout functions may be delayed, due to the processing of other
|
||||||
|
* event sources. Thus they should not be relied on for precise timing.
|
||||||
|
* After each call to the timeout function, the time of the next
|
||||||
|
* timeout is recalculated based on the current time and the given interval
|
||||||
|
* (it does not try to 'catch up' time lost in delays).
|
||||||
|
*
|
||||||
|
* This variant of g_timeout_add_full() can be thought of a MT-safe version
|
||||||
|
* for Clutter actors. See also clutter_threads_add_idle_full().
|
||||||
|
*
|
||||||
|
* Return value: the ID (greater than 0) of the event source.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
clutter_threads_add_timeout_full (gint priority,
|
||||||
|
guint interval,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
ClutterThreadsDispatch *dispatch;
|
||||||
|
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
dispatch = g_slice_new (ClutterThreadsDispatch);
|
||||||
|
dispatch->func = func;
|
||||||
|
dispatch->data = data;
|
||||||
|
dispatch->notify = notify;
|
||||||
|
|
||||||
|
return g_timeout_add_full (priority,
|
||||||
|
interval,
|
||||||
|
clutter_threads_dispatch, dispatch,
|
||||||
|
clutter_threads_dispatch_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_add_timeout:
|
||||||
|
* @interval: the time between calls to the function, in milliseconds
|
||||||
|
* @func: function to call
|
||||||
|
* @data: data to pass to the function
|
||||||
|
*
|
||||||
|
* Simple wrapper around clutter_threads_add_timeout_full().
|
||||||
|
*
|
||||||
|
* Return value: the ID (greater than 0) of the event source.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
clutter_threads_add_timeout (guint interval,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
return clutter_threads_add_timeout_full (G_PRIORITY_DEFAULT,
|
||||||
|
interval,
|
||||||
|
func, data,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_enter:
|
||||||
|
*
|
||||||
|
* Locks the Clutter thread lock.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_threads_enter (void)
|
||||||
|
{
|
||||||
|
if (clutter_threads_lock)
|
||||||
|
(* clutter_threads_lock) ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_threads_leave:
|
||||||
|
*
|
||||||
|
* Unlocks the Clutter thread lock.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_threads_leave (void)
|
||||||
|
{
|
||||||
|
if (clutter_threads_unlock)
|
||||||
|
(* clutter_threads_unlock) ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_get_debug_enabled:
|
* clutter_get_debug_enabled:
|
||||||
*
|
*
|
||||||
@ -410,8 +742,6 @@ pre_parse_hook (GOptionContext *context,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
clutter_context = clutter_context_get_default ();
|
||||||
clutter_context->main_loops = NULL;
|
|
||||||
clutter_context->main_loop_level = 0;
|
|
||||||
|
|
||||||
clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
|
clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
|
||||||
pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0);
|
pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0);
|
||||||
@ -568,11 +898,11 @@ clutter_init_with_args (int *argc,
|
|||||||
if (clutter_is_initialized)
|
if (clutter_is_initialized)
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return CLUTTER_INIT_SUCCESS;
|
||||||
|
|
||||||
|
clutter_base_init ();
|
||||||
|
|
||||||
if (argc && *argc > 0 && *argv)
|
if (argc && *argc > 0 && *argv)
|
||||||
g_set_prgname ((*argv)[0]);
|
g_set_prgname ((*argv)[0]);
|
||||||
|
|
||||||
clutter_base_init ();
|
|
||||||
|
|
||||||
group = clutter_get_option_group ();
|
group = clutter_get_option_group ();
|
||||||
context = g_option_context_new (parameter_string);
|
context = g_option_context_new (parameter_string);
|
||||||
|
|
||||||
@ -664,10 +994,11 @@ clutter_init (int *argc,
|
|||||||
if (clutter_is_initialized)
|
if (clutter_is_initialized)
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return CLUTTER_INIT_SUCCESS;
|
||||||
|
|
||||||
|
clutter_base_init ();
|
||||||
|
|
||||||
if (argc && *argc > 0 && *argv)
|
if (argc && *argc > 0 && *argv)
|
||||||
g_set_prgname ((*argv)[0]);
|
g_set_prgname ((*argv)[0]);
|
||||||
|
|
||||||
clutter_base_init ();
|
|
||||||
|
|
||||||
/* parse_args will trigger backend creation and things like
|
/* parse_args will trigger backend creation and things like
|
||||||
* DISPLAY connection etc.
|
* DISPLAY connection etc.
|
||||||
@ -734,6 +1065,8 @@ clutter_base_init (void)
|
|||||||
|
|
||||||
/* initialise GLib type system */
|
/* initialise GLib type system */
|
||||||
g_type_init ();
|
g_type_init ();
|
||||||
|
|
||||||
|
/* CLUTTER_TYPE_ACTOR */
|
||||||
foo = clutter_actor_get_type ();
|
foo = clutter_actor_get_type ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,8 @@ typedef enum {
|
|||||||
|
|
||||||
GQuark clutter_init_error_quark (void);
|
GQuark clutter_init_error_quark (void);
|
||||||
|
|
||||||
|
/* Initialisation */
|
||||||
|
void clutter_base_init (void);
|
||||||
ClutterInitError clutter_init (int *argc,
|
ClutterInitError clutter_init (int *argc,
|
||||||
char ***argv);
|
char ***argv);
|
||||||
ClutterInitError clutter_init_with_args (int *argc,
|
ClutterInitError clutter_init_with_args (int *argc,
|
||||||
@ -63,22 +65,41 @@ ClutterInitError clutter_init_with_args (int *argc,
|
|||||||
GOptionEntry *entries,
|
GOptionEntry *entries,
|
||||||
char *translation_domain,
|
char *translation_domain,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GOptionGroup * clutter_get_option_group (void);
|
GOptionGroup * clutter_get_option_group (void);
|
||||||
|
|
||||||
|
/* Mainloop */
|
||||||
void clutter_main (void);
|
void clutter_main (void);
|
||||||
void clutter_main_quit (void);
|
void clutter_main_quit (void);
|
||||||
gint clutter_main_level (void);
|
gint clutter_main_level (void);
|
||||||
|
|
||||||
void clutter_redraw (void);
|
void clutter_redraw (void);
|
||||||
|
|
||||||
|
/* Debug utility functions */
|
||||||
gboolean clutter_get_debug_enabled (void);
|
gboolean clutter_get_debug_enabled (void);
|
||||||
gboolean clutter_get_show_fps (void);
|
gboolean clutter_get_show_fps (void);
|
||||||
|
|
||||||
void clutter_base_init (void);
|
|
||||||
|
|
||||||
gulong clutter_get_timestamp (void);
|
gulong clutter_get_timestamp (void);
|
||||||
|
|
||||||
|
/* Threading functions */
|
||||||
|
void clutter_threads_init (void);
|
||||||
|
void clutter_threads_enter (void);
|
||||||
|
void clutter_threads_leave (void);
|
||||||
|
void clutter_threads_set_lock_functions (GCallback enter_fn,
|
||||||
|
GCallback leave_fn);
|
||||||
|
guint clutter_threads_add_idle (GSourceFunc func,
|
||||||
|
gpointer data);
|
||||||
|
guint clutter_threads_add_idle_full (gint priority,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
guint clutter_threads_add_timeout (guint interval,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data);
|
||||||
|
guint clutter_threads_add_timeout_full (gint priority,
|
||||||
|
guint interval,
|
||||||
|
GSourceFunc func,
|
||||||
|
gpointer data,
|
||||||
|
GDestroyNotify notify);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif /* _HAVE_CLUTTER_MAIN_H */
|
||||||
|
@ -47,15 +47,19 @@ typedef struct _ClutterMainContext ClutterMainContext;
|
|||||||
|
|
||||||
struct _ClutterMainContext
|
struct _ClutterMainContext
|
||||||
{
|
{
|
||||||
/* holds a pointer to the stage */
|
/* holds a pointer to the backend, which controls the stage */
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
|
|
||||||
|
/* the main event queue */
|
||||||
GQueue *events_queue;
|
GQueue *events_queue;
|
||||||
|
|
||||||
PangoFT2FontMap *font_map;
|
PangoFT2FontMap *font_map;
|
||||||
|
|
||||||
guint update_idle;
|
guint update_idle;
|
||||||
guint main_loop_level;
|
|
||||||
GSList *main_loops;
|
|
||||||
guint is_initialized : 1;
|
guint is_initialized : 1;
|
||||||
guint pick_mode :1; /* Indicates pick render mode */
|
guint pick_mode : 1; /* Indicates pick render mode */
|
||||||
|
|
||||||
GTimer *timer; /* Used for debugging scheduler */
|
GTimer *timer; /* Used for debugging scheduler */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ timeout_add (guint interval,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = g_timeout_add_full (CLUTTER_TIMELINE_PRIORITY,
|
res = clutter_threads_add_timeout_full (CLUTTER_TIMELINE_PRIORITY,
|
||||||
interval,
|
interval,
|
||||||
func, data, notify);
|
func, data, notify);
|
||||||
}
|
}
|
||||||
|
@ -183,12 +183,16 @@ static gboolean
|
|||||||
clutter_timeout_dispatch (GSource *source,
|
clutter_timeout_dispatch (GSource *source,
|
||||||
ClutterTimeout *timeout)
|
ClutterTimeout *timeout)
|
||||||
{
|
{
|
||||||
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
if (G_UNLIKELY (!timeout->func))
|
if (G_UNLIKELY (!timeout->func))
|
||||||
{
|
{
|
||||||
g_warning ("Timeout dispatched without a callback.");
|
g_warning ("Timeout dispatched without a callback.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
if (timeout->func (timeout->data))
|
if (timeout->func (timeout->data))
|
||||||
{
|
{
|
||||||
GTimeVal current_time;
|
GTimeVal current_time;
|
||||||
@ -196,10 +200,12 @@ clutter_timeout_dispatch (GSource *source,
|
|||||||
g_source_get_current_time (source, ¤t_time);
|
g_source_get_current_time (source, ¤t_time);
|
||||||
clutter_timeout_set_expiration (timeout, ¤t_time);
|
clutter_timeout_set_expiration (timeout, ¤t_time);
|
||||||
|
|
||||||
return TRUE;
|
retval = TRUE;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return FALSE;
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterTimeout *
|
static ClutterTimeout *
|
||||||
|
@ -150,10 +150,16 @@ clutter_event_prepare (GSource *source,
|
|||||||
gint *timeout)
|
gint *timeout)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
|
retval = clutter_events_pending ();
|
||||||
|
|
||||||
return clutter_events_pending ();
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -161,9 +167,16 @@ clutter_event_check (GSource *source)
|
|||||||
{
|
{
|
||||||
ClutterEventSource *event_source = (ClutterEventSource *) source;
|
ClutterEventSource *event_source = (ClutterEventSource *) source;
|
||||||
ClutterBackend *backend = event_source->backend;
|
ClutterBackend *backend = event_source->backend;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
return ((event_source->event_poll_fd.revents & G_IO_IN)
|
clutter_threads_enter ();
|
||||||
|| clutter_events_pending ());
|
|
||||||
|
retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
|
||||||
|
clutter_events_pending ());
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -178,6 +191,8 @@ clutter_event_dispatch (GSource *source,
|
|||||||
ClutterMainContext *clutter_context;
|
ClutterMainContext *clutter_context;
|
||||||
static gint last_x, last_y;
|
static gint last_x, last_y;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
clutter_context = clutter_context_get_default ();
|
||||||
#ifdef HAVE_TSLIB
|
#ifdef HAVE_TSLIB
|
||||||
/* FIXME while would be better here but need to deal with lockups */
|
/* FIXME while would be better here but need to deal with lockups */
|
||||||
@ -190,7 +205,7 @@ clutter_event_dispatch (GSource *source,
|
|||||||
* and triple clicks.
|
* and triple clicks.
|
||||||
*/
|
*/
|
||||||
if (tsevent.pressure && last_x == tsevent.x && last_y == tsevent.y)
|
if (tsevent.pressure && last_x == tsevent.x && last_y == tsevent.y)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
event = clutter_event_new (CLUTTER_NOTHING);
|
event = clutter_event_new (CLUTTER_NOTHING);
|
||||||
|
|
||||||
@ -223,5 +238,8 @@ clutter_event_dispatch (GSource *source,
|
|||||||
clutter_event_free (event);
|
clutter_event_free (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -326,9 +326,13 @@ clutter_event_prepare (GSource *source,
|
|||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,11 +343,15 @@ clutter_event_check (GSource *source)
|
|||||||
ClutterBackend *backend = event_source->backend;
|
ClutterBackend *backend = event_source->backend;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
if (event_source->event_poll_fd.revents & G_IO_IN)
|
if (event_source->event_poll_fd.revents & G_IO_IN)
|
||||||
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
retval = (clutter_events_pending () || clutter_check_xpending (backend));
|
||||||
else
|
else
|
||||||
retval = FALSE;
|
retval = FALSE;
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,6 +363,8 @@ clutter_event_dispatch (GSource *source,
|
|||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
ClutterEvent *event;
|
ClutterEvent *event;
|
||||||
|
|
||||||
|
clutter_thread_enter ();
|
||||||
|
|
||||||
events_queue (backend);
|
events_queue (backend);
|
||||||
|
|
||||||
event = clutter_event_get ();
|
event = clutter_event_get ();
|
||||||
@ -365,5 +375,7 @@ clutter_event_dispatch (GSource *source,
|
|||||||
clutter_event_free (event);
|
clutter_event_free (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -549,9 +549,13 @@ clutter_event_prepare (GSource *source,
|
|||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
retval = (clutter_events_pending () || check_xpending (backend));
|
retval = (clutter_events_pending () || check_xpending (backend));
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,11 +566,15 @@ clutter_event_check (GSource *source)
|
|||||||
ClutterBackend *backend = event_source->backend;
|
ClutterBackend *backend = event_source->backend;
|
||||||
gboolean retval;
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
if (event_source->event_poll_fd.revents & G_IO_IN)
|
if (event_source->event_poll_fd.revents & G_IO_IN)
|
||||||
retval = (clutter_events_pending () || check_xpending (backend));
|
retval = (clutter_events_pending () || check_xpending (backend));
|
||||||
else
|
else
|
||||||
retval = FALSE;
|
retval = FALSE;
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,6 +586,8 @@ clutter_event_dispatch (GSource *source,
|
|||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
ClutterEvent *event;
|
ClutterEvent *event;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
/* Grab the event(s), translate and figure out double click.
|
/* Grab the event(s), translate and figure out double click.
|
||||||
* The push onto queue (stack) if valid.
|
* The push onto queue (stack) if valid.
|
||||||
*/
|
*/
|
||||||
@ -593,5 +603,7 @@ clutter_event_dispatch (GSource *source,
|
|||||||
clutter_event_free (event);
|
clutter_event_free (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -112,11 +112,16 @@ clutter_event_prepare (GSource *source,
|
|||||||
{
|
{
|
||||||
SDL_Event events;
|
SDL_Event events;
|
||||||
int num_events;
|
int num_events;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
num_events = SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
|
num_events = SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
|
||||||
|
|
||||||
if (num_events == 1)
|
if (num_events == 1)
|
||||||
{
|
{
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
*timeout = 0;
|
*timeout = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -126,7 +131,11 @@ clutter_event_prepare (GSource *source,
|
|||||||
|
|
||||||
*timeout = 50;
|
*timeout = 50;
|
||||||
|
|
||||||
return clutter_events_pending ();
|
retval = clutter_events_pending ();
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -134,6 +143,9 @@ clutter_event_check (GSource *source)
|
|||||||
{
|
{
|
||||||
SDL_Event events;
|
SDL_Event events;
|
||||||
int num_events;
|
int num_events;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
/* Pump SDL */
|
/* Pump SDL */
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
@ -143,7 +155,11 @@ clutter_event_check (GSource *source)
|
|||||||
if (num_events == -1)
|
if (num_events == -1)
|
||||||
g_warning("Error polling SDL: %s", SDL_GetError());
|
g_warning("Error polling SDL: %s", SDL_GetError());
|
||||||
|
|
||||||
return (num_events == 1 || clutter_events_pending ());
|
retval = (num_events == 1 || clutter_events_pending ());
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -292,6 +308,8 @@ clutter_event_dispatch (GSource *source,
|
|||||||
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
|
||||||
ClutterMainContext *clutter_context;
|
ClutterMainContext *clutter_context;
|
||||||
|
|
||||||
|
clutter_threads_enter ();
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
clutter_context = clutter_context_get_default ();
|
||||||
|
|
||||||
while (SDL_PollEvent(&sdl_event))
|
while (SDL_PollEvent(&sdl_event))
|
||||||
@ -328,5 +346,7 @@ clutter_event_dispatch (GSource *source,
|
|||||||
clutter_event_free (event);
|
clutter_event_free (event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clutter_threads_leave ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# An odd micro number indicates in-progress development, (eg. from CVS)
|
# An odd micro number indicates in-progress development, (eg. from CVS)
|
||||||
# An even micro number indicates a released version.
|
# An even micro number indicates a released version.
|
||||||
m4_define([clutter_major_version], [0])
|
m4_define([clutter_major_version], [0])
|
||||||
m4_define([clutter_minor_version], [4])
|
m4_define([clutter_minor_version], [5])
|
||||||
m4_define([clutter_micro_version], [0])
|
m4_define([clutter_micro_version], [0])
|
||||||
|
|
||||||
m4_define([clutter_version],
|
m4_define([clutter_version],
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2007-08-08 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
* clutter-sections.txt: Add the new clutter_threads_* API.
|
||||||
|
|
||||||
2007-08-07 Emmanuele Bassi <ebassi@openedhand.com>
|
2007-08-07 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
* clutter-sections.txt: Shuffle around a bit the symbols.
|
* clutter-sections.txt: Shuffle around a bit the symbols.
|
||||||
|
@ -828,12 +828,23 @@ ClutterInitError
|
|||||||
clutter_init
|
clutter_init
|
||||||
clutter_init_with_args
|
clutter_init_with_args
|
||||||
clutter_get_option_group
|
clutter_get_option_group
|
||||||
clutter_get_debug_enabled
|
<SUBSECTION>
|
||||||
clutter_get_show_fps
|
|
||||||
clutter_main
|
clutter_main
|
||||||
clutter_main_quit
|
clutter_main_quit
|
||||||
clutter_main_level
|
clutter_main_level
|
||||||
|
<SUBSECTION>
|
||||||
|
clutter_get_debug_enabled
|
||||||
|
clutter_get_show_fps
|
||||||
clutter_get_timestamp
|
clutter_get_timestamp
|
||||||
|
<SUBSECTION>
|
||||||
|
clutter_threads_set_lock_functions
|
||||||
|
clutter_threads_init
|
||||||
|
clutter_threads_enter
|
||||||
|
clutter_threads_leave
|
||||||
|
clutter_threads_add_idle
|
||||||
|
clutter_threads_add_idle_full
|
||||||
|
clutter_threads_add_timeout
|
||||||
|
clutter_threads_add_timeout_full
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
CLUTTER_INIT_ERROR
|
CLUTTER_INIT_ERROR
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
|
noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
|
||||||
test-actors test-behave test-text test-entry test-project \
|
test-actors test-behave test-text test-entry test-project \
|
||||||
test-boxes test-perspective test-rotate test-depth
|
test-boxes test-perspective test-rotate test-depth \
|
||||||
|
test-threads
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/
|
INCLUDES = -I$(top_srcdir)/
|
||||||
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||||
@ -20,5 +21,6 @@ test_boxes_SOURCES = test-boxes.c
|
|||||||
test_perspective_SOURCES = test-perspective.c
|
test_perspective_SOURCES = test-perspective.c
|
||||||
test_rotate_SOURCES = test-rotate.c
|
test_rotate_SOURCES = test-rotate.c
|
||||||
test_depth_SOURCES = test-depth.c
|
test_depth_SOURCES = test-depth.c
|
||||||
|
test_threads_SOURCES = test-threads.c
|
||||||
|
|
||||||
EXTRA_DIST = redhand.png
|
EXTRA_DIST = redhand.png
|
||||||
|
@ -234,7 +234,7 @@ main (int argc, char *argv[])
|
|||||||
/* and start it */
|
/* and start it */
|
||||||
clutter_timeline_start (timeline);
|
clutter_timeline_start (timeline);
|
||||||
|
|
||||||
clutter_main();
|
clutter_main ();
|
||||||
|
|
||||||
g_free (oh->hand);
|
g_free (oh->hand);
|
||||||
g_free (oh);
|
g_free (oh);
|
||||||
|
Loading…
Reference in New Issue
Block a user