From fbfab93c63b3931cef0d11b7a559f210f8c649e6 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Mon, 13 Jun 2011 18:09:59 -0400 Subject: [PATCH] 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. https://bugzilla.gnome.org/show_bug.cgi?id=685463 --- src/compositor/compositor.c | 12 +++++++ 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, 62 insertions(+) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 87cd28926..a1b361bcc 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -470,6 +470,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) @@ -539,6 +549,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor, meta_screen_set_cm_selection (screen); info->stage = clutter_stage_new (); + 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 0d653ec6c..01f7aaaa5 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 6c147afeb..5c5c53ba5 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; @@ -2307,6 +2311,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 04ee11046..97b06acc3 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -356,6 +356,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 5bf8f050b..a4838d292 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -9493,6 +9493,9 @@ void meta_window_update_sync_request_counter (MetaWindow *window, gint64 new_counter_value) { + 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 ca0520fd0..2b10fe238 100644 --- a/src/meta/atomnames.h +++ b/src/meta/atomnames.h @@ -174,6 +174,7 @@ item(_NET_WM_FULLSCREEN_MONITORS) item(_NET_WM_STATE_FOCUSED) item(_NET_WM_BYPASS_COMPOSITOR) item(_NET_WM_OPAQUE_REGION) +item(_NET_WM_FRAME_DRAWN) #if 0 /* We apparently never use: */