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.
This commit is contained in:
Jasper St. Pierre 2014-07-31 11:05:34 +02:00
parent 505eabb78c
commit 9a6a189e36
3 changed files with 41 additions and 5 deletions

View File

@ -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, \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
MetaShapedTexturePrivate)) MetaShapedTexturePrivate))
enum {
SIZE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
struct _MetaShapedTexturePrivate struct _MetaShapedTexturePrivate
{ {
MetaTextureTower *paint_tower; MetaTextureTower *paint_tower;
@ -97,6 +105,13 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
actor_class->paint = meta_shaped_texture_paint; actor_class->paint = meta_shaped_texture_paint;
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume; 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)); g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
} }
@ -262,6 +277,7 @@ set_cogl_texture (MetaShapedTexture *stex,
priv->tex_width = width; priv->tex_width = width;
priv->tex_height = height; priv->tex_height = height;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); 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 /* NB: We don't queue a redraw of the actor here because we don't

View File

@ -36,6 +36,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_
enum { enum {
REPAINT_SCHEDULED, REPAINT_SCHEDULED,
SIZE_CHANGED,
LAST_SIGNAL, LAST_SIGNAL,
}; };
@ -120,6 +121,13 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 0); 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)); 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; 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 static void
meta_surface_actor_init (MetaSurfaceActor *self) meta_surface_actor_init (MetaSurfaceActor *self)
{ {
@ -154,6 +170,8 @@ meta_surface_actor_init (MetaSurfaceActor *self)
MetaSurfaceActorPrivate); MetaSurfaceActorPrivate);
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); 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)); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
} }

View File

@ -76,6 +76,7 @@ struct _MetaWindowActorPrivate
gint64 frame_drawn_time; gint64 frame_drawn_time;
guint repaint_scheduled_id; guint repaint_scheduled_id;
guint size_changed_id;
/* /*
* These need to be counters rather than flags, since more plugins * These need to be counters rather than flags, since more plugins
@ -272,10 +273,10 @@ window_appears_focused_notify (MetaWindow *mw,
} }
static void static void
window_size_changed (MetaWindow *mw, surface_size_changed (MetaSurfaceActor *actor,
gpointer data) gpointer user_data)
{ {
MetaWindowActor *self = META_WINDOW_ACTOR (data); MetaWindowActor *self = META_WINDOW_ACTOR (user_data);
meta_window_actor_update_shape (self); meta_window_actor_update_shape (self);
} }
@ -368,6 +369,7 @@ set_surface (MetaWindowActor *self,
if (priv->surface) if (priv->surface)
{ {
g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id); 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; priv->repaint_scheduled_id = 0;
clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
g_object_unref (priv->surface); g_object_unref (priv->surface);
@ -380,6 +382,8 @@ set_surface (MetaWindowActor *self,
g_object_ref_sink (priv->surface); g_object_ref_sink (priv->surface);
priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled", priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
G_CALLBACK (surface_repaint_scheduled), self); 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)); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
/* If the previous surface actor was frozen, start out /* 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); priv->window = g_value_dup_object (value);
g_signal_connect_object (priv->window, "notify::appears-focused", g_signal_connect_object (priv->window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0); G_CALLBACK (window_appears_focused_notify), self, 0);
g_signal_connect_object (priv->window, "size-changed",
G_CALLBACK (window_size_changed), self, 0);
break; break;
case PROP_NO_SHADOW: case PROP_NO_SHADOW:
{ {