[mutter] Fix corner cases where _NET_WM_FRAME_DRAWN might be missed
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] Fix corner cases where _NET_WM_FRAME_DRAWN might be missed
- Date: Thu, 14 Feb 2013 21:22:22 +0000 (UTC)
commit 5876f2e3e5093b5acc25a675afc8b4f0271cf5c1
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Thu Feb 14 13:40:55 2013 -0500
Fix corner cases where _NET_WM_FRAME_DRAWN might be missed
The WM spec requires _NET_WM_FRAME_DRAWN to *always* be sent when
there is an appropriate update to the sync counter value. We were
potentially missing _NET_WM_FRAME_DRAWN when an application did a
spontaneous update during an interactive resize and during effects.
Refactor the code to always send _NET_WM_FRAME_DRAWN, even when
a window is frozen.
https://bugzilla.gnome.org/show_bug.cgi?id=693833
src/compositor/compositor.c | 15 +++++++
src/compositor/meta-window-actor-private.h | 2 +
src/compositor/meta-window-actor.c | 62 ++++++++++++++++------------
src/core/window-private.h | 9 ----
src/core/window.c | 14 ++++--
src/meta/compositor.h | 3 +
6 files changed, 66 insertions(+), 39 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 91b0767..cf9e05b 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 5938677..e2eec5c 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 9980fe6..013a8ec 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)
+ {
+ 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;
- * 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.
+ /* 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 676a6ee..04ee110 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 ea50d69..e7c42fe 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 e36f30b..d917caf 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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]