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
This commit is contained in:
Owen W. Taylor 2011-06-13 18:09:59 -04:00
parent 70c0d39fa7
commit fbfab93c63
6 changed files with 62 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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: */