diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 91b076734..cf9e05bdd 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -764,6 +764,21 @@ meta_compositor_set_updates_frozen (MetaCompositor *compositor, meta_window_actor_set_updates_frozen (window_actor, updates_frozen); } +void +meta_compositor_queue_frame_drawn (MetaCompositor *compositor, + MetaWindow *window, + gboolean no_delay_frame) +{ + MetaWindowActor *window_actor; + + DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n"); + window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); + if (!window_actor) + return; + + meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame); +} + static gboolean is_grabbed_event (MetaDisplay *display, XEvent *event) diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h index 5938677a9..e2eec5c86 100644 --- a/src/compositor/meta-window-actor-private.h +++ b/src/compositor/meta-window-actor-private.h @@ -51,6 +51,8 @@ void meta_window_actor_mapped (MetaWindowActor *self); void meta_window_actor_unmapped (MetaWindowActor *self); void meta_window_actor_set_updates_frozen (MetaWindowActor *self, gboolean updates_frozen); +void meta_window_actor_queue_frame_drawn (MetaWindowActor *self, + gboolean no_delay_frame); cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self); diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 9980fe6f7..013a8ec66 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -107,6 +107,7 @@ struct _MetaWindowActorPrivate guint needs_damage_all : 1; guint received_damage : 1; + guint repaint_scheduled : 1; /* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN * client message using the most recent frame in ->frames */ @@ -932,6 +933,7 @@ meta_window_actor_damage_all (MetaWindowActor *self) cogl_texture_get_height (texture)); priv->needs_damage_all = FALSE; + priv->repaint_scheduled = TRUE; } static void @@ -961,17 +963,41 @@ meta_window_actor_thaw (MetaWindowActor *self) * don't know what real damage has happened. */ if (self->priv->needs_damage_all) meta_window_actor_damage_all (self); - else if (self->priv->needs_frame_drawn != 0) +} + +void +meta_window_actor_queue_frame_drawn (MetaWindowActor *self, + gboolean no_delay_frame) +{ + MetaWindowActorPrivate *priv = self->priv; + FrameData *frame = g_slice_new0 (FrameData); + + priv->needs_frame_drawn = TRUE; + + frame->sync_request_serial = priv->window->sync_request_serial; + + priv->frames = g_list_prepend (priv->frames, frame); + + if (no_delay_frame) { - /* A frame was marked by the client without actually doing any damage; - * we need to make sure that the pre_paint/post_paint functions - * get called, enabling us to send a _NET_WM_FRAME_DRAWN. We do a - * 1-pixel redraw to get consistent timing with non-empty frames. + ClutterActor *stage = clutter_actor_get_stage (CLUTTER_ACTOR (self)); + clutter_stage_skip_sync_delay (CLUTTER_STAGE (stage)); + } + + if (!priv->repaint_scheduled) + { + /* A frame was marked by the client without actually doing any + * damage, or while we had the window frozen (e.g. during an + * interactive resize.) We need to make sure that the + * pre_paint/post_paint functions get called, enabling us to + * send a _NET_WM_FRAME_DRAWN. We do a 1-pixel redraw to get + * consistent timing with non-empty frames. */ - if (self->priv->mapped && !self->priv->needs_pixmap) + if (priv->mapped && !priv->needs_pixmap) { const cairo_rectangle_int_t clip = { 0, 0, 1, 1 }; - clutter_actor_queue_redraw_with_clip (self->priv->actor, &clip); + clutter_actor_queue_redraw_with_clip (priv->actor, &clip); + priv->repaint_scheduled = TRUE; } } } @@ -1949,6 +1975,7 @@ meta_window_actor_process_damage (MetaWindowActor *self, event->area.y, event->area.width, event->area.height); + priv->repaint_scheduled = TRUE; } void @@ -2350,25 +2377,6 @@ meta_window_actor_handle_updates (MetaWindowActor *self) check_needs_pixmap (self); check_needs_reshape (self); check_needs_shadow (self); - - if (priv->window->needs_frame_drawn) - { - FrameData *frame = g_slice_new0 (FrameData); - - priv->needs_frame_drawn = TRUE; - - frame->sync_request_serial = priv->window->sync_request_serial; - - priv->frames = g_list_prepend (priv->frames, frame); - - priv->window->needs_frame_drawn = FALSE; - - if (priv->window->no_delay_frame) - { - ClutterActor *stage = clutter_actor_get_stage (CLUTTER_ACTOR (self)); - clutter_stage_skip_sync_delay (CLUTTER_STAGE (stage)); - } - } } void @@ -2396,6 +2404,8 @@ meta_window_actor_post_paint (MetaWindowActor *self) { MetaWindowActorPrivate *priv = self->priv; + priv->repaint_scheduled = FALSE; + if (priv->needs_frame_drawn) { MetaScreen *screen = priv->screen; diff --git a/src/core/window-private.h b/src/core/window-private.h index 676a6ee8b..04ee11046 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -356,15 +356,6 @@ 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; - - /* if TRUE, the frame that was just drawn was drawn without any delay - * on the client's part and thus is high-priority - if we add delay - * we might cause the client to miss it's target frame rate */ - guint no_delay_frame : 1; - /* Note: can be NULL */ GSList *struts; diff --git a/src/core/window.c b/src/core/window.c index ea50d6934..e7c42fe44 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -9510,11 +9510,13 @@ void meta_window_update_sync_request_counter (MetaWindow *window, gint64 new_counter_value) { - if (window->extended_sync_request_counter && - new_counter_value % 2 == 0) + gboolean needs_frame_drawn = FALSE; + gboolean no_delay_frame = FALSE; + + if (window->extended_sync_request_counter && new_counter_value % 2 == 0) { - window->needs_frame_drawn = TRUE; - window->no_delay_frame = new_counter_value == window->sync_request_serial + 1; + needs_frame_drawn = TRUE; + no_delay_frame = new_counter_value == window->sync_request_serial + 1; } window->sync_request_serial = new_counter_value; @@ -9547,6 +9549,10 @@ meta_window_update_sync_request_counter (MetaWindow *window, window->display->grab_latest_motion_y, TRUE); } + + if (needs_frame_drawn) + meta_compositor_queue_frame_drawn (window->display->compositor, window, + no_delay_frame); } #endif /* HAVE_XSYNC */ diff --git a/src/meta/compositor.h b/src/meta/compositor.h index e36f30b05..d917cafb0 100644 --- a/src/meta/compositor.h +++ b/src/meta/compositor.h @@ -156,6 +156,9 @@ void meta_compositor_sync_window_geometry (MetaCompositor *compositor, void meta_compositor_set_updates_frozen (MetaCompositor *compositor, MetaWindow *window, gboolean updates_frozen); +void meta_compositor_queue_frame_drawn (MetaCompositor *compositor, + MetaWindow *window, + gboolean no_delay_frame); void meta_compositor_sync_stack (MetaCompositor *compositor, MetaScreen *screen,