2007-11-17 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Sat, 17 Nov 2007 18:11:14 +0000 (18:11 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Sat, 17 Nov 2007 18:11:14 +0000 (18:11 +0000)
Optimise Atoms usage in the X11 and X11-based backends.

* clutter/x11/clutter-backend-x11.c:

ChangeLog
clutter/glx/clutter-stage-glx.c
clutter/x11/clutter-backend-x11.c
clutter/x11/clutter-backend-x11.h
clutter/x11/clutter-event-x11.c
clutter/x11/clutter-stage-x11.c
clutter/x11/clutter-stage-x11.h
tests/test-actors.c

index f4965a3..ddf76ca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 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.
 
index 65cd590..d74b8e1 100644 (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);
index 7814610..3d4e0e5 100644 (file)
 
 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);
index b6289e8..4a55eef 100644 (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
index 2001859..e14bd6f 100644 (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;
index 05269b8..cba44b9 100644 (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, 
index 172cd87..194d6e9 100644 (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
 
index cf83fbd..42b8d59 100644 (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);