[mutter/wip/frame-synchronization: 6/8] Send _NET_WM_FRAME_DRAWN messages



commit 4a0ac00147ed45fcb8329637db8d0b5cc0e5f51c
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Jun 13 18:09:59 2011 -0400

    Send _NET_WM_FRAME_DRAWN messages
    
    When the application provides the extended second counter for
    _NET_WM_SYNC_REQUEST, send a client message with completion
    information after the next redraw after each counter update
    by the application.

 src/compositor/compositor.c                |   14 +++++++++-
 src/compositor/meta-window-actor-private.h |    1 +
 src/compositor/meta-window-actor.c         |   41 ++++++++++++++++++++++++++++
 src/core/window-private.h                  |    4 +++
 src/core/window.c                          |    3 ++
 src/meta/atomnames.h                       |    1 +
 6 files changed, 63 insertions(+), 1 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 7f6d43e..8487efa 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -445,6 +445,16 @@ meta_check_end_modal (MetaScreen *screen)
     }
 }
 
+static void
+after_stage_paint (ClutterActor   *stage,
+                   MetaCompScreen *info)
+{
+  GList *l;
+
+  for (l = info->windows; l; l = l->next)
+    meta_window_actor_post_paint (l->data);
+}
+
 void
 meta_compositor_manage_screen (MetaCompositor *compositor,
                                MetaScreen     *screen)
@@ -515,7 +525,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
 
   meta_screen_set_cm_selection (screen);
 
-  info->stage = clutter_stage_new ();
+  info->stage = clutter_stage_get_default ();
+  g_signal_connect_after (info->stage, "paint",
+                          G_CALLBACK (after_stage_paint), info);
 
   meta_screen_get_size (screen, &width, &height);
   clutter_actor_realize (info->stage);
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index 0d653ec..01f7aaa 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -28,6 +28,7 @@ void meta_window_actor_process_damage (MetaWindowActor    *self,
                                        XDamageNotifyEvent *event);
 
 void meta_window_actor_pre_paint      (MetaWindowActor    *self);
+void meta_window_actor_post_paint     (MetaWindowActor    *self);
 
 void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
 
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 1339f54..a091d13 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -97,6 +97,10 @@ struct _MetaWindowActorPrivate
   gint              map_in_progress;
   gint              destroy_in_progress;
 
+  /* If non-zero, the client needs to be sent a _NET_WM_FRAME_DRAWN
+   * client message with this value */
+  gint64            frame_drawn_serial;
+
   guint		    visible                : 1;
   guint		    mapped                 : 1;
   guint		    argb32                 : 1;
@@ -2379,6 +2383,43 @@ meta_window_actor_pre_paint (MetaWindowActor *self)
   check_needs_pixmap (self);
   check_needs_reshape (self);
   check_needs_shadow (self);
+
+  if (priv->window->needs_frame_drawn)
+    {
+      priv->frame_drawn_serial = priv->window->sync_request_serial;
+      priv->window->needs_frame_drawn = FALSE;
+    }
+}
+
+void
+meta_window_actor_post_paint (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+
+  if (priv->frame_drawn_serial != 0)
+    {
+      MetaScreen  *screen  = priv->screen;
+      MetaDisplay *display = meta_screen_get_display (screen);
+      Display *xdisplay = meta_display_get_xdisplay (display);
+
+      XClientMessageEvent ev;
+
+      ev.type = ClientMessage;
+      ev.window = meta_window_get_xwindow (priv->window);
+      ev.message_type = display->atom_WM_PROTOCOLS;
+      ev.format = 32;
+      ev.data.l[0] = display->atom__NET_WM_FRAME_DRAWN;
+      ev.data.l[1] = 0; /* timestamp */
+      ev.data.l[2] = priv->frame_drawn_serial & G_GUINT64_CONSTANT(0xffffffff);
+      ev.data.l[3] = priv->frame_drawn_serial >> 32;
+      ev.data.l[4] = 0; /* vblank estimate */
+
+      meta_error_trap_push (display);
+      XSendEvent (xdisplay, ev.window, False, 0, (XEvent*) &ev);
+      meta_error_trap_pop (display);
+
+      priv->frame_drawn_serial = 0;
+    }
 }
 
 void
diff --git a/src/core/window-private.h b/src/core/window-private.h
index e1648fc..3877661 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -343,6 +343,10 @@ struct _MetaWindow
    * also handles application frames */
   guint extended_sync_request_counter : 1;
 
+  /* if TRUE, we still need to send a _NET_WM_FRAME_DRAWN message for the
+   * last update the sync request counter */
+  guint needs_frame_drawn : 1;
+
   /* Note: can be NULL */
   GSList *struts;
 
diff --git a/src/core/window.c b/src/core/window.c
index 430871b..dd30c13 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -9360,6 +9360,9 @@ meta_window_update_sync_request_counter (MetaWindow *window,
                                          gint64      new_counter_value)
 {
 #ifdef HAVE_XSYNC
+  if (window->extended_sync_request_counter)
+    window->needs_frame_drawn = TRUE;
+
   window->sync_request_serial = new_counter_value;
   meta_compositor_set_updates_frozen (window->display->compositor, window,
                                       meta_window_updates_are_frozen (window));
diff --git a/src/meta/atomnames.h b/src/meta/atomnames.h
index 210e5a2..35f85d4 100644
--- a/src/meta/atomnames.h
+++ b/src/meta/atomnames.h
@@ -172,6 +172,7 @@ item(_NET_WM_ACTION_BELOW)
 item(_NET_WM_STATE_STICKY)
 item(_NET_WM_FULLSCREEN_MONITORS)
 item(_NET_WM_STATE_FOCUSED)
+item(_NET_WM_FRAME_DRAWN)
 
 #if 0
 /* We apparently never use: */



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