|
|
|
@ -67,8 +67,12 @@ struct _MetaWindowActorPrivate
|
|
|
|
|
MetaShadow *focused_shadow;
|
|
|
|
|
MetaShadow *unfocused_shadow;
|
|
|
|
|
|
|
|
|
|
CoglTexture *focused_mask;
|
|
|
|
|
CoglTexture *unfocused_mask;
|
|
|
|
|
|
|
|
|
|
/* A region that matches the shape of the window, including frame bounds */
|
|
|
|
|
cairo_region_t *shape_region;
|
|
|
|
|
cairo_region_t *focused_shape_region;
|
|
|
|
|
cairo_region_t *unfocused_shape_region;
|
|
|
|
|
/* The region we should clip to when painting the shadow */
|
|
|
|
|
cairo_region_t *shadow_clip;
|
|
|
|
|
|
|
|
|
@ -175,6 +179,8 @@ static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
|
|
|
|
|
static void meta_window_actor_handle_updates (MetaWindowActor *self);
|
|
|
|
|
|
|
|
|
|
static void check_needs_reshape (MetaWindowActor *self);
|
|
|
|
|
static void meta_window_actor_update_shape_region (MetaWindowActor *self);
|
|
|
|
|
static void meta_window_actor_shape_region_changed (MetaWindowActor *self);
|
|
|
|
|
|
|
|
|
|
static void do_send_frame_drawn (MetaWindowActor *self, FrameData *frame);
|
|
|
|
|
static void do_send_frame_timings (MetaWindowActor *self,
|
|
|
|
@ -284,6 +290,29 @@ window_appears_focused_notify (MetaWindow *mw,
|
|
|
|
|
GParamSpec *arg1,
|
|
|
|
|
gpointer data)
|
|
|
|
|
{
|
|
|
|
|
MetaWindowActor *self = META_WINDOW_ACTOR (data);
|
|
|
|
|
MetaWindowActorPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
|
|
if (priv->surface)
|
|
|
|
|
{
|
|
|
|
|
gboolean appears_focused = meta_window_appears_focused (mw);
|
|
|
|
|
CoglTexture *mask = appears_focused ? self->priv->focused_mask
|
|
|
|
|
: self->priv->unfocused_mask;
|
|
|
|
|
|
|
|
|
|
if (mask)
|
|
|
|
|
{
|
|
|
|
|
MetaShapedTexture *stex;
|
|
|
|
|
|
|
|
|
|
stex = meta_surface_actor_get_texture (priv->surface);
|
|
|
|
|
meta_shaped_texture_set_mask_texture (stex, mask);
|
|
|
|
|
meta_window_actor_shape_region_changed (self);
|
|
|
|
|
}
|
|
|
|
|
else if (priv->window->frame)
|
|
|
|
|
{
|
|
|
|
|
meta_window_actor_update_shape_region (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -457,7 +486,8 @@ meta_window_actor_constructed (GObject *object)
|
|
|
|
|
|
|
|
|
|
/* Start off with an empty shape region to maintain the invariant
|
|
|
|
|
* that it's always set */
|
|
|
|
|
priv->shape_region = cairo_region_create ();
|
|
|
|
|
priv->focused_shape_region = cairo_region_create ();
|
|
|
|
|
priv->unfocused_shape_region = cairo_region_create ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@ -478,9 +508,13 @@ meta_window_actor_dispose (GObject *object)
|
|
|
|
|
priv->send_frame_messages_timer = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
|
|
|
|
g_clear_pointer (&priv->focused_shape_region, cairo_region_destroy);
|
|
|
|
|
g_clear_pointer (&priv->unfocused_shape_region, cairo_region_destroy);
|
|
|
|
|
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->focused_mask, cogl_object_unref);
|
|
|
|
|
g_clear_pointer (&priv->unfocused_mask, cogl_object_unref);
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->shadow_class, g_free);
|
|
|
|
|
g_clear_pointer (&priv->focused_shadow, meta_shadow_unref);
|
|
|
|
|
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
|
|
|
|
@ -621,8 +655,10 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
|
|
|
|
cairo_rectangle_int_t *bounds)
|
|
|
|
|
{
|
|
|
|
|
MetaWindowActorPrivate *priv = self->priv;
|
|
|
|
|
|
|
|
|
|
cairo_region_get_extents (priv->shape_region, bounds);
|
|
|
|
|
gboolean appears_focused = meta_window_appears_focused (priv->window);
|
|
|
|
|
cairo_region_t *shape_region = appears_focused ? priv->focused_shape_region
|
|
|
|
|
: priv->unfocused_shape_region;
|
|
|
|
|
cairo_region_get_extents (shape_region, bounds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@ -821,11 +857,11 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Always put a shadow around windows with a frame - This should override
|
|
|
|
|
* the restriction about not putting a shadow around ARGB windows.
|
|
|
|
|
* Do not put a shadow around windows with a frame - the decoration
|
|
|
|
|
* includes the shadow as defined by the GTK+ theme
|
|
|
|
|
*/
|
|
|
|
|
if (meta_window_get_frame (priv->window))
|
|
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Do not add shadows to non-opaque (ARGB32) windows, as we can't easily
|
|
|
|
@ -1585,7 +1621,12 @@ check_needs_shadow (MetaWindowActor *self)
|
|
|
|
|
if (*shadow_location == NULL && should_have_shadow)
|
|
|
|
|
{
|
|
|
|
|
if (priv->shadow_shape == NULL)
|
|
|
|
|
priv->shadow_shape = meta_window_shape_new (priv->shape_region);
|
|
|
|
|
{
|
|
|
|
|
cairo_region_t *shape_region;
|
|
|
|
|
shape_region = appears_focused ? priv->focused_shape_region
|
|
|
|
|
: priv->unfocused_shape_region;
|
|
|
|
|
priv->shadow_shape = meta_window_shape_new (shape_region);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MetaShadowFactory *factory = meta_shadow_factory_get_default ();
|
|
|
|
|
const char *shadow_class = meta_window_actor_get_shadow_class (self);
|
|
|
|
@ -1678,10 +1719,11 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
|
|
|
|
guchar *mask_data;
|
|
|
|
|
guint tex_width, tex_height;
|
|
|
|
|
MetaShapedTexture *stex;
|
|
|
|
|
CoglTexture *paint_tex, *mask_texture;
|
|
|
|
|
CoglTexture *paint_tex, *mask_texture, **mask_ptr;
|
|
|
|
|
int stride;
|
|
|
|
|
cairo_t *cr;
|
|
|
|
|
cairo_surface_t *surface;
|
|
|
|
|
gboolean appears_focused = meta_window_appears_focused (priv->window);
|
|
|
|
|
|
|
|
|
|
stex = meta_surface_actor_get_texture (priv->surface);
|
|
|
|
|
g_return_if_fail (stex);
|
|
|
|
@ -1762,8 +1804,10 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
|
|
|
|
if (mask_texture)
|
|
|
|
|
cogl_object_unref (mask_texture);
|
|
|
|
|
|
|
|
|
|
mask_ptr = appears_focused ? &priv->focused_mask : &priv->unfocused_mask;
|
|
|
|
|
g_clear_pointer (mask_ptr, cogl_object_unref);
|
|
|
|
|
*mask_ptr = mask_texture;
|
|
|
|
|
|
|
|
|
|
g_free (mask_data);
|
|
|
|
|
}
|
|
|
|
@ -1772,8 +1816,12 @@ static void
|
|
|
|
|
meta_window_actor_update_shape_region (MetaWindowActor *self)
|
|
|
|
|
{
|
|
|
|
|
MetaWindowActorPrivate *priv = self->priv;
|
|
|
|
|
cairo_region_t *region = NULL;
|
|
|
|
|
cairo_region_t *region = NULL, **shape_region;
|
|
|
|
|
cairo_rectangle_int_t client_area;
|
|
|
|
|
gboolean appears_focused = meta_window_appears_focused (priv->window);
|
|
|
|
|
|
|
|
|
|
shape_region = appears_focused ? &priv->focused_shape_region
|
|
|
|
|
: &priv->unfocused_shape_region;
|
|
|
|
|
|
|
|
|
|
meta_window_get_client_area_rect (priv->window, &client_area);
|
|
|
|
|
|
|
|
|
@ -1797,8 +1845,8 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
|
|
|
|
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
|
|
|
|
build_and_scan_frame_mask (self, &client_area, region);
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
|
|
|
|
priv->shape_region = region;
|
|
|
|
|
g_clear_pointer (shape_region, cairo_region_destroy);
|
|
|
|
|
*shape_region = region;
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
|
|
|
|
|
|
|
|
|
@ -1832,8 +1880,12 @@ static void
|
|
|
|
|
meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
|
|
|
|
{
|
|
|
|
|
MetaWindowActorPrivate *priv = self->priv;
|
|
|
|
|
cairo_region_t *opaque_region;
|
|
|
|
|
cairo_region_t *opaque_region, *shape_region;
|
|
|
|
|
gboolean argb32 = is_argb32 (self);
|
|
|
|
|
gboolean appears_focused = meta_window_appears_focused (priv->window);
|
|
|
|
|
|
|
|
|
|
shape_region = appears_focused ? priv->focused_shape_region
|
|
|
|
|
: priv->unfocused_shape_region;
|
|
|
|
|
|
|
|
|
|
if (argb32 && priv->window->opaque_region != NULL)
|
|
|
|
|
{
|
|
|
|
@ -1853,17 +1905,27 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
|
|
|
|
*/
|
|
|
|
|
opaque_region = cairo_region_copy (priv->window->opaque_region);
|
|
|
|
|
cairo_region_translate (opaque_region, client_area.x, client_area.y);
|
|
|
|
|
cairo_region_intersect (opaque_region, priv->shape_region);
|
|
|
|
|
cairo_region_intersect (opaque_region, shape_region);
|
|
|
|
|
}
|
|
|
|
|
else if (argb32)
|
|
|
|
|
opaque_region = NULL;
|
|
|
|
|
else
|
|
|
|
|
opaque_region = cairo_region_reference (priv->shape_region);
|
|
|
|
|
opaque_region = cairo_region_reference (shape_region);
|
|
|
|
|
|
|
|
|
|
meta_surface_actor_set_opaque_region (priv->surface, opaque_region);
|
|
|
|
|
cairo_region_destroy (opaque_region);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
meta_window_actor_shape_region_changed (MetaWindowActor *self)
|
|
|
|
|
{
|
|
|
|
|
if (self->priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
|
|
|
|
{
|
|
|
|
|
meta_window_actor_update_input_region (self);
|
|
|
|
|
meta_window_actor_update_opaque_region (self);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_needs_reshape (MetaWindowActor *self)
|
|
|
|
|
{
|
|
|
|
@ -1872,13 +1934,11 @@ check_needs_reshape (MetaWindowActor *self)
|
|
|
|
|
if (!priv->needs_reshape)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
meta_window_actor_update_shape_region (self);
|
|
|
|
|
g_clear_pointer (&priv->focused_mask, cogl_object_unref);
|
|
|
|
|
g_clear_pointer (&priv->unfocused_mask, cogl_object_unref);
|
|
|
|
|
|
|
|
|
|
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
|
|
|
|
{
|
|
|
|
|
meta_window_actor_update_input_region (self);
|
|
|
|
|
meta_window_actor_update_opaque_region (self);
|
|
|
|
|
}
|
|
|
|
|
meta_window_actor_update_shape_region (self);
|
|
|
|
|
meta_window_actor_shape_region_changed (self);
|
|
|
|
|
|
|
|
|
|
priv->needs_reshape = FALSE;
|
|
|
|
|
}
|
|
|
|
|