background: paint color matte for scaled and centered backgrounds

Some backgrounds don't fully fill the screen.  For those backgrounds
it's important to paint a color behind them to fill in the gaps.

This commit checks whether or not the background image textures take
up the entire monitor, and in the event they don't, draws a color
behind them (such as it would do if the background were
translucent).

https://bugzilla.gnome.org/show_bug.cgi?id=754476
This commit is contained in:
Ray Strode 2015-09-03 13:57:25 -04:00
parent 0ffd4254d9
commit 1d56d50fcd

View File

@ -22,6 +22,8 @@
#include "meta-background-private.h" #include "meta-background-private.h"
#include "cogl-utils.h" #include "cogl-utils.h"
#include <string.h>
enum enum
{ {
CHANGED, CHANGED,
@ -71,6 +73,8 @@ enum
G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT)
static gboolean texture_has_alpha (CoglTexture *texture);
static GSList *all_backgrounds = NULL; static GSList *all_backgrounds = NULL;
static void static void
@ -474,7 +478,7 @@ get_texture_area (MetaBackground *self,
} }
} }
static void static gboolean
draw_texture (MetaBackground *self, draw_texture (MetaBackground *self,
CoglFramebuffer *framebuffer, CoglFramebuffer *framebuffer,
CoglPipeline *pipeline, CoglPipeline *pipeline,
@ -483,6 +487,7 @@ draw_texture (MetaBackground *self,
{ {
MetaBackgroundPrivate *priv = self->priv; MetaBackgroundPrivate *priv = self->priv;
cairo_rectangle_int_t texture_area; cairo_rectangle_int_t texture_area;
gboolean bare_region_visible;
get_texture_area (self, monitor_area, texture, &texture_area); get_texture_area (self, monitor_area, texture, &texture_area);
@ -503,6 +508,9 @@ draw_texture (MetaBackground *self,
- texture_area.y / (float)texture_area.height, - texture_area.y / (float)texture_area.height,
(monitor_area->width - texture_area.x) / (float)texture_area.width, (monitor_area->width - texture_area.x) / (float)texture_area.width,
(monitor_area->height - texture_area.y) / (float)texture_area.height); (monitor_area->height - texture_area.y) / (float)texture_area.height);
bare_region_visible = texture_has_alpha (texture);
/* Draw just the texture */ /* Draw just the texture */
break; break;
case G_DESKTOP_BACKGROUND_STYLE_CENTERED: case G_DESKTOP_BACKGROUND_STYLE_CENTERED:
@ -513,11 +521,16 @@ draw_texture (MetaBackground *self,
texture_area.x + texture_area.width, texture_area.x + texture_area.width,
texture_area.y + texture_area.height, texture_area.y + texture_area.height,
0, 0, 1.0, 1.0); 0, 0, 1.0, 1.0);
bare_region_visible = texture_has_alpha (texture) || memcmp (&texture_area, monitor_area, sizeof (cairo_rectangle_int_t)) != 0;
break;
case G_DESKTOP_BACKGROUND_STYLE_NONE: case G_DESKTOP_BACKGROUND_STYLE_NONE:
bare_region_visible = TRUE;
break; break;
default: default:
g_return_if_reached(); g_return_if_reached();
} }
return bare_region_visible;
} }
static void static void
@ -748,6 +761,7 @@ meta_background_get_texture (MetaBackground *self,
if (monitor->dirty) if (monitor->dirty)
{ {
CoglError *catch_error = NULL; CoglError *catch_error = NULL;
gboolean bare_region_visible = FALSE;
if (monitor->texture == NULL) if (monitor->texture == NULL)
{ {
@ -783,9 +797,9 @@ meta_background_get_texture (MetaBackground *self,
cogl_pipeline_set_layer_texture (pipeline, 0, texture2); cogl_pipeline_set_layer_texture (pipeline, 0, texture2);
cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style)); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
draw_texture (self, bare_region_visible = draw_texture (self,
monitor->fbo, pipeline, monitor->fbo, pipeline,
texture2, &monitor_area); texture2, &monitor_area);
cogl_object_unref (pipeline); cogl_object_unref (pipeline);
} }
@ -807,15 +821,14 @@ meta_background_get_texture (MetaBackground *self,
cogl_pipeline_set_layer_texture (pipeline, 0, texture1); cogl_pipeline_set_layer_texture (pipeline, 0, texture1);
cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style)); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (priv->style));
draw_texture (self, bare_region_visible = bare_region_visible || draw_texture (self,
monitor->fbo, pipeline, monitor->fbo, pipeline,
texture1, &monitor_area); texture1, &monitor_area);
cogl_object_unref (pipeline); cogl_object_unref (pipeline);
} }
if (!((texture2 != NULL && priv->blend_factor == 1.0 && !texture_has_alpha (texture2)) || if (bare_region_visible)
(texture1 != NULL && !texture_has_alpha (texture1))))
{ {
CoglPipeline *pipeline = create_pipeline (PIPELINE_OVER_REVERSE); CoglPipeline *pipeline = create_pipeline (PIPELINE_OVER_REVERSE);