Compare commits

...

8 Commits

Author SHA1 Message Date
6a9ca17814 theme: Update style classes to match CSD decorations
We currently use the "ssd" style class instead of "csd", so themes
can avoid adding a window shadow to windows that already got a shadow
from the compositor. Now that we no longer add a shadow to regular
windows, we should ask for the appropriate style.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
42ecde5f38 window-actor: Stop adding shadows to windows with frames
The frame decorations can pick up the shadow as defined by the GTK+
theme.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
45a273de20 window-actor: Only recompute shape region and mask if necessary
Rather than recomputing shape region and mask on every focus change,
re-use the previously computed ones if possible.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
b35ad080ce window-actor: Use different shape_regions/masks based on focus state
We now update the frame mask and -shape on every focus change, which
is expensive and wasteful if we recompute the same two regions over
and over again. To address this, use different regions/masks based on
the focus state, so that we'll be able to re-use a previously computed
one if possible.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
385cce7b8e window-actor: Update mask on focus changes
We currently assume that the frame mask and -shape don't change with the
focus style. This is reasonable for the actual decoration, but not for
the window shadow that is expected to be more pronounced when focused.
We will eventually let the GTK+ theme draw the shadow of regular windows,
so update shape region and frame mask on focus changes.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
482a5816f3 theme: Consider frame borders in titlebar
We currently use the entire top border area to paint the titlebar,
ignoring the frame border set by the theme. Fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:57 +02:00
9149f56b51 ui: Render frame in mask as well
The theme may render bits of the frame that are outside the rendered
area of the background, so don't skip it when painting the frame mask.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:56 +02:00
aae007193f shaped-texture: Only mask alpha channel
We currently apply the mask texture to any channel, which means
elements drawn outside the actual decorations are blended with
gray. This should hardly matter in practice where shadows can
be expected to be some shade of gray, but let's still make sure
the odd theme with pink shadows or the like works correctly by
applying the alpha mask to the alpha channel only.

https://bugzilla.gnome.org/show_bug.cgi?id=744667
2016-10-28 17:10:56 +02:00
4 changed files with 100 additions and 30 deletions

View File

@ -216,7 +216,8 @@ get_masked_pipeline (CoglContext *ctx)
{
template = cogl_pipeline_copy (get_base_pipeline (ctx));
cogl_pipeline_set_layer_combine (template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
"RGB = REPLACE (PREVIOUS)"
"A = MODULATE (PREVIOUS, TEXTURE)",
NULL);
}

View File

@ -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;
}

View File

@ -1358,10 +1358,19 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
borders.invisible.left / scale,
borders.invisible.top / scale,
frame_rect.width / scale, frame_rect.height / scale);
gtk_render_frame (frame->style_info->styles[META_STYLE_ELEMENT_FRAME], cr,
borders.invisible.left / scale,
borders.invisible.top / scale,
frame_rect.width / scale, frame_rect.height / scale);
gtk_render_background (frame->style_info->styles[META_STYLE_ELEMENT_TITLEBAR], cr,
borders.invisible.left / scale,
borders.invisible.top / scale,
frame_rect.width / scale, borders.total.top / scale);
gtk_render_frame (frame->style_info->styles[META_STYLE_ELEMENT_TITLEBAR], cr,
borders.invisible.left / scale,
borders.invisible.top / scale,
frame_rect.width / scale, borders.total.top / scale);
}
/* XXX -- this is disgusting. Find a better approach here.

View File

@ -766,10 +766,10 @@ meta_frame_layout_draw_with_style (MetaFrameLayout *layout,
visible_rect.x, visible_rect.y,
visible_rect.width, visible_rect.height);
titlebar_rect.x = visible_rect.x;
titlebar_rect.y = visible_rect.y;
titlebar_rect.width = visible_rect.width;
titlebar_rect.height = borders->visible.top / scale;
titlebar_rect.x = borders->total.left / scale;
titlebar_rect.y = visible_rect.y + layout->frame_border.top;
titlebar_rect.width = (fgeom->width - borders->total.left - borders->total.right) / scale;
titlebar_rect.height = borders->visible.top / scale - layout->frame_border.top;
style = style_info->styles[META_STYLE_ELEMENT_TITLEBAR];
gtk_render_background (style, cr,
@ -1065,7 +1065,7 @@ meta_theme_create_style_info (GdkScreen *screen,
provider,
"window",
GTK_STYLE_CLASS_BACKGROUND,
"ssd",
"csd",
NULL);
style_info->styles[META_STYLE_ELEMENT_FRAME] =
create_style_context (META_TYPE_FRAMES,