2007-11-17 Emmanuele Bassi <ebassi@openedhand.com>

Optimise Atoms usage in the X11 and X11-based backends.

	* clutter/x11/clutter-backend-x11.c:
This commit is contained in:
Emmanuele Bassi 2007-11-17 18:11:14 +00:00
parent 3282e6ceb2
commit b7a79cf198
8 changed files with 143 additions and 95 deletions

View File

@ -1,3 +1,36 @@
2007-11-17 Emmanuele Bassi <ebassi@openedhand.com>
Optimise Atoms usage in the X11 and X11-based backends.
* clutter/x11/clutter-backend-x11.c:
(clutter_backend_x11_post_parse): Call XInternAtoms() here and
get all the atoms from X in one call.
* clutter/x11/clutter-backend-x11.h: Store all the atoms inside
the ClutterBackendX11 structure.
* clutter/x11/clutter-event-x11.c:
(xembed_send_message), (xembed_set_info),
(_clutter_backend_x11_events_init),
(set_user_time), (handle_wm_protocols_event),
(handle_xembed_event), (event_translate): Do not cache atoms
or call XInternAtom() directly, and use the atoms off the X11
backend structure instead.
* clutter/x11/clutter-stage-x11.c:
(send_wmspec_change_state), (clutter_stage_x11_set_wm_protocols),
(clutter_stage_x11_set_fullscreen),
(clutter_stage_x11_set_title): Ditto as above.
* clutter/x11/clutter-stage-x11.h: Update the set_wm_protocols()
method to take the X11 stage implementation.
* clutter/glx/clutter-stage-glx.c:
(clutter_stage_glx_realize): Update for the set_wm_protocols()
change.
* tests/test-project.c: (main): Test clutter_stage_set_title().
2007-11-17 Emmanuele Bassi <ebassi@openedhand.com> 2007-11-17 Emmanuele Bassi <ebassi@openedhand.com>
* configure.ac: Depend on GLib >= 2.14 because of ClutterModel * configure.ac: Depend on GLib >= 2.14 because of ClutterModel

View File

@ -180,7 +180,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
/* no user resize.. */ /* no user resize.. */
clutter_stage_x11_fix_window_size (stage_x11); clutter_stage_x11_fix_window_size (stage_x11);
clutter_stage_x11_set_wm_protocols (stage_x11->xdpy, stage_x11->xwin); clutter_stage_x11_set_wm_protocols (stage_x11);
if (stage_glx->gl_context) if (stage_glx->gl_context)
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context); glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);

View File

@ -47,6 +47,25 @@
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND); G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
/* atoms; remember to add the code that assigns the atom value to
* the member of the ClutterBackendX11 structure if you add an
* atom name here. do not change the order!
*/
static const gchar *atom_names[] = {
"_NET_WM_PING",
"_NET_WM_STATE",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_USER_TIME",
"WM_PROTOCOLS",
"WM_DELETE_WINDOW",
"_XEMBED",
"_XEMBED_INFO",
"_NET_WM_NAME",
"UTF8_STRING",
};
static const guint n_atom_names = G_N_ELEMENTS (atom_names);
/* singleton object */ /* singleton object */
static ClutterBackendX11 *backend_singleton = NULL; static ClutterBackendX11 *backend_singleton = NULL;
@ -101,6 +120,7 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
if (backend_x11->xdpy) if (backend_x11->xdpy)
{ {
Atom atoms[n_atom_names];
double dpi; double dpi;
CLUTTER_NOTE (BACKEND, "Getting the X screen"); CLUTTER_NOTE (BACKEND, "Getting the X screen");
@ -126,10 +146,20 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
if (clutter_synchronise) if (clutter_synchronise)
XSynchronize (backend_x11->xdpy, True); XSynchronize (backend_x11->xdpy, True);
backend_x11->atom_WM_STATE XInternAtoms (backend_x11->xdpy,
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE", False); (char **) atom_names, n_atom_names,
backend_x11->atom_WM_STATE_FULLSCREEN False, atoms);
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE_FULLSCREEN", False);
backend_x11->atom_NET_WM_PING = atoms[0];
backend_x11->atom_NET_WM_STATE = atoms[1];
backend_x11->atom_NET_WM_STATE_FULLSCREEN = atoms[2];
backend_x11->atom_NET_WM_USER_TIME = atoms[3];
backend_x11->atom_WM_PROTOCOLS = atoms[4];
backend_x11->atom_WM_DELETE_WINDOW = atoms[5];
backend_x11->atom_XEMBED = atoms[6];
backend_x11->atom_XEMBED_INFO = atoms[7];
backend_x11->atom_NET_WM_NAME = atoms[8];
backend_x11->atom_UTF8_STRING = atoms[9];
} }
g_free (clutter_display_name); g_free (clutter_display_name);

