[mutter] Add ::first-frame signal to MetaWindowActor



commit 9c6e527d4b7c80dda997aae35a7bdb00e9bd3aed
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Wed May 21 09:57:15 2014 -0400

    Add ::first-frame signal to MetaWindowActor
    
    This signal is emitted the first time a frame of contents of the
    window is completed by the application and has been drawn on the
    screen. This is meant to be used for performance measurement of
    application startup.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=732343

 src/compositor/meta-window-actor.c |   57 ++++++++++++++++++++++++++++++++++++
 1 files changed, 57 insertions(+), 0 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index b743127..363c980 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -36,6 +36,12 @@
 
 #include "wayland/meta-wayland-surface.h"
 
+typedef enum {
+  INITIALLY_FROZEN,
+  DRAWING_FIRST_FRAME,
+  EMITTED_FIRST_FRAME
+} FirstFrameState;
+
 struct _MetaWindowActorPrivate
 {
   MetaWindow *window;
@@ -104,6 +110,7 @@ struct _MetaWindowActorPrivate
   guint             no_shadow              : 1;
 
   guint             updates_frozen         : 1;
+  guint             first_frame_state      : 2; /* FirstFrameState */
 };
 
 typedef struct _FrameData FrameData;
@@ -117,6 +124,14 @@ struct _FrameData
 
 enum
 {
+  FIRST_FRAME,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum
+{
   PROP_META_WINDOW = 1,
   PROP_NO_SHADOW,
   PROP_SHADOW_CLASS
@@ -181,6 +196,31 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
   actor_class->paint = meta_window_actor_paint;
   actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
 
+  /**
+   * MetaWindowActor::first-frame:
+   * @actor: the #MetaWindowActor instance
+   *
+   * The ::first-frame signal will be emitted the first time a frame
+   * of window contents has been drawn by the application and Mutter
+   * has had the chance to drawn that frame to the screen. If the
+   * window starts off initially hidden, obscured, or on on a
+   * different workspace, the ::first-frame signal will be emitted
+   * even though the user doesn't see the contents.
+   *
+   * MetaDisplay::window-created is a good place to connect to this
+   * signal - at that point, the MetaWindowActor for the window
+   * exists, but the window has reliably not yet been drawn.
+   * Connecting to an existing window that has already been drawn to
+   * the screen is not useful.
+   */
+  signals[FIRST_FRAME] =
+    g_signal_new ("first-frame",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
   pspec = g_param_spec_object ("meta-window",
                                "MetaWindow",
                                "The displayed MetaWindow",
@@ -306,6 +346,9 @@ meta_window_actor_thaw (MetaWindowActor *self)
   if (priv->freeze_count > 0)
     return;
 
+  if (priv->first_frame_state == INITIALLY_FROZEN)
+    priv->first_frame_state = DRAWING_FIRST_FRAME;
+
   if (priv->surface)
     meta_surface_actor_set_frozen (priv->surface, FALSE);
 
@@ -348,6 +391,9 @@ set_surface (MetaWindowActor  *self,
        * frozen as well... */
       meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
 
+      if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
+        priv->first_frame_state = DRAWING_FIRST_FRAME;
+
       meta_window_actor_update_shape (self);
     }
 }
@@ -1328,6 +1374,11 @@ meta_window_actor_new (MetaWindow *window)
 
   meta_window_actor_sync_updates_frozen (self);
 
+  if (is_frozen (self))
+    priv->first_frame_state = INITIALLY_FROZEN;
+  else
+    priv->first_frame_state = DRAWING_FIRST_FRAME;
+
   /* If a window doesn't start off with updates frozen, we should
    * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
    */
@@ -1910,6 +1961,12 @@ meta_window_actor_post_paint (MetaWindowActor *self)
       do_send_frame_drawn (self, priv->frames->data);
       priv->needs_frame_drawn = FALSE;
     }
+
+  if (priv->first_frame_state == DRAWING_FIRST_FRAME)
+    {
+      priv->first_frame_state = EMITTED_FIRST_FRAME;
+      g_signal_emit (self, signals[FIRST_FRAME], 0);
+    }
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]