diff --git a/ChangeLog b/ChangeLog index f4965a31e..ddf76ca86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2007-11-17 Emmanuele Bassi + + 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 * configure.ac: Depend on GLib >= 2.14 because of ClutterModel diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index 65cd590a0..d74b8e1da 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -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); diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index 7814610f0..3d4e0e552 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -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); diff --git a/clutter/x11/clutter-backend-x11.h b/clutter/x11/clutter-backend-x11.h index b6289e869..4a55eef8a 100644 --- a/clutter/x11/clutter-backend-x11.h +++ b/clutter/x11/clutter-backend-x11.h @@ -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 diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 200185932..e14bd6f69 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -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 *) ×tamp, 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; diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c index 05269b82f..cba44b95f 100644 --- a/clutter/x11/clutter-stage-x11.c +++ b/clutter/x11/clutter-stage-x11.c @@ -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, diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h index 172cd878d..194d6e9cd 100644 --- a/clutter/x11/clutter-stage-x11.h +++ b/clutter/x11/clutter-stage-x11.h @@ -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 diff --git a/tests/test-actors.c b/tests/test-actors.c index cf83fbd4b..42b8d597c 100644 --- a/tests/test-actors.c +++ b/tests/test-actors.c @@ -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);