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>
* 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.. */
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)
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);

View File

@ -47,6 +47,25 @@
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 */
static ClutterBackendX11 *backend_singleton = NULL;
@ -101,6 +120,7 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
if (backend_x11->xdpy)
{
Atom atoms[n_atom_names];
double dpi;
CLUTTER_NOTE (BACKEND, "Getting the X screen");
@ -126,10 +146,20 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
if (clutter_synchronise)
XSynchronize (backend_x11->xdpy, True);
backend_x11->atom_WM_STATE
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE", False);
backend_x11->atom_WM_STATE_FULLSCREEN
= XInternAtom (backend_x11->xdpy, "_NET_WM_STATE_FULLSCREEN", False);
XInternAtoms (backend_x11->xdpy,
(char **) atom_names, n_atom_names,
False, atoms);
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);

View File

@ -67,8 +67,16 @@ struct _ClutterBackendX11
GSList *event_filters;
/* props */
Atom atom_WM_STATE;
Atom atom_WM_STATE_FULLSCREEN;
Atom atom_NET_WM_PING;
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

View File

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

View File

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

View File

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

View File

@ -86,10 +86,11 @@ frame_cb (ClutterTimeline *timeline,
gint i;
/* Rotate everything clockwise about stage center*/
clutter_actor_rotate_z (CLUTTER_ACTOR (oh->group),
frame_num,
CLUTTER_STAGE_WIDTH() / 2,
CLUTTER_STAGE_HEIGHT() / 2);
clutter_actor_set_rotation (CLUTTER_ACTOR (oh->group), frame_num,
CLUTTER_Z_AXIS,
CLUTTER_STAGE_WIDTH() / 2,
CLUTTER_STAGE_HEIGHT() / 2,
0);
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
* unit based functions to fix.
*/
clutter_actor_rotate_z
(oh->hand[i],
- 6.0 * frame_num,
clutter_actor_set_rotation (oh->hand[i], - 6.0 * frame_num,
CLUTTER_Z_AXIS,
#if 0
(clutter_actor_get_width (oh->hand[i]) / 2) * scale_x,
(clutter_actor_get_height (oh->hand[i]) / 2) * scale_y
#endif
(clutter_actor_get_height (oh->hand[i]) / 2) * scale_y,
#else
(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)
g_error("pixbuf load failed");
clutter_stage_set_title (CLUTTER_STAGE (stage), "Actors Test");
clutter_stage_set_color (CLUTTER_STAGE (stage),
&stage_color);