Optimise Atoms usage in the X11 and X11-based backends.
* clutter/x11/clutter-backend-x11.c:
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
usage of GSequence.
/* 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);
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;
if (backend_x11->xdpy)
{
+ Atom atoms[n_atom_names];
double dpi;
CLUTTER_NOTE (BACKEND, "Getting the X screen");
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);
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
#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;
}
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;
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;
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;
}
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 ();
}
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);
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);
}
}
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 *) ×tamp, 1);
}
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
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;
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;
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;
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;
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,
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++;
}
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;
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 */
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;
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;
}
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
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
send_wmspec_change_state(backend_x11,
stage_x11->xwin,
- backend_x11->atom_WM_STATE_FULLSCREEN,
+ backend_x11->atom_NET_WM_STATE_FULLSCREEN,
TRUE);
}
}
/* 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
{
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 */
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,
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
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++)
{
* 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);
}
}
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);