From 9a6a189e3697fbcfbe4def9d9178d2b1db2ee9e3 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Thu, 31 Jul 2014 11:05:34 +0200 Subject: [PATCH] window-actor: Rebuild the shape and mask when the surface updates Connecting to size-changed is wrong -- size-changed tells us when we *told* the X server or resize the window. For X11, we're sort of guaranteed that the surface will be updated at some point before the next frame, but for Xwayland, we can't be sure that the new surface is attached at this point. This fixes weird artifacts when resizing apps like xclock. --- src/compositor/meta-shaped-texture.c | 16 ++++++++++++++++ src/compositor/meta-surface-actor.c | 18 ++++++++++++++++++ src/compositor/meta-window-actor.c | 12 +++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index be87e8159..7ae1913b5 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -65,6 +65,14 @@ G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_AC (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \ MetaShapedTexturePrivate)) +enum { + SIZE_CHANGED, + + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL]; + struct _MetaShapedTexturePrivate { MetaTextureTower *paint_tower; @@ -97,6 +105,13 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) actor_class->paint = meta_shaped_texture_paint; actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume; + signals[SIZE_CHANGED] = g_signal_new ("size-changed", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate)); } @@ -262,6 +277,7 @@ set_cogl_texture (MetaShapedTexture *stex, priv->tex_width = width; priv->tex_height = height; clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); + g_signal_emit (stex, signals[SIZE_CHANGED], 0); } /* NB: We don't queue a redraw of the actor here because we don't diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 20933b6ed..d280c7a13 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -36,6 +36,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_ enum { REPAINT_SCHEDULED, + SIZE_CHANGED, LAST_SIGNAL, }; @@ -120,6 +121,13 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + signals[SIZE_CHANGED] = g_signal_new ("size-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); } @@ -144,6 +152,14 @@ cullable_iface_init (MetaCullableInterface *iface) iface->reset_culling = meta_surface_actor_reset_culling; } +static void +texture_size_changed (MetaShapedTexture *texture, + gpointer user_data) +{ + MetaSurfaceActor *actor = META_SURFACE_ACTOR (user_data); + g_signal_emit (actor, signals[SIZE_CHANGED], 0); +} + static void meta_surface_actor_init (MetaSurfaceActor *self) { @@ -154,6 +170,8 @@ meta_surface_actor_init (MetaSurfaceActor *self) MetaSurfaceActorPrivate); priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); + g_signal_connect_object (priv->texture, "size-changed", + G_CALLBACK (texture_size_changed), self, 0); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); } diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 66a7e3c92..3465ee94a 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -76,6 +76,7 @@ struct _MetaWindowActorPrivate gint64 frame_drawn_time; guint repaint_scheduled_id; + guint size_changed_id; /* * These need to be counters rather than flags, since more plugins @@ -272,10 +273,10 @@ window_appears_focused_notify (MetaWindow *mw, } static void -window_size_changed (MetaWindow *mw, - gpointer data) +surface_size_changed (MetaSurfaceActor *actor, + gpointer user_data) { - MetaWindowActor *self = META_WINDOW_ACTOR (data); + MetaWindowActor *self = META_WINDOW_ACTOR (user_data); meta_window_actor_update_shape (self); } @@ -368,6 +369,7 @@ set_surface (MetaWindowActor *self, if (priv->surface) { g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id); + g_signal_handler_disconnect (priv->surface, priv->size_changed_id); priv->repaint_scheduled_id = 0; clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); g_object_unref (priv->surface); @@ -380,6 +382,8 @@ set_surface (MetaWindowActor *self, g_object_ref_sink (priv->surface); priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled", G_CALLBACK (surface_repaint_scheduled), self); + priv->size_changed_id = g_signal_connect (priv->surface, "size-changed", + G_CALLBACK (surface_size_changed), self); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); /* If the previous surface actor was frozen, start out @@ -489,8 +493,6 @@ meta_window_actor_set_property (GObject *object, priv->window = g_value_dup_object (value); g_signal_connect_object (priv->window, "notify::appears-focused", G_CALLBACK (window_appears_focused_notify), self, 0); - g_signal_connect_object (priv->window, "size-changed", - G_CALLBACK (window_size_changed), self, 0); break; case PROP_NO_SHADOW: {