MetaBackground: untie background rendering from MetaScreen

Rather than associating background textures with a MetaScreen, associate
them with GnomeBG objects. This allows to have different actors that render
different backgrounds, without losing the ability to share textures.

https://bugzilla.gnome.org/show_bug.cgi?id=688210
This commit is contained in:
Giovanni Campagna 2012-12-17 19:01:45 +01:00
parent 5a83ef71c9
commit 0a1ee4aa54
7 changed files with 223 additions and 140 deletions

View File

@ -227,7 +227,7 @@ typelib_DATA = Meta-$(api_version).typelib
INTROSPECTION_GIRS = Meta-$(api_version).gir INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la Meta-$(api_version).gir: libmutter.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0 @META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0 GnomeDesktop-3.0
@META_GIR@_EXPORT_PACKAGES = libmutter @META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(INCLUDES) @META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la @META_GIR@_LIBS = libmutter.la

View File

@ -573,7 +573,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
} }
info->window_group = meta_window_group_new (screen); info->window_group = meta_window_group_new (screen);
info->background_actor = meta_background_actor_new_for_screen (screen); info->background_actor = meta_background_actor_new (screen, NULL);
info->overlay_group = clutter_group_new (); info->overlay_group = clutter_group_new ();
clutter_container_add (CLUTTER_CONTAINER (info->window_group), clutter_container_add (CLUTTER_CONTAINER (info->window_group),
@ -1183,8 +1183,6 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
XResizeWindow (xdisplay, xwin, width, height); XResizeWindow (xdisplay, xwin, width, height);
meta_background_actor_screen_size_changed (screen);
meta_verbose ("Changed size for stage on screen %d to %dx%d\n", meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen), meta_screen_get_screen_number (screen),
width, height); width, height);

View File