View File

@ -67,8 +67,16 @@ struct _ClutterBackendX11
GSList *event_filters; GSList *event_filters;
/* props */ /* props */
Atom atom_WM_STATE; Atom atom_NET_WM_PING;
Atom atom_WM_STATE_FULLSCREEN; Atom atom_NET_WM_STATE;
Atom atom_NET_WM_STATE_FULLSCREEN;
Atom atom_NET_WM_USER_TIME;
Atom atom_WM_PROTOCOLS;
Atom atom_WM_DELETE_WINDOW;
Atom atom_XEMBED;
Atom atom_XEMBED_INFO;
Atom atom_NET_WM_NAME;
Atom atom_UTF8_STRING;
}; };
struct _ClutterBackendX11Class struct _ClutterBackendX11Class

View File

@ -60,9 +60,6 @@
#define XEMBED_UNREGISTER_ACCELERATOR 13 #define XEMBED_UNREGISTER_ACCELERATOR 13
#define XEMBED_ACTIVATE_ACCELERATOR 14 #define XEMBED_ACTIVATE_ACCELERATOR 14
static Atom Atom_XEMBED = 0;
static Atom Atom_WM_PROTOCOLS = 0;
static Window ParentEmbedderWin = None; static Window ParentEmbedderWin = None;
typedef struct _ClutterEventSource ClutterEventSource; typedef struct _ClutterEventSource ClutterEventSource;
@ -109,12 +106,12 @@ check_xpending (ClutterBackend *backend)
} }
static gboolean static gboolean
xembed_send_message (Display *xdisplay, xembed_send_message (ClutterBackendX11 *backend_x11,
Window window, Window window,
long message, long message,
long detail, long detail,
long data1, long data1,
long data2) long data2)
{ {
XEvent ev; XEvent ev;
@ -122,7 +119,7 @@ xembed_send_message (Display *xdisplay,
ev.xclient.type = ClientMessage; ev.xclient.type = ClientMessage;
ev.xclient.window = window; ev.xclient.window = window;
ev.xclient.message_type = Atom_XEMBED; ev.xclient.message_type = backend_x11->atom_XEMBED;
ev.xclient.format = 32; ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime; ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = message; ev.xclient.data.l[1] = message;
@ -132,8 +129,8 @@ xembed_send_message (Display *xdisplay,
clutter_x11_trap_x_errors (); clutter_x11_trap_x_errors ();
XSendEvent (xdisplay, window, False, NoEventMask, &ev); XSendEvent (backend_x11->xdpy, window, False, NoEventMask, &ev);
XSync (xdisplay, False); XSync (backend_x11->xdpy, False);
if (clutter_x11_untrap_x_errors ()) if (clutter_x11_untrap_x_errors ())
return False; return False;
@ -142,22 +139,19 @@ xembed_send_message (Display *xdisplay,
} }
static void static void
xembed_set_info (Display *xdisplay, xembed_set_info (ClutterBackendX11 *backend_x11,
Window window, Window window,
gint flags) gint flags)
{ {
gint32 list[2]; gint32 list[2];
Atom atom_XEMBED_INFO;
atom_XEMBED_INFO = XInternAtom (xdisplay, "_XEMBED_INFO", False);
list[0] = MAX_SUPPORTED_XEMBED_VERSION; list[0] = MAX_SUPPORTED_XEMBED_VERSION;
list[1] = XEMBED_MAPPED; list[1] = XEMBED_MAPPED;
clutter_x11_trap_x_errors (); clutter_x11_trap_x_errors ();
XChangeProperty (xdisplay, window, XChangeProperty (backend_x11->xdpy, window,
atom_XEMBED_INFO, backend_x11->atom_XEMBED_INFO,
atom_XEMBED_INFO, 32, backend_x11->atom_XEMBED_INFO, 32,
PropModeReplace, (unsigned char *) list, 2); PropModeReplace, (unsigned char *) list, 2);
clutter_x11_untrap_x_errors (); clutter_x11_untrap_x_errors ();
} }
@ -165,17 +159,15 @@ xembed_set_info (Display *xdisplay,
void void
_clutter_backend_x11_events_init (ClutterBackend *backend) _clutter_backend_x11_events_init (ClutterBackend *backend)
{ {
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage);
GSource *source; GSource *source;
ClutterEventSource *event_source; ClutterEventSource *event_source;
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
int connection_number; int connection_number;
connection_number = ConnectionNumber (backend_x11->xdpy); connection_number = ConnectionNumber (backend_x11->xdpy);
CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number); CLUTTER_NOTE (EVENT, "Connection number: %d", connection_number);
Atom_XEMBED = XInternAtom (backend_x11->xdpy, "_XEMBED", False);
Atom_WM_PROTOCOLS = XInternAtom (backend_x11->xdpy, "WM_PROTOCOLS", False);
source = backend_x11->event_source = clutter_event_source_new (backend); source = backend_x11->event_source = clutter_event_source_new (backend);
event_source = (ClutterEventSource *) source; event_source = (ClutterEventSource *) source;
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
@ -189,9 +181,8 @@ _clutter_backend_x11_events_init (ClutterBackend *backend)
g_source_set_can_recurse (source, TRUE); g_source_set_can_recurse (source, TRUE);
g_source_attach (source, NULL); g_source_attach (source, NULL);
xembed_set_info (backend_x11->xdpy, xembed_set_info (backend_x11,
clutter_x11_get_stage_window clutter_x11_get_stage_window (stage),
(CLUTTER_STAGE (backend_x11->stage)),
0); 0);
} }
@ -214,18 +205,14 @@ _clutter_backend_x11_events_uninit (ClutterBackend *backend)
} }
static void static void
set_user_time (Display *display, set_user_time (ClutterBackendX11 *backend_x11,
Window *xwindow, Window *xwindow,
long timestamp) long timestamp)
{ {
if (timestamp != CLUTTER_CURRENT_TIME) if (timestamp != CLUTTER_CURRENT_TIME)
{ {
Atom atom_WM_USER_TIME; XChangeProperty (backend_x11->xdpy, *xwindow,
backend_x11->atom_NET_WM_USER_TIME,
atom_WM_USER_TIME = XInternAtom (display, "_NET_WM_USER_TIME", False);
XChangeProperty (display, *xwindow,
atom_WM_USER_TIME,
XA_CARDINAL, 32, PropModeReplace, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) &timestamp, 1); (unsigned char *) &timestamp, 1);
} }
@ -258,18 +245,10 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
XEvent *xevent) XEvent *xevent)
{ {
Atom atom = (Atom) xevent->xclient.data.l[0]; Atom atom = (Atom) xevent->xclient.data.l[0];
Atom Atom_WM_DELETE_WINDOW;
Atom Atom_NEW_WM_PING;
ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage); ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage);
Window stage_xwindow = clutter_x11_get_stage_window (stage); Window stage_xwindow = clutter_x11_get_stage_window (stage);
Atom_WM_DELETE_WINDOW = XInternAtom (backend_x11->xdpy, if (atom == backend_x11->atom_WM_DELETE_WINDOW &&
"WM_DELETE_WINDOW",
False);
Atom_NEW_WM_PING = XInternAtom (backend_x11->xdpy, "_NET_WM_PING", False);
if (atom == Atom_WM_DELETE_WINDOW &&
xevent->xany.window == stage_xwindow) xevent->xany.window == stage_xwindow)
{ {
/* the WM_DELETE_WINDOW is a request: we do not destroy /* the WM_DELETE_WINDOW is a request: we do not destroy
@ -280,13 +259,13 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld", CLUTTER_NOTE (EVENT, "delete window:\twindow: %ld",
xevent->xclient.window); xevent->xclient.window);
set_user_time (backend_x11->xdpy, set_user_time (backend_x11,
&stage_xwindow, &stage_xwindow,
xevent->xclient.data.l[1]); xevent->xclient.data.l[1]);
return TRUE; return TRUE;
} }
else if (atom == Atom_NEW_WM_PING && else if (atom == backend_x11->atom_NET_WM_PING &&
xevent->xany.window == stage_xwindow) xevent->xany.window == stage_xwindow)
{ {
XClientMessageEvent xclient = xevent->xclient; XClientMessageEvent xclient = xevent->xclient;
@ -323,7 +302,7 @@ handle_xembed_event (ClutterBackendX11 *backend_x11,
clutter_actor_realize (stage); clutter_actor_realize (stage);
clutter_actor_show (stage); clutter_actor_show (stage);
xembed_set_info (backend_x11->xdpy, xembed_set_info (backend_x11,
clutter_x11_get_stage_window (CLUTTER_STAGE (stage)), clutter_x11_get_stage_window (CLUTTER_STAGE (stage)),
XEMBED_MAPPED); XEMBED_MAPPED);
break; break;
@ -336,7 +315,7 @@ handle_xembed_event (ClutterBackendX11 *backend_x11,
case XEMBED_FOCUS_IN: case XEMBED_FOCUS_IN:
CLUTTER_NOTE (EVENT, "got XEMBED_FOCUS_IN"); CLUTTER_NOTE (EVENT, "got XEMBED_FOCUS_IN");
if (ParentEmbedderWin) if (ParentEmbedderWin)
xembed_send_message (backend_x11->xdpy, ParentEmbedderWin, xembed_send_message (backend_x11, ParentEmbedderWin,
XEMBED_FOCUS_NEXT, XEMBED_FOCUS_NEXT,
0, 0, 0); 0, 0, 0);
break; break;
@ -412,7 +391,7 @@ event_translate (ClutterBackend *backend,
break; break;
case PropertyNotify: case PropertyNotify:
{ {
if (xevent->xproperty.atom == backend_x11->atom_WM_STATE) if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE)
{ {
Atom type; Atom type;
gint format; gint format;
@ -425,7 +404,7 @@ event_translate (ClutterBackend *backend,
clutter_x11_trap_x_errors (); clutter_x11_trap_x_errors ();
XGetWindowProperty (backend_x11->xdpy, XGetWindowProperty (backend_x11->xdpy,
stage_xwindow, stage_xwindow,
backend_x11->atom_WM_STATE, backend_x11->atom_NET_WM_STATE,
0, G_MAXLONG, 0, G_MAXLONG,
False, XA_ATOM, False, XA_ATOM,
&type, &format, &nitems, &type, &format, &nitems,
@ -439,7 +418,7 @@ event_translate (ClutterBackend *backend,
i = 0; i = 0;
while (i < nitems) while (i < nitems)
{ {
if (atoms[i] == backend_x11->atom_WM_STATE_FULLSCREEN) if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
fullscreen_set = TRUE; fullscreen_set = TRUE;
i++; i++;
} }
@ -512,7 +491,7 @@ event_translate (ClutterBackend *backend,
case KeyPress: case KeyPress:
event->type = CLUTTER_KEY_PRESS; event->type = CLUTTER_KEY_PRESS;
translate_key_event (backend, event, xevent); translate_key_event (backend, event, xevent);
set_user_time (backend_x11->xdpy, &xwindow, xevent->xkey.time); set_user_time (backend_x11, &xwindow, xevent->xkey.time);
break; break;
case KeyRelease: case KeyRelease:
event->type = CLUTTER_KEY_RELEASE; event->type = CLUTTER_KEY_RELEASE;
@ -553,7 +532,7 @@ event_translate (ClutterBackend *backend,
break; break;
} }
set_user_time (backend_x11->xdpy, &xwindow, event->button.time); set_user_time (backend_x11, &xwindow, event->button.time);
break; break;
case ButtonRelease: case ButtonRelease:
/* scroll events don't have a corresponding release */ /* scroll events don't have a corresponding release */
@ -590,9 +569,9 @@ event_translate (ClutterBackend *backend,
event->type = event->any.type = CLUTTER_CLIENT_MESSAGE; event->type = event->any.type = CLUTTER_CLIENT_MESSAGE;
if (xevent->xclient.message_type == Atom_XEMBED) if (xevent->xclient.message_type == backend_x11->atom_XEMBED)
res = handle_xembed_event (backend_x11, xevent); res = handle_xembed_event (backend_x11, xevent);
else if (xevent->xclient.message_type == Atom_WM_PROTOCOLS) else if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
{ {
res = handle_wm_protocols_event (backend_x11, xevent); res = handle_wm_protocols_event (backend_x11, xevent);
event->type = event->any.type = CLUTTER_DELETE; event->type = event->any.type = CLUTTER_DELETE;

View File

@ -63,7 +63,7 @@ send_wmspec_change_state (ClutterBackendX11 *backend_x11,
xclient.type = ClientMessage; xclient.type = ClientMessage;
xclient.window = window; xclient.window = window;
xclient.message_type = backend_x11->atom_WM_STATE; xclient.message_type = backend_x11->atom_NET_WM_STATE;
xclient.format = 32; xclient.format = 32;
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
@ -136,16 +136,16 @@ clutter_stage_x11_hide (ClutterActor *actor)
} }
void void
clutter_stage_x11_set_wm_protocols (Display *xdisplay, clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11)
Window xwindow)
{ {
ClutterBackendX11 *backend_x11 = stage_x11->backend;
Atom protocols[2]; Atom protocols[2];
int n = 0; int n = 0;
protocols[n++] = XInternAtom (xdisplay, "WM_DELETE_WINDOW", False); protocols[n++] = backend_x11->atom_WM_DELETE_WINDOW;
protocols[n++] = XInternAtom (xdisplay, "_NET_WM_PING", False); protocols[n++] = backend_x11->atom_NET_WM_PING;
XSetWMProtocols (xdisplay, xwindow, protocols, n); XSetWMProtocols (stage_x11->xdpy, stage_x11->xwin, protocols, n);
} }
static void static void
@ -228,9 +228,9 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
XChangeProperty XChangeProperty
(stage_x11->xdpy, (stage_x11->xdpy,
stage_x11->xwin, stage_x11->xwin,
backend_x11->atom_WM_STATE, XA_ATOM, 32, backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, PropModeReplace,
(unsigned char *)&backend_x11->atom_WM_STATE_FULLSCREEN, (unsigned char *)&backend_x11->atom_NET_WM_STATE_FULLSCREEN,
1); 1);
} }
else else
@ -245,7 +245,7 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
send_wmspec_change_state(backend_x11, send_wmspec_change_state(backend_x11,
stage_x11->xwin, stage_x11->xwin,
backend_x11->atom_WM_STATE_FULLSCREEN, backend_x11->atom_NET_WM_STATE_FULLSCREEN,
TRUE); TRUE);
} }
} }
@ -259,7 +259,7 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
/* FIXME: This wont work if we support more states */ /* FIXME: This wont work if we support more states */
XDeleteProperty (stage_x11->xdpy, XDeleteProperty (stage_x11->xdpy,
stage_x11->xwin, stage_x11->xwin,
backend_x11->atom_WM_STATE); backend_x11->atom_NET_WM_STATE);
} }
else else
{ {
@ -267,7 +267,7 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
send_wmspec_change_state(backend_x11, send_wmspec_change_state(backend_x11,
stage_x11->xwin, stage_x11->xwin,
backend_x11->atom_WM_STATE_FULLSCREEN, backend_x11->atom_NET_WM_STATE_FULLSCREEN,
FALSE); FALSE);
/* reset the windows state - this isn't fun - see above */ /* reset the windows state - this isn't fun - see above */
@ -331,27 +331,23 @@ clutter_stage_x11_set_title (ClutterStage *stage,
const gchar *title) const gchar *title)
{ {
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage); ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
Atom atom_NET_WM_NAME, atom_UTF8_STRING; ClutterBackendX11 *backend_x11 = stage_x11->backend;
if (stage_x11->xwin == None) if (stage_x11->xwin == None)
return; return;
/* FIXME: pre create these to avoid too many round trips */
atom_NET_WM_NAME = XInternAtom (stage_x11->xdpy, "_NET_WM_NAME", False);
atom_UTF8_STRING = XInternAtom (stage_x11->xdpy, "UTF8_STRING", False);
if (title == NULL) if (title == NULL)
{ {
XDeleteProperty (stage_x11->xdpy, XDeleteProperty (stage_x11->xdpy,
stage_x11->xwin, stage_x11->xwin,
atom_NET_WM_NAME); backend_x11->atom_NET_WM_NAME);
} }
else else
{ {
XChangeProperty (stage_x11->xdpy, XChangeProperty (stage_x11->xdpy,
stage_x11->xwin, stage_x11->xwin,
atom_NET_WM_NAME, backend_x11->atom_NET_WM_NAME,
atom_UTF8_STRING, backend_x11->atom_UTF8_STRING,
8, 8,
PropModeReplace, PropModeReplace,
(unsigned char*)title, (unsigned char*)title,

View File

@ -72,8 +72,7 @@ void
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11); clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11);
void void
clutter_stage_x11_set_wm_protocols (Display *xdisplay, clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
Window xwindow);
G_END_DECLS G_END_DECLS

View File

@ -86,10 +86,11 @@ frame_cb (ClutterTimeline *timeline,
gint i; gint i;
/* Rotate everything clockwise about stage center*/ /* Rotate everything clockwise about stage center*/
clutter_actor_rotate_z (CLUTTER_ACTOR (oh->group), clutter_actor_set_rotation (CLUTTER_ACTOR (oh->group), frame_num,
frame_num, CLUTTER_Z_AXIS,
CLUTTER_STAGE_WIDTH() / 2, CLUTTER_STAGE_WIDTH() / 2,
CLUTTER_STAGE_HEIGHT() / 2); CLUTTER_STAGE_HEIGHT() / 2,
0);
for (i = 0; i < n_hands; i++) for (i = 0; i < n_hands; i++)
{ {
@ -103,15 +104,16 @@ frame_cb (ClutterTimeline *timeline,
* FIXME: scaling causes drift so disabled for now. Need rotation * FIXME: scaling causes drift so disabled for now. Need rotation
* unit based functions to fix. * unit based functions to fix.
*/ */
clutter_actor_rotate_z clutter_actor_set_rotation (oh->hand[i], - 6.0 * frame_num,
(oh->hand[i], CLUTTER_Z_AXIS,
- 6.0 * frame_num,
#if 0 #if 0
(clutter_actor_get_width (oh->hand[i]) / 2) * scale_x, (clutter_actor_get_width (oh->hand[i]) / 2) * scale_x,
(clutter_actor_get_height (oh->hand[i]) / 2) * scale_y (clutter_actor_get_height (oh->hand[i]) / 2) * scale_y,
#endif #else
(clutter_actor_get_width (oh->hand[i]) / 2), (clutter_actor_get_width (oh->hand[i]) / 2),
(clutter_actor_get_height (oh->hand[i]) / 2)); (clutter_actor_get_height (oh->hand[i]) / 2),
#endif
0);
} }
} }
@ -152,6 +154,7 @@ main (int argc, char *argv[])
if (!pixbuf) if (!pixbuf)
g_error("pixbuf load failed"); g_error("pixbuf load failed");
clutter_stage_set_title (CLUTTER_STAGE (stage), "Actors Test");
clutter_stage_set_color (CLUTTER_STAGE (stage), clutter_stage_set_color (CLUTTER_STAGE (stage),
&stage_color); &stage_color);