@ -12,9 +12,6 @@
void meta_background_actor_set_visible_region (MetaBackgroundActor *self, void meta_background_actor_set_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region); cairo_region_t *visible_region);
void meta_background_actor_update (MetaScreen *screen);
void meta_background_actor_screen_size_changed (MetaScreen *screen);
GTask *meta_background_draw_async (MetaScreen *screen, GTask *meta_background_draw_async (MetaScreen *screen,
GnomeBG *bg, GnomeBG *bg,
GCancellable *cancellable, GCancellable *cancellable,

View File

@ -36,40 +36,39 @@
#define CROSSFADE_DURATION 1000 #define CROSSFADE_DURATION 1000
/* We allow creating multiple MetaBackgroundActors for the same MetaScreen to /* We allow creating multiple MetaBackgroundActors for the same MetaScreen and GnomeBG to
* allow different rendering options to be set for different copies. * allow different rendering options to be set for different copies.
* But we want to share the same underlying CoglTexture for efficiency and * But we want to share the same underlying CoglTexture for efficiency.
* to avoid driver bugs that might occur if we created multiple CoglTexturePixmaps
* for the same pixmap.
* *
* This structure holds common information. * This structure holds common information.
*/ */
typedef struct _MetaScreenBackground MetaScreenBackground; typedef struct _MetaBackground MetaBackground;
struct _MetaScreenBackground struct _MetaBackground
{ {
MetaScreen *screen;
GSList *actors; GSList *actors;
GSettings *settings; MetaScreen *screen;
GnomeBG *bg;
GCancellable *cancellable; GCancellable *cancellable;
float texture_width; float texture_width;
float texture_height; float texture_height;
CoglTexture *old_texture; CoglTexture *old_texture;
CoglTexture *texture; CoglTexture *texture;
CoglMaterialWrapMode wrap_mode;
GTask *rendering_task; GTask *rendering_task;
}; };
struct _MetaBackgroundActorPrivate struct _MetaBackgroundActorPrivate
{ {
MetaScreenBackground *background; MetaScreen *screen;
MetaBackground *background;
GnomeBG *settings;
CoglPipeline *single_pipeline; CoglPipeline *single_pipeline;
CoglPipeline *crossfade_pipeline; CoglPipeline *crossfade_pipeline;
CoglPipeline *pipeline; CoglPipeline *pipeline;
CoglMaterialWrapMode wrap_mode;
cairo_region_t *visible_region; cairo_region_t *visible_region;
float dim_factor; float dim_factor;
@ -81,6 +80,9 @@ enum
{ {
PROP_0, PROP_0,
PROP_SCREEN,
PROP_SETTINGS,
PROP_DIM_FACTOR, PROP_DIM_FACTOR,
PROP_CROSSFADE_PROGRESS, PROP_CROSSFADE_PROGRESS,
@ -91,68 +93,89 @@ static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR); G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
static void clear_old_texture (MetaScreenBackground *background); static void meta_background_update (GnomeBG *bg,
static void set_texture (MetaScreenBackground *background, MetaBackground *background);
CoglHandle texture); static void meta_background_actor_screen_size_changed (MetaScreen *screen,
MetaBackgroundActor *actor);
static void meta_background_actor_constructed (GObject *object);
static void clear_old_texture (MetaBackground *background);
static void set_texture (MetaBackground *background,
CoglHandle texture);
static void static void
free_screen_background (MetaScreenBackground *background) meta_background_free (MetaBackground *background)
{ {
set_texture (background, COGL_INVALID_HANDLE); set_texture (background, COGL_INVALID_HANDLE);
g_cancellable_cancel (background->cancellable); g_cancellable_cancel (background->cancellable);
g_object_unref (background->cancellable); g_object_unref (background->cancellable);
g_object_unref (background->bg); g_clear_object (&background->rendering_task);
g_object_unref (background->settings);
g_slice_free (MetaBackground, background);
} }
static void static void
on_settings_changed (GSettings *settings, on_settings_changed (GSettings *settings,
const char *key, const char *key,
MetaScreenBackground *background) GnomeBG *bg)
{ {
gnome_bg_load_from_preferences (background->bg, gnome_bg_load_from_preferences (bg, settings);
background->settings);
} }
static MetaScreenBackground * static GnomeBG *
meta_screen_background_get (MetaScreen *screen) meta_background_get_default_settings (void)
{ {
MetaScreenBackground *background; GSettings *settings;
GnomeBG *bg;
background = g_object_get_data (G_OBJECT (screen), "meta-screen-background"); settings = g_settings_new ("org.gnome.desktop.background");
if (background == NULL) bg = gnome_bg_new ();
g_signal_connect (settings, "changed",
G_CALLBACK (on_settings_changed), bg);
on_settings_changed (settings, NULL, bg);
/* Just to keep settings alive */
g_object_set_data_full (G_OBJECT (bg), "g-settings",
g_object_ref (settings), g_object_unref);
g_object_unref (settings);
return bg;
}
static MetaBackground *
meta_background_get (MetaScreen *screen,
GnomeBG *bg)
{
static GQuark background_quark;
MetaBackground *background;
if (G_UNLIKELY (background_quark == 0))
background_quark = g_quark_from_static_string ("meta-background");
background = g_object_get_qdata (G_OBJECT (bg), background_quark);
if (G_UNLIKELY (background == NULL))
{ {
background = g_new0 (MetaScreenBackground, 1); background = g_slice_new0 (MetaBackground);
g_object_set_qdata_full (G_OBJECT (bg), background_quark,
background, (GDestroyNotify) meta_background_free);
background->screen = screen; background->screen = screen;
g_object_set_data_full (G_OBJECT (screen), "meta-screen-background",
background, (GDestroyNotify) free_screen_background);
background->settings = g_settings_new ("org.gnome.desktop.background");
g_signal_connect (background->settings, "changed",
G_CALLBACK (on_settings_changed), background);
background->bg = gnome_bg_new ();
g_signal_connect_object (background->bg, "transitioned",
G_CALLBACK (meta_background_actor_update),
screen, G_CONNECT_SWAPPED);
g_signal_connect_object (background->bg, "changed",
G_CALLBACK (meta_background_actor_update),
screen, G_CONNECT_SWAPPED);
background->texture_width = -1; background->texture_width = -1;
background->texture_height = -1; background->texture_height = -1;
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
on_settings_changed (background->settings, NULL, background); g_signal_connect (bg, "transitioned",
G_CALLBACK (meta_background_update), background);
g_signal_connect (bg, "changed",
G_CALLBACK (meta_background_update), background);
/* GnomeBG has queued a changed event, but we need to start rendering now, /* GnomeBG has queued a changed event, but we need to start rendering now,
or it will be too late when we paint the first frame. or it will be too late when we paint the first frame.
*/ */
g_object_set_data (G_OBJECT (background->bg), "ignore-pending-change", GINT_TO_POINTER (TRUE)); g_object_set_data (G_OBJECT (bg), "ignore-pending-change", GINT_TO_POINTER (TRUE));
meta_background_actor_update (screen); meta_background_update (bg, background);
} }
return background; return background;
@ -170,10 +193,10 @@ update_actor_pipeline (MetaBackgroundActor *self,
priv->is_crossfading = TRUE; priv->is_crossfading = TRUE;
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->old_texture); cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->old_texture);
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->background->wrap_mode); cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->wrap_mode);
cogl_pipeline_set_layer_texture (priv->pipeline, 1, priv->background->texture); cogl_pipeline_set_layer_texture (priv->pipeline, 1, priv->background->texture);
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 1, priv->background->wrap_mode); cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 1, priv->wrap_mode);
} }
else else
{ {
@ -181,7 +204,7 @@ update_actor_pipeline (MetaBackgroundActor *self,
priv->is_crossfading = FALSE; priv->is_crossfading = FALSE;
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->texture); cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->texture);
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->background->wrap_mode); cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->wrap_mode);
} }
clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
@ -196,7 +219,7 @@ crossfade_completed (ClutterTimeline *timeline,
} }
static void static void
clear_old_texture (MetaScreenBackground *background) clear_old_texture (MetaBackground *background)
{ {
if (background->old_texture != COGL_INVALID_HANDLE) if (background->old_texture != COGL_INVALID_HANDLE)
{ {
@ -206,12 +229,13 @@ clear_old_texture (MetaScreenBackground *background)
} }
static void static void
set_texture (MetaScreenBackground *background, set_texture (MetaBackground *background,
CoglHandle texture) CoglHandle texture)
{ {
GSList *l; GSList *l;
gboolean crossfade; gboolean crossfade;
int width, height; int width, height;
CoglMaterialWrapMode wrap_mode;
if (background->old_texture != COGL_INVALID_HANDLE) if (background->old_texture != COGL_INVALID_HANDLE)
{ {
@ -246,14 +270,15 @@ set_texture (MetaScreenBackground *background,
* side of the image via bilinear filtering. * side of the image via bilinear filtering.
*/ */
if (width == background->texture_width && height == background->texture_height) if (width == background->texture_width && height == background->texture_height)
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE; wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
else else
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT; wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
for (l = background->actors; l; l = l->next) for (l = background->actors; l; l = l->next)
{ {
MetaBackgroundActor *actor = l->data; MetaBackgroundActor *actor = l->data;
actor->priv->wrap_mode = wrap_mode;
update_actor_pipeline (actor, crossfade); update_actor_pipeline (actor, crossfade);
if (crossfade) if (crossfade)
@ -281,29 +306,8 @@ set_texture (MetaScreenBackground *background,
} }
} }
static void
update_wrap_mode (MetaScreenBackground *background)
{
GSList *l;
int width, height;
meta_screen_get_size (background->screen, &width, &height);
if (width == background->texture_width && height == background->texture_height)
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
else
background->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
for (l = background->actors; l != NULL; l++)
{
MetaBackgroundActor *actor = l->data;
update_actor_pipeline (actor, actor->priv->is_crossfading);
}
}
static inline void static inline void
meta_background_ensure_rendered (MetaScreenBackground *background) meta_background_ensure_rendered (MetaBackground *background)
{ {
if (G_LIKELY (background->rendering_task == NULL || if (G_LIKELY (background->rendering_task == NULL ||
background->texture != COGL_INVALID_HANDLE)) background->texture != COGL_INVALID_HANDLE))
@ -326,8 +330,9 @@ meta_background_actor_dispose (GObject *object)
priv->background = NULL; priv->background = NULL;
} }
g_clear_pointer(&priv->single_pipeline, cogl_object_unref); g_clear_pointer (&priv->single_pipeline, cogl_object_unref);
g_clear_pointer(&priv->crossfade_pipeline, cogl_object_unref); g_clear_pointer (&priv->crossfade_pipeline, cogl_object_unref);
g_clear_object (&priv->settings);
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object); G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
} }
@ -342,7 +347,7 @@ meta_background_actor_get_preferred_width (ClutterActor *actor,
MetaBackgroundActorPrivate *priv = self->priv; MetaBackgroundActorPrivate *priv = self->priv;
int width, height; int width, height;
meta_screen_get_size (priv->background->screen, &width, &height); meta_screen_get_size (priv->screen, &width, &height);
if (min_width_p) if (min_width_p)
*min_width_p = width; *min_width_p = width;
@ -361,7 +366,7 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
MetaBackgroundActorPrivate *priv = self->priv; MetaBackgroundActorPrivate *priv = self->priv;
int width, height; int width, height;
meta_screen_get_size (priv->background->screen, &width, &height); meta_screen_get_size (priv->screen, &width, &height);
if (min_height_p) if (min_height_p)
*min_height_p = height; *min_height_p = height;
@ -381,7 +386,7 @@ meta_background_actor_paint (ClutterActor *actor)
meta_background_ensure_rendered (priv->background); meta_background_ensure_rendered (priv->background);
meta_screen_get_size (priv->background->screen, &width, &height); meta_screen_get_size (priv->screen, &width, &height);
color_component = (int)(0.5 + opacity * priv->dim_factor); color_component = (int)(0.5 + opacity * priv->dim_factor);
@ -440,7 +445,7 @@ meta_background_actor_get_paint_volume (ClutterActor *actor,
MetaBackgroundActorPrivate *priv = self->priv; MetaBackgroundActorPrivate *priv = self->priv;
int width, height; int width, height;
meta_screen_get_size (priv->background->screen, &width, &height); meta_screen_get_size (priv->screen, &width, &height);
clutter_paint_volume_set_width (volume, width); clutter_paint_volume_set_width (volume, width);
clutter_paint_volume_set_height (volume, height); clutter_paint_volume_set_height (volume, height);
@ -480,6 +485,31 @@ meta_background_actor_set_dim_factor (MetaBackgroundActor *self,
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIM_FACTOR]); g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIM_FACTOR]);
} }
static void
meta_background_actor_set_screen (MetaBackgroundActor *self,
MetaScreen *screen)
{
self->priv->screen = screen;
g_object_add_weak_pointer (G_OBJECT (screen), (void**) &self->priv->screen);
g_signal_connect_object (screen, "monitors-changed",
G_CALLBACK (meta_background_actor_screen_size_changed), self, 0);
}
static void
meta_background_actor_set_settings (MetaBackgroundActor *self,
GnomeBG *settings)
{
MetaBackgroundActorPrivate *priv;
priv = self->priv;
if (settings)
priv->settings = g_object_ref (settings);
else
priv->settings = meta_background_get_default_settings ();
}
static void static void
meta_background_actor_get_property(GObject *object, meta_background_actor_get_property(GObject *object,
guint prop_id, guint prop_id,
@ -496,6 +526,13 @@ meta_background_actor_get_property(GObject *object,
break; break;
case PROP_CROSSFADE_PROGRESS: case PROP_CROSSFADE_PROGRESS:
g_value_set_float (value, priv->crossfade_progress); g_value_set_float (value, priv->crossfade_progress);
break;
case PROP_SETTINGS:
g_value_set_object (value, priv->settings);
break;
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -518,6 +555,12 @@ meta_background_actor_set_property(GObject *object,
case PROP_CROSSFADE_PROGRESS: case PROP_CROSSFADE_PROGRESS:
meta_background_actor_set_crossfade_progress (self, g_value_get_float (value)); meta_background_actor_set_crossfade_progress (self, g_value_get_float (value));
break; break;
case PROP_SETTINGS:
meta_background_actor_set_settings (self, GNOME_BG (g_value_get_object (value)));
break;
case PROP_SCREEN:
meta_background_actor_set_screen (self, META_SCREEN (g_value_get_object (value)));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -536,12 +579,37 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass)
object_class->dispose = meta_background_actor_dispose; object_class->dispose = meta_background_actor_dispose;
object_class->get_property = meta_background_actor_get_property; object_class->get_property = meta_background_actor_get_property;
object_class->set_property = meta_background_actor_set_property; object_class->set_property = meta_background_actor_set_property;
object_class->constructed = meta_background_actor_constructed;
actor_class->get_preferred_width = meta_background_actor_get_preferred_width; actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
actor_class->get_preferred_height = meta_background_actor_get_preferred_height; actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
actor_class->paint = meta_background_actor_paint; actor_class->paint = meta_background_actor_paint;
actor_class->get_paint_volume = meta_background_actor_get_paint_volume; actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
/**
* MetaBackgroundActor:screen:
*
* The #MetaScreen this actor is operating on.
*/
pspec = g_param_spec_object ("screen",
"Screen",
"The screen the actor is on",
META_TYPE_SCREEN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
obj_props[PROP_SCREEN] = pspec;
/**
* MetaBackgroundActor:settings:
*
* The #GnomeBG object holding settings for this background.
*/
pspec = g_param_spec_object ("settings",
"Settings",
"Object holding required information to render a background",
GNOME_TYPE_BG,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
obj_props[PROP_SETTINGS] = pspec;
/** /**
* MetaBackgroundActor:dim-factor: * MetaBackgroundActor:dim-factor:
* *
@ -578,28 +646,22 @@ meta_background_actor_init (MetaBackgroundActor *self)
META_TYPE_BACKGROUND_ACTOR, META_TYPE_BACKGROUND_ACTOR,
MetaBackgroundActorPrivate); MetaBackgroundActorPrivate);
priv->dim_factor = 1.0; priv->dim_factor = 1.0;
priv->crossfade_progress = 0.0;
priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
} }
/** static void
* meta_background_actor_new: meta_background_actor_constructed (GObject *object)
* @screen: the #MetaScreen
*
* Creates a new actor to draw the background for the given screen.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_background_actor_new_for_screen (MetaScreen *screen)
{ {
MetaBackgroundActor *self; MetaBackgroundActor *self;
MetaBackgroundActorPrivate *priv; MetaBackgroundActorPrivate *priv;
g_return_val_if_fail (META_IS_SCREEN (screen), NULL); G_OBJECT_CLASS (meta_background_actor_parent_class)->constructed (object);
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL); self = META_BACKGROUND_ACTOR (object);
priv = self->priv; priv = self->priv;
priv->background = meta_screen_background_get (screen); priv->background = meta_background_get (priv->screen, priv->settings);
priv->background->actors = g_slist_prepend (priv->background->actors, self); priv->background->actors = g_slist_prepend (priv->background->actors, self);
priv->single_pipeline = meta_create_texture_material (priv->background->texture); priv->single_pipeline = meta_create_texture_material (priv->background->texture);
@ -608,8 +670,28 @@ meta_background_actor_new_for_screen (MetaScreen *screen)
if (priv->background->texture != COGL_INVALID_HANDLE) if (priv->background->texture != COGL_INVALID_HANDLE)
update_actor_pipeline (self, FALSE); update_actor_pipeline (self, FALSE);
}
return CLUTTER_ACTOR (self); /**
* meta_background_actor_new:
* @screen: the #MetaScreen
* @settings: (allow-none): a #GnomeBG holding the background configuration,
* or %NULL to pick the default one.
*
* Creates a new actor to draw the background for the given screen.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_background_actor_new (MetaScreen *screen,
GnomeBG *settings)
{
g_return_val_if_fail (META_IS_SCREEN (screen), NULL);
return g_object_new (META_TYPE_BACKGROUND_ACTOR,
"screen", screen,
"settings", settings,
NULL);
} }
static void static void
@ -617,25 +699,26 @@ on_background_drawn (GObject *object,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
MetaScreen *screen = META_SCREEN (object); MetaBackground *background;
MetaScreenBackground *background;
CoglHandle texture; CoglHandle texture;
GError *error; GError *error;
background = meta_screen_background_get (screen);
g_clear_object (&background->rendering_task);
g_clear_object (&background->cancellable);
error = NULL; error = NULL;
texture = meta_background_draw_finish (screen, result, &error); texture = meta_background_draw_finish (META_SCREEN (object), result, &error);
/* Don't even access user_data if cancelled, it might be already
freed */
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{ {
g_error_free (error); g_error_free (error);
return; return;
} }
background = user_data;
g_clear_object (&background->rendering_task);
g_clear_object (&background->cancellable);
if (texture != COGL_INVALID_HANDLE) if (texture != COGL_INVALID_HANDLE)
{ {
set_texture (background, texture); set_texture (background, texture);
@ -650,21 +733,19 @@ on_background_drawn (GObject *object,
} }
} }
/** /*
* meta_background_actor_update: * meta_background_update:
* @screen: a #MetaScreen * @bg: the #GnomeBG that triggered the update
* @background: a #MetaBackground
* *
* Forces a redraw of the background. The redraw happens asynchronously in * Forces a redraw of the background. The redraw happens asynchronously in
* a thread, and the actual on screen change is therefore delayed until * a thread, and the actual on screen change is therefore delayed until
* the redraw is finished. * the redraw is finished.
*/ */
void void
meta_background_actor_update (MetaScreen *screen) meta_background_update (GnomeBG *bg,
MetaBackground *background)
{ {
MetaScreenBackground *background;
background = meta_screen_background_get (screen);
if (background->cancellable) if (background->cancellable)
{ {
g_cancellable_cancel (background->cancellable); g_cancellable_cancel (background->cancellable);
@ -674,10 +755,10 @@ meta_background_actor_update (MetaScreen *screen)
g_clear_object (&background->rendering_task); g_clear_object (&background->rendering_task);
background->cancellable = g_cancellable_new (); background->cancellable = g_cancellable_new ();
background->rendering_task = meta_background_draw_async (screen, background->rendering_task = meta_background_draw_async (background->screen,
background->bg, bg,
background->cancellable, background->cancellable,
on_background_drawn, NULL); on_background_drawn, background);
} }
/** /**
@ -708,7 +789,7 @@ meta_background_actor_set_visible_region (MetaBackgroundActor *self,
if (visible_region) if (visible_region)
{ {
cairo_rectangle_int_t screen_rect = { 0 }; cairo_rectangle_int_t screen_rect = { 0 };
meta_screen_get_size (priv->background->screen, &screen_rect.width, &screen_rect.height); meta_screen_get_size (priv->screen, &screen_rect.width, &screen_rect.height);
/* Doing the intersection here is probably unnecessary - MetaWindowGroup /* Doing the intersection here is probably unnecessary - MetaWindowGroup
* should never compute a visible area that's larger than the root screen! * should never compute a visible area that's larger than the root screen!
@ -719,22 +800,26 @@ meta_background_actor_set_visible_region (MetaBackgroundActor *self,
} }
} }
/** static void
* meta_background_actor_screen_size_changed: meta_background_actor_screen_size_changed (MetaScreen *screen,
* @screen: a #MetaScreen MetaBackgroundActor *actor)
*
* Called by the compositor when the size of the #MetaScreen changes
*/
void
meta_background_actor_screen_size_changed (MetaScreen *screen)
{ {
MetaScreenBackground *background = meta_screen_background_get (screen); MetaBackgroundActorPrivate *priv;
GSList *l; MetaBackground *background;
int width, height;
update_wrap_mode (background); priv = actor->priv;
background = priv->background;
for (l = background->actors; l; l = l->next) meta_screen_get_size (screen, &width, &height);
clutter_actor_queue_relayout (l->data);
if (width == background->texture_width && height == background->texture_height)
priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
else
priv->wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
update_actor_pipeline (actor, actor->priv->is_crossfading);
clutter_actor_queue_relayout (CLUTTER_ACTOR (actor));
} }
/** /**

View File

@ -239,7 +239,7 @@ meta_screen_class_init (MetaScreenClass *klass)
G_TYPE_FROM_CLASS (object_class), G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MetaScreenClass, monitors_changed), G_STRUCT_OFFSET (MetaScreenClass, monitors_changed),
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
g_object_class_install_property (object_class, g_object_class_install_property (object_class,

View File

@ -12,7 +12,7 @@ mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter Name: libmutter
Description: Mutter window manager library Description: Mutter window manager library
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11 Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11 gnome-desktop-3.0
Version: @VERSION@ Version: @VERSION@
Libs: -L${libdir} -lmutter Libs: -L${libdir} -lmutter
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version} Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}

View File

@ -24,6 +24,8 @@
#define META_BACKGROUND_ACTOR_H #define META_BACKGROUND_ACTOR_H
#include <clutter/clutter.h> #include <clutter/clutter.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-bg.h>
#include <meta/screen.h> #include <meta/screen.h>
@ -60,7 +62,8 @@ struct _MetaBackgroundActor
GType meta_background_actor_get_type (void); GType meta_background_actor_get_type (void);
ClutterActor *meta_background_actor_new_for_screen (MetaScreen *screen); ClutterActor *meta_background_actor_new (MetaScreen *screen,
GnomeBG *settings);
/** /**
* MetaSnippetHook: * MetaSnippetHook: