compositor: rework how backgrounds are managed
Background handling in GNOME is very roundabout at the moment. gnome-settings-daemon uses gnome-desktop to read the background from disk into a screen-sized pixmap. It then sets the XID of that pixmap on the _XROOTPMAP_ID root window property. mutter puts that pixmap into a texture/actor which gnome-shell then uses. Having the gnome-settings-daemon detour from disk to screen means we can't easily let the compositor handle transition effects when switching backgrounds. Also, having the background actor be per-screen instead of per-monitor means we may have oversized textures in certain multihead setups. This commit changes mutter to read backgrounds from disk itself, and it changes backgrounds to be per-monitor. This way background handling/compositing is left to the compositor. https://bugzilla.gnome.org/show_bug.cgi?id=682427
This commit is contained in:
parent
842bc4421c
commit
580feb0c85
@ -8,6 +8,7 @@ SUBDIRS=wm-tester tools compositor/plugins
|
|||||||
INCLUDES= \
|
INCLUDES= \
|
||||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||||
|
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||||
$(MUTTER_CFLAGS) \
|
$(MUTTER_CFLAGS) \
|
||||||
-I$(srcdir) \
|
-I$(srcdir) \
|
||||||
-I$(srcdir)/core \
|
-I$(srcdir)/core \
|
||||||
@ -48,8 +49,11 @@ libmutter_la_SOURCES = \
|
|||||||
compositor/cogl-utils.h \
|
compositor/cogl-utils.h \
|
||||||
compositor/compositor.c \
|
compositor/compositor.c \
|
||||||
compositor/compositor-private.h \
|
compositor/compositor-private.h \
|
||||||
|
compositor/meta-background.c \
|
||||||
compositor/meta-background-actor.c \
|
compositor/meta-background-actor.c \
|
||||||
compositor/meta-background-actor-private.h \
|
compositor/meta-background-actor-private.h \
|
||||||
|
compositor/meta-background-group.c \
|
||||||
|
compositor/meta-background-group-private.h \
|
||||||
compositor/meta-module.c \
|
compositor/meta-module.c \
|
||||||
compositor/meta-module.h \
|
compositor/meta-module.h \
|
||||||
compositor/meta-plugin.c \
|
compositor/meta-plugin.c \
|
||||||
@ -71,7 +75,9 @@ libmutter_la_SOURCES = \
|
|||||||
compositor/region-utils.c \
|
compositor/region-utils.c \
|
||||||
compositor/region-utils.h \
|
compositor/region-utils.h \
|
||||||
meta/compositor.h \
|
meta/compositor.h \
|
||||||
|
meta/meta-background.h \
|
||||||
meta/meta-background-actor.h \
|
meta/meta-background-actor.h \
|
||||||
|
meta/meta-background-group.h \
|
||||||
meta/meta-plugin.h \
|
meta/meta-plugin.h \
|
||||||
meta/meta-shadow-factory.h \
|
meta/meta-shadow-factory.h \
|
||||||
meta/meta-window-actor.h \
|
meta/meta-window-actor.h \
|
||||||
@ -175,6 +181,8 @@ libmutterinclude_base_headers = \
|
|||||||
meta/keybindings.h \
|
meta/keybindings.h \
|
||||||
meta/main.h \
|
meta/main.h \
|
||||||
meta/meta-background-actor.h \
|
meta/meta-background-actor.h \
|
||||||
|
meta/meta-background-group.h \
|
||||||
|
meta/meta-background.h \
|
||||||
meta/meta-plugin.h \
|
meta/meta-plugin.h \
|
||||||
meta/meta-shaped-texture.h \
|
meta/meta-shaped-texture.h \
|
||||||
meta/meta-shadow-factory.h \
|
meta/meta-shadow-factory.h \
|
||||||
|
@ -13,10 +13,11 @@
|
|||||||
#include "xprops.h"
|
#include "xprops.h"
|
||||||
#include <meta/prefs.h>
|
#include <meta/prefs.h>
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
|
#include <meta/meta-background-actor.h>
|
||||||
|
#include <meta/meta-background-group.h>
|
||||||
#include <meta/meta-shadow-factory.h>
|
#include <meta/meta-shadow-factory.h>
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-window-group.h"
|
#include "meta-window-group.h"
|
||||||
#include "meta-background-actor-private.h"
|
|
||||||
#include "window-private.h" /* to check window->hidden */
|
#include "window-private.h" /* to check window->hidden */
|
||||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
@ -117,21 +118,6 @@ process_property_notify (MetaCompositor *compositor,
|
|||||||
{
|
{
|
||||||
MetaWindowActor *window_actor;
|
MetaWindowActor *window_actor;
|
||||||
|
|
||||||
if (event->atom == compositor->atom_x_root_pixmap)
|
|
||||||
{
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
for (l = meta_display_get_screens (compositor->display); l; l = l->next)
|
|
||||||
{
|
|
||||||
MetaScreen *screen = l->data;
|
|
||||||
if (event->window == meta_screen_get_xroot (screen))
|
|
||||||
{
|
|
||||||
meta_background_actor_update (screen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -254,27 +240,6 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
|
|||||||
return info->top_window_group;
|
return info->top_window_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_get_background_actor_for_screen:
|
|
||||||
* @screen: a #MetaScreen
|
|
||||||
*
|
|
||||||
* Gets the actor that draws the root window background under the windows.
|
|
||||||
* The root window background automatically tracks the image or color set
|
|
||||||
* by the environment.
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): The background actor corresponding to @screen
|
|
||||||
*/
|
|
||||||
ClutterActor *
|
|
||||||
meta_get_background_actor_for_screen (MetaScreen *screen)
|
|
||||||
{
|
|
||||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return info->background_actor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_get_window_actors:
|
* meta_get_window_actors:
|
||||||
* @screen: a #MetaScreen
|
* @screen: a #MetaScreen
|
||||||
@ -606,14 +571,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
|
|
||||||
info->window_group = meta_window_group_new (screen);
|
info->window_group = meta_window_group_new (screen);
|
||||||
info->top_window_group = meta_window_group_new (screen);
|
info->top_window_group = meta_window_group_new (screen);
|
||||||
info->background_actor = meta_background_actor_new_for_screen (screen);
|
|
||||||
clutter_actor_set_reactive (info->background_actor, TRUE);
|
|
||||||
info->overlay_group = clutter_group_new ();
|
info->overlay_group = clutter_group_new ();
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (info->window_group),
|
|
||||||
info->background_actor,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
clutter_container_add (CLUTTER_CONTAINER (info->stage),
|
clutter_container_add (CLUTTER_CONTAINER (info->stage),
|
||||||
info->window_group,
|
info->window_group,
|
||||||
info->top_window_group,
|
info->top_window_group,
|
||||||
@ -1066,6 +1025,7 @@ sync_actor_stacking (MetaCompScreen *info)
|
|||||||
GList *expected_window_node;
|
GList *expected_window_node;
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
GList *old;
|
GList *old;
|
||||||
|
GList *backgrounds;
|
||||||
gboolean has_windows;
|
gboolean has_windows;
|
||||||
gboolean reordered;
|
gboolean reordered;
|
||||||
|
|
||||||
@ -1083,15 +1043,19 @@ sync_actor_stacking (MetaCompScreen *info)
|
|||||||
* (we really need extra API to make that reliable.)
|
* (we really need extra API to make that reliable.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* First we check if the background is at the bottom. Then
|
/* First we collect a list of all backgrounds, and check if they're at the
|
||||||
* we check if the window actors are in the correct sequence */
|
* bottom. Then we check if the window actors are in the correct sequence */
|
||||||
|
backgrounds = NULL;
|
||||||
expected_window_node = info->windows;
|
expected_window_node = info->windows;
|
||||||
for (old = children; old != NULL; old = old->next)
|
for (old = children; old != NULL; old = old->next)
|
||||||
{
|
{
|
||||||
ClutterActor *actor = old->data;
|
ClutterActor *actor = old->data;
|
||||||
|
|
||||||
if (actor == info->background_actor)
|
if (META_IS_BACKGROUND_GROUP (actor) ||
|
||||||
|
META_IS_BACKGROUND_ACTOR (actor))
|
||||||
{
|
{
|
||||||
|
backgrounds = g_list_prepend (backgrounds, actor);
|
||||||
|
|
||||||
if (has_windows)
|
if (has_windows)
|
||||||
reordered = TRUE;
|
reordered = TRUE;
|
||||||
}
|
}
|
||||||
@ -1109,7 +1073,10 @@ sync_actor_stacking (MetaCompScreen *info)
|
|||||||
g_list_free (children);
|
g_list_free (children);
|
||||||
|
|
||||||
if (!reordered)
|
if (!reordered)
|
||||||
return;
|
{
|
||||||
|
g_list_free (backgrounds);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* reorder the actors by lowering them in turn to the bottom of the stack.
|
/* reorder the actors by lowering them in turn to the bottom of the stack.
|
||||||
* windows first, then background */
|
* windows first, then background */
|
||||||
@ -1120,7 +1087,16 @@ sync_actor_stacking (MetaCompScreen *info)
|
|||||||
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
|
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_actor_lower_bottom (info->background_actor);
|
/* we prepended the backgrounds above so the last actor in the list
|
||||||
|
* should get lowered to the bottom last.
|
||||||
|
*/
|
||||||
|
for (tmp = backgrounds; tmp != NULL; tmp = tmp->next)
|
||||||
|
{
|
||||||
|
ClutterActor *actor = tmp->data;
|
||||||
|
|
||||||
|
clutter_actor_lower_bottom (CLUTTER_ACTOR (actor));
|
||||||
|
}
|
||||||
|
g_list_free (backgrounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1276,8 +1252,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);
|
||||||
|
@ -9,7 +9,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);
|
cairo_region_t *meta_background_actor_get_visible_region (MetaBackgroundActor *self);
|
||||||
void meta_background_actor_screen_size_changed (MetaScreen *screen);
|
|
||||||
|
|
||||||
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */
|
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */
|
||||||
|
@ -34,223 +34,23 @@
|
|||||||
#include "cogl-utils.h"
|
#include "cogl-utils.h"
|
||||||
#include "compositor-private.h"
|
#include "compositor-private.h"
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
|
#include <meta/meta-background.h>
|
||||||
#include "meta-background-actor-private.h"
|
#include "meta-background-actor-private.h"
|
||||||
|
|
||||||
/* We allow creating multiple MetaBackgroundActors for the same MetaScreen to
|
|
||||||
* allow different rendering options to be set for different copies.
|
|
||||||
* But we want to share the same underlying CoglTexture for efficiency and
|
|
||||||
* to avoid driver bugs that might occur if we created multiple CoglTexturePixmaps
|
|
||||||
* for the same pixmap.
|
|
||||||
*
|
|
||||||
* This structure holds common information.
|
|
||||||
*/
|
|
||||||
typedef struct _MetaScreenBackground MetaScreenBackground;
|
|
||||||
|
|
||||||
struct _MetaScreenBackground
|
|
||||||
{
|
|
||||||
MetaScreen *screen;
|
|
||||||
GSList *actors;
|
|
||||||
|
|
||||||
float texture_width;
|
|
||||||
float texture_height;
|
|
||||||
CoglTexture *texture;
|
|
||||||
CoglMaterialWrapMode wrap_mode;
|
|
||||||
guint have_pixmap : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaBackgroundActorPrivate
|
struct _MetaBackgroundActorPrivate
|
||||||
{
|
{
|
||||||
MetaScreenBackground *background;
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
|
|
||||||
cairo_region_t *visible_region;
|
cairo_region_t *visible_region;
|
||||||
float dim_factor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
|
|
||||||
PROP_DIM_FACTOR,
|
|
||||||
|
|
||||||
PROP_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
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 set_texture (MetaScreenBackground *background,
|
|
||||||
CoglHandle texture);
|
|
||||||
static void set_texture_to_stage_color (MetaScreenBackground *background);
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_notify_stage_color (GObject *stage,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
MetaScreenBackground *background)
|
|
||||||
{
|
|
||||||
if (!background->have_pixmap)
|
|
||||||
set_texture_to_stage_color (background);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_screen_background (MetaScreenBackground *background)
|
|
||||||
{
|
|
||||||
set_texture (background, COGL_INVALID_HANDLE);
|
|
||||||
|
|
||||||
if (background->screen != NULL)
|
|
||||||
{
|
|
||||||
ClutterActor *stage = meta_get_stage_for_screen (background->screen);
|
|
||||||
g_signal_handlers_disconnect_by_func (stage,
|
|
||||||
(gpointer) on_notify_stage_color,
|
|
||||||
background);
|
|
||||||
background->screen = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaScreenBackground *
|
|
||||||
meta_screen_background_get (MetaScreen *screen)
|
|
||||||
{
|
|
||||||
MetaScreenBackground *background;
|
|
||||||
|
|
||||||
background = g_object_get_data (G_OBJECT (screen), "meta-screen-background");
|
|
||||||
if (background == NULL)
|
|
||||||
{
|
|
||||||
ClutterActor *stage;
|
|
||||||
|
|
||||||
background = g_new0 (MetaScreenBackground, 1);
|
|
||||||
|
|
||||||
background->screen = screen;
|
|
||||||
g_object_set_data_full (G_OBJECT (screen), "meta-screen-background",
|
|
||||||
background, (GDestroyNotify) free_screen_background);
|
|
||||||
|
|
||||||
stage = meta_get_stage_for_screen (screen);
|
|
||||||
g_signal_connect (stage, "notify::color",
|
|
||||||
G_CALLBACK (on_notify_stage_color), background);
|
|
||||||
|
|
||||||
meta_background_actor_update (screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
return background;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_wrap_mode_of_actor (MetaBackgroundActor *self)
|
|
||||||
{
|
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
|
|
||||||
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, priv->background->wrap_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_wrap_mode (MetaScreenBackground *background)
|
|
||||||
{
|
|
||||||
GSList *l;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
meta_screen_get_size (background->screen, &width, &height);
|
|
||||||
|
|
||||||
/* We turn off repeating when we have a full-screen pixmap to keep from
|
|
||||||
* getting artifacts from one side of the image sneaking into the other
|
|
||||||
* side of the image via bilinear filtering.
|
|
||||||
*/
|
|
||||||
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; l = l->next)
|
|
||||||
update_wrap_mode_of_actor (l->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_texture_on_actor (MetaBackgroundActor *self)
|
|
||||||
{
|
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
MetaDisplay *display = meta_screen_get_display (priv->background->screen);
|
|
||||||
|
|
||||||
/* This may trigger destruction of an old texture pixmap, which, if
|
|
||||||
* the underlying X pixmap is already gone has the tendency to trigger
|
|
||||||
* X errors inside DRI. For safety, trap errors */
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->background->texture);
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_texture (MetaScreenBackground *background,
|
|
||||||
CoglHandle texture)
|
|
||||||
{
|
|
||||||
MetaDisplay *display = meta_screen_get_display (background->screen);
|
|
||||||
GSList *l;
|
|
||||||
|
|
||||||
/* This may trigger destruction of an old texture pixmap, which, if
|
|
||||||
* the underlying X pixmap is already gone has the tendency to trigger
|
|
||||||
* X errors inside DRI. For safety, trap errors */
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
if (background->texture != COGL_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
cogl_handle_unref (background->texture);
|
|
||||||
background->texture = COGL_INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
|
|
||||||
if (texture != COGL_INVALID_HANDLE)
|
|
||||||
background->texture = cogl_handle_ref (texture);
|
|
||||||
|
|
||||||
background->texture_width = cogl_texture_get_width (background->texture);
|
|
||||||
background->texture_height = cogl_texture_get_height (background->texture);
|
|
||||||
|
|
||||||
for (l = background->actors; l; l = l->next)
|
|
||||||
set_texture_on_actor (l->data);
|
|
||||||
|
|
||||||
update_wrap_mode (background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sets our pipeline to paint with a 1x1 texture of the stage's background
|
|
||||||
* color; doing this when we have no pixmap allows the application to turn
|
|
||||||
* off painting the stage. There might be a performance benefit to
|
|
||||||
* painting in this case with a solid color, but the normal solid color
|
|
||||||
* case is a 1x1 root pixmap, so we'd have to reverse-engineer that to
|
|
||||||
* actually pick up the (small?) performance win. This is just a fallback.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
set_texture_to_stage_color (MetaScreenBackground *background)
|
|
||||||
{
|
|
||||||
ClutterActor *stage = meta_get_stage_for_screen (background->screen);
|
|
||||||
ClutterColor color;
|
|
||||||
CoglHandle texture;
|
|
||||||
|
|
||||||
clutter_stage_get_color (CLUTTER_STAGE (stage), &color);
|
|
||||||
|
|
||||||
/* Slicing will prevent COGL from using hardware texturing for
|
|
||||||
* the tiled 1x1 pixmap, and will cause it to draw the window
|
|
||||||
* background in millions of separate 1x1 rectangles */
|
|
||||||
texture = meta_create_color_texture_4ub (color.red, color.green,
|
|
||||||
color.blue, 0xff,
|
|
||||||
COGL_TEXTURE_NO_SLICING);
|
|
||||||
set_texture (background, texture);
|
|
||||||
cogl_handle_unref (texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_background_actor_dispose (GObject *object)
|
meta_background_actor_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
|
|
||||||
meta_background_actor_set_visible_region (self, NULL);
|
meta_background_actor_set_visible_region (self, NULL);
|
||||||
|
|
||||||
if (priv->background != NULL)
|
|
||||||
{
|
|
||||||
priv->background->actors = g_slist_remove (priv->background->actors, self);
|
|
||||||
priv->background = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer(&priv->pipeline, cogl_object_unref);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,11 +60,15 @@ meta_background_actor_get_preferred_width (ClutterActor *actor,
|
|||||||
gfloat *min_width_p,
|
gfloat *min_width_p,
|
||||||
gfloat *natural_width_p)
|
gfloat *natural_width_p)
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
ClutterContent *content;
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
gfloat width;
|
||||||
int width, height;
|
|
||||||
|
|
||||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
content = clutter_actor_get_content (actor);
|
||||||
|
|
||||||
|
if (content)
|
||||||
|
clutter_content_get_preferred_size (content, &width, NULL);
|
||||||
|
else
|
||||||
|
width = 0;
|
||||||
|
|
||||||
if (min_width_p)
|
if (min_width_p)
|
||||||
*min_width_p = width;
|
*min_width_p = width;
|
||||||
@ -279,11 +83,15 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
|
|||||||
gfloat *natural_height_p)
|
gfloat *natural_height_p)
|
||||||
|
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
ClutterContent *content;
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
gfloat height;
|
||||||
int width, height;
|
|
||||||
|
|
||||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
content = clutter_actor_get_content (actor);
|
||||||
|
|
||||||
|
if (content)
|
||||||
|
clutter_content_get_preferred_size (content, NULL, &height);
|
||||||
|
else
|
||||||
|
height = 0;
|
||||||
|
|
||||||
if (min_height_p)
|
if (min_height_p)
|
||||||
*min_height_p = height;
|
*min_height_p = height;
|
||||||
@ -291,64 +99,19 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
|
|||||||
*natural_height_p = height;
|
*natural_height_p = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
meta_background_actor_paint (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
guint8 opacity = clutter_actor_get_paint_opacity (actor);
|
|
||||||
guint8 color_component;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
|
||||||
|
|
||||||
color_component = (int)(0.5 + opacity * priv->dim_factor);
|
|
||||||
|
|
||||||
cogl_pipeline_set_color4ub (priv->pipeline,
|
|
||||||
color_component,
|
|
||||||
color_component,
|
|
||||||
color_component,
|
|
||||||
opacity);
|
|
||||||
|
|
||||||
cogl_set_source (priv->pipeline);
|
|
||||||
|
|
||||||
if (priv->visible_region)
|
|
||||||
{
|
|
||||||
int n_rectangles = cairo_region_num_rectangles (priv->visible_region);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_rectangles; i++)
|
|
||||||
{
|
|
||||||
cairo_rectangle_int_t rect;
|
|
||||||
cairo_region_get_rectangle (priv->visible_region, i, &rect);
|
|
||||||
|
|
||||||
cogl_rectangle_with_texture_coords (rect.x, rect.y,
|
|
||||||
rect.x + rect.width, rect.y + rect.height,
|
|
||||||
rect.x / priv->background->texture_width,
|
|
||||||
rect.y / priv->background->texture_height,
|
|
||||||
(rect.x + rect.width) / priv->background->texture_width,
|
|
||||||
(rect.y + rect.height) / priv->background->texture_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cogl_rectangle_with_texture_coords (0.0f, 0.0f,
|
|
||||||
width, height,
|
|
||||||
0.0f, 0.0f,
|
|
||||||
width / priv->background->texture_width,
|
|
||||||
height / priv->background->texture_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_background_actor_get_paint_volume (ClutterActor *actor,
|
meta_background_actor_get_paint_volume (ClutterActor *actor,
|
||||||
ClutterPaintVolume *volume)
|
ClutterPaintVolume *volume)
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
|
ClutterContent *content;
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
gfloat width, height;
|
||||||
int width, height;
|
|
||||||
|
|
||||||
meta_screen_get_size (priv->background->screen, &width, &height);
|
content = clutter_actor_get_content (actor);
|
||||||
|
|
||||||
|
if (!content)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
clutter_content_get_preferred_size (content, &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);
|
||||||
@ -356,215 +119,48 @@ meta_background_actor_get_paint_volume (ClutterActor *actor,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
meta_background_actor_set_dim_factor (MetaBackgroundActor *self,
|
|
||||||
gfloat dim_factor)
|
|
||||||
{
|
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
|
|
||||||
if (priv->dim_factor == dim_factor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
priv->dim_factor = dim_factor;
|
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_DIM_FACTOR]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_background_actor_get_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
|
||||||
MetaBackgroundActorPrivate *priv = self->priv;
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_DIM_FACTOR:
|
|
||||||
g_value_set_float (value, priv->dim_factor);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_background_actor_set_property(GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_DIM_FACTOR:
|
|
||||||
meta_background_actor_set_dim_factor (self, g_value_get_float (value));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
|
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GParamSpec *pspec;
|
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
|
g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
|
||||||
|
|
||||||
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->set_property = meta_background_actor_set_property;
|
|
||||||
|
|
||||||
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->get_paint_volume = meta_background_actor_get_paint_volume;
|
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
|
||||||
|
|
||||||
/**
|
|
||||||
* MetaBackgroundActor:dim-factor:
|
|
||||||
*
|
|
||||||
* Factor to dim the background by, between 0.0 (black) and 1.0 (original
|
|
||||||
* colors)
|
|
||||||
*/
|
|
||||||
pspec = g_param_spec_float ("dim-factor",
|
|
||||||
"Dim factor",
|
|
||||||
"Factor to dim the background by",
|
|
||||||
0.0, 1.0,
|
|
||||||
1.0,
|
|
||||||
G_PARAM_READWRITE);
|
|
||||||
obj_props[PROP_DIM_FACTOR] = pspec;
|
|
||||||
g_object_class_install_property (object_class, PROP_DIM_FACTOR, pspec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_background_actor_init (MetaBackgroundActor *self)
|
meta_background_actor_init (MetaBackgroundActor *self)
|
||||||
{
|
{
|
||||||
MetaBackgroundActorPrivate *priv;
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
META_TYPE_BACKGROUND_ACTOR,
|
||||||
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
MetaBackgroundActorPrivate);
|
||||||
META_TYPE_BACKGROUND_ACTOR,
|
|
||||||
MetaBackgroundActorPrivate);
|
|
||||||
priv->dim_factor = 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_background_actor_new:
|
* meta_background_actor_new:
|
||||||
* @screen: the #MetaScreen
|
|
||||||
*
|
*
|
||||||
* Creates a new actor to draw the background for the given screen.
|
* Creates a new actor to draw the background for the given monitor.
|
||||||
|
* This actor should be associated with a #MetaBackground using
|
||||||
|
* clutter_actor_set_content()
|
||||||
*
|
*
|
||||||
* Return value: the newly created background actor
|
* Return value: the newly created background actor
|
||||||
*/
|
*/
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
meta_background_actor_new_for_screen (MetaScreen *screen)
|
meta_background_actor_new (void)
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *self;
|
MetaBackgroundActor *self;
|
||||||
MetaBackgroundActorPrivate *priv;
|
|
||||||
|
|
||||||
g_return_val_if_fail (META_IS_SCREEN (screen), NULL);
|
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
|
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
|
||||||
priv = self->priv;
|
|
||||||
|
|
||||||
priv->background = meta_screen_background_get (screen);
|
|
||||||
priv->background->actors = g_slist_prepend (priv->background->actors, self);
|
|
||||||
|
|
||||||
/* A CoglMaterial and a CoglPipeline are the same thing */
|
|
||||||
priv->pipeline = (CoglPipeline*) meta_create_texture_material (NULL);
|
|
||||||
|
|
||||||
set_texture_on_actor (self);
|
|
||||||
update_wrap_mode_of_actor (self);
|
|
||||||
|
|
||||||
return CLUTTER_ACTOR (self);
|
return CLUTTER_ACTOR (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_background_actor_update:
|
|
||||||
* @screen: a #MetaScreen
|
|
||||||
*
|
|
||||||
* Refetches the _XROOTPMAP_ID property for the root window and updates
|
|
||||||
* the contents of the background actor based on that. There's no attempt
|
|
||||||
* to optimize out pixmap values that don't change (since a root pixmap
|
|
||||||
* could be replaced by with another pixmap with the same ID under some
|
|
||||||
* circumstances), so this should only be called when we actually receive
|
|
||||||
* a PropertyNotify event for the property.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
meta_background_actor_update (MetaScreen *screen)
|
|
||||||
{
|
|
||||||
MetaScreenBackground *background;
|
|
||||||
MetaDisplay *display;
|
|
||||||
MetaCompositor *compositor;
|
|
||||||
Atom type;
|
|
||||||
int format;
|
|
||||||
gulong nitems;
|
|
||||||
gulong bytes_after;
|
|
||||||
guchar *data;
|
|
||||||
Pixmap root_pixmap_id;
|
|
||||||
|
|
||||||
background = meta_screen_background_get (screen);
|
|
||||||
display = meta_screen_get_display (screen);
|
|
||||||
compositor = meta_display_get_compositor (display);
|
|
||||||
|
|
||||||
root_pixmap_id = None;
|
|
||||||
if (!XGetWindowProperty (meta_display_get_xdisplay (display),
|
|
||||||
meta_screen_get_xroot (screen),
|
|
||||||
compositor->atom_x_root_pixmap,
|
|
||||||
0, LONG_MAX,
|
|
||||||
False,
|
|
||||||
AnyPropertyType,
|
|
||||||
&type, &format, &nitems, &bytes_after, &data) &&
|
|
||||||
type != None)
|
|
||||||
{
|
|
||||||
/* Got a property. */
|
|
||||||
if (type == XA_PIXMAP && format == 32 && nitems == 1)
|
|
||||||
{
|
|
||||||
/* Was what we expected. */
|
|
||||||
root_pixmap_id = *(Pixmap *)data;
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (root_pixmap_id != None)
|
|
||||||
{
|
|
||||||
CoglHandle texture;
|
|
||||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
texture = cogl_texture_pixmap_x11_new (ctx, root_pixmap_id, FALSE, &error);
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
|
|
||||||
if (texture != COGL_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
set_texture (background, texture);
|
|
||||||
cogl_handle_unref (texture);
|
|
||||||
|
|
||||||
background->have_pixmap = True;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("Failed to create background texture from pixmap: %s",
|
|
||||||
error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background->have_pixmap = False;
|
|
||||||
set_texture_to_stage_color (background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_background_actor_set_visible_region:
|
* meta_background_actor_set_visible_region:
|
||||||
* @self: a #MetaBackgroundActor
|
* @self: a #MetaBackgroundActor
|
||||||
@ -584,120 +180,44 @@ meta_background_actor_set_visible_region (MetaBackgroundActor *self,
|
|||||||
|
|
||||||
priv = self->priv;
|
priv = self->priv;
|
||||||
|
|
||||||
if (priv->visible_region)
|
g_clear_pointer (&priv->visible_region,
|
||||||
{
|
(GDestroyNotify)
|
||||||
cairo_region_destroy (priv->visible_region);
|
cairo_region_destroy);
|
||||||
priv->visible_region = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visible_region)
|
if (visible_region)
|
||||||
{
|
priv->visible_region = cairo_region_copy (visible_region);
|
||||||
cairo_rectangle_int_t screen_rect = { 0 };
|
|
||||||
meta_screen_get_size (priv->background->screen, &screen_rect.width, &screen_rect.height);
|
|
||||||
|
|
||||||
/* Doing the intersection here is probably unnecessary - MetaWindowGroup
|
|
||||||
* should never compute a visible area that's larger than the root screen!
|
|
||||||
* but it's not that expensive and adds some extra robustness.
|
|
||||||
*/
|
|
||||||
priv->visible_region = cairo_region_create_rectangle (&screen_rect);
|
|
||||||
cairo_region_intersect (priv->visible_region, visible_region);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_background_actor_screen_size_changed:
|
* meta_background_actor_get_visible_region:
|
||||||
* @screen: a #MetaScreen
|
* @self: a #MetaBackgroundActor
|
||||||
*
|
*
|
||||||
* Called by the compositor when the size of the #MetaScreen changes
|
* Return value (transfer full): a #cairo_region_t that represents the part of
|
||||||
|
* the background not obscured by other #MetaBackgroundActor or
|
||||||
|
* #MetaWindowActor objects.
|
||||||
*/
|
*/
|
||||||
void
|
cairo_region_t *
|
||||||
meta_background_actor_screen_size_changed (MetaScreen *screen)
|
meta_background_actor_get_visible_region (MetaBackgroundActor *self)
|
||||||
{
|
{
|
||||||
MetaScreenBackground *background = meta_screen_background_get (screen);
|
MetaBackgroundActorPrivate *priv = self->priv;
|
||||||
GSList *l;
|
ClutterActorBox content_box;
|
||||||
|
cairo_rectangle_int_t content_area = { 0 };
|
||||||
|
cairo_region_t *visible_region;
|
||||||
|
|
||||||
update_wrap_mode (background);
|
g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
|
||||||
|
|
||||||
for (l = background->actors; l; l = l->next)
|
if (!priv->visible_region)
|
||||||
clutter_actor_queue_relayout (l->data);
|
return NULL;
|
||||||
|
|
||||||
|
clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
|
||||||
|
|
||||||
|
content_area.x = content_box.x1;
|
||||||
|
content_area.y = content_box.y1;
|
||||||
|
content_area.width = content_box.x2 - content_box.x1;
|
||||||
|
content_area.height = content_box.y2 - content_box.y1;
|
||||||
|
|
||||||
|
visible_region = cairo_region_create_rectangle (&content_area);
|
||||||
|
cairo_region_intersect (visible_region, priv->visible_region);
|
||||||
|
|
||||||
|
return visible_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_background_actor_add_glsl_snippet:
|
|
||||||
* @actor: a #MetaBackgroundActor
|
|
||||||
* @hook: where to insert the code
|
|
||||||
* @declarations: GLSL declarations
|
|
||||||
* @code: GLSL code
|
|
||||||
* @is_replace: wheter Cogl code should be replaced by the custom shader
|
|
||||||
*
|
|
||||||
* Adds a GLSL snippet to the pipeline used for drawing the background.
|
|
||||||
* See #CoglSnippet for details.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
meta_background_actor_add_glsl_snippet (MetaBackgroundActor *actor,
|
|
||||||
MetaSnippetHook hook,
|
|
||||||
const char *declarations,
|
|
||||||
const char *code,
|
|
||||||
gboolean is_replace)
|
|
||||||
{
|
|
||||||
MetaBackgroundActorPrivate *priv;
|
|
||||||
CoglSnippet *snippet;
|
|
||||||
|
|
||||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (actor));
|
|
||||||
|
|
||||||
priv = actor->priv;
|
|
||||||
|
|
||||||
if (is_replace)
|
|
||||||
{
|
|
||||||
snippet = cogl_snippet_new (hook, declarations, NULL);
|
|
||||||
cogl_snippet_set_replace (snippet, code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snippet = cogl_snippet_new (hook, declarations, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hook == META_SNIPPET_HOOK_VERTEX ||
|
|
||||||
hook == META_SNIPPET_HOOK_FRAGMENT)
|
|
||||||
cogl_pipeline_add_snippet (priv->pipeline, snippet);
|
|
||||||
else
|
|
||||||
cogl_pipeline_add_layer_snippet (priv->pipeline, 0, snippet);
|
|
||||||
|
|
||||||
cogl_object_unref (snippet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_background_actor_set_uniform_float:
|
|
||||||
* @actor: a #MetaBackgroundActor
|
|
||||||
* @uniform_name:
|
|
||||||
* @n_components: number of components (for vector uniforms)
|
|
||||||
* @count: number of uniforms (for array uniforms)
|
|
||||||
* @uniform: (array length=uniform_length): the float values to set
|
|
||||||
* @uniform_length: the length of @uniform. Must be exactly @n_components x @count,
|
|
||||||
* and is provided mainly for language bindings.
|
|
||||||
*
|
|
||||||
* Sets a new GLSL uniform to the provided value. This is mostly
|
|
||||||
* useful in congiunction with meta_background_actor_add_glsl_snippet().
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_background_actor_set_uniform_float (MetaBackgroundActor *actor,
|
|
||||||
const char *uniform_name,
|
|
||||||
int n_components,
|
|
||||||
int count,
|
|
||||||
const float *uniform,
|
|
||||||
int uniform_length)
|
|
||||||
{
|
|
||||||
MetaBackgroundActorPrivate *priv;
|
|
||||||
|
|
||||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (actor));
|
|
||||||
g_return_if_fail (uniform_length == n_components * count);
|
|
||||||
|
|
||||||
priv = actor->priv;
|
|
||||||
|
|
||||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
|
||||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
|
||||||
uniform_name),
|
|
||||||
n_components, count, uniform);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
11
src/compositor/meta-background-group-private.h
Normal file
11
src/compositor/meta-background-group-private.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#ifndef META_BACKGROUND_GROUP_PRIVATE_H
|
||||||
|
#define META_BACKGROUND_GROUP_PRIVATE_H
|
||||||
|
|
||||||
|
#include <meta/screen.h>
|
||||||
|
#include <meta/meta-background-group.h>
|
||||||
|
|
||||||
|
void meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||||
|
cairo_region_t *visible_region);
|
||||||
|
#endif /* META_BACKGROUND_GROUP_PRIVATE_H */
|
92
src/compositor/meta-background-group.c
Normal file
92
src/compositor/meta-background-group.c
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "compositor-private.h"
|
||||||
|
#include "clutter-utils.h"
|
||||||
|
#include "meta-background-actor-private.h"
|
||||||
|
#include "meta-background-group-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_GROUP);
|
||||||
|
|
||||||
|
struct _MetaBackgroundGroupPrivate
|
||||||
|
{
|
||||||
|
ClutterLayoutManager *layout_manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_background_group_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (meta_background_group_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_background_group_class_init (MetaBackgroundGroupClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = meta_background_group_dispose;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (MetaBackgroundGroupPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_background_group_init (MetaBackgroundGroup *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
META_TYPE_BACKGROUND_GROUP,
|
||||||
|
MetaBackgroundGroupPrivate);
|
||||||
|
|
||||||
|
self->priv->layout_manager = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_FIXED,
|
||||||
|
CLUTTER_BIN_ALIGNMENT_FIXED);
|
||||||
|
|
||||||
|
clutter_actor_set_layout_manager (CLUTTER_ACTOR (self), self->priv->layout_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_background_group_set_visible_region:
|
||||||
|
* @self: a #MetaBackgroundGroup
|
||||||
|
* @visible_region: (allow-none): the parts of the background to paint
|
||||||
|
*
|
||||||
|
* Sets the area of the backgrounds that is unobscured by overlapping windows.
|
||||||
|
* This is used to optimize and only paint the visible portions.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_background_group_set_visible_region (MetaBackgroundGroup *self,
|
||||||
|
cairo_region_t *region)
|
||||||
|
{
|
||||||
|
GList *children, *l;
|
||||||
|
|
||||||
|
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
|
||||||
|
for (l = children; l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterActor *actor = l->data;
|
||||||
|
|
||||||
|
if (META_IS_BACKGROUND_ACTOR (actor))
|
||||||
|
{
|
||||||
|
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
|
||||||
|
}
|
||||||
|
else if (META_IS_BACKGROUND_GROUP (actor))
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if (!meta_actor_is_untransformed (actor, &x, &y))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cairo_region_translate (region, -x, -y);
|
||||||
|
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (actor), region);
|
||||||
|
cairo_region_translate (region, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_list_free (children);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterActor *
|
||||||
|
meta_background_group_new (void)
|
||||||
|
{
|
||||||
|
MetaBackgroundGroup *background_group;
|
||||||
|
|
||||||
|
background_group = g_object_new (META_TYPE_BACKGROUND_GROUP, NULL);
|
||||||
|
|
||||||
|
return CLUTTER_ACTOR (background_group);
|
||||||
|
}
|
1324
src/compositor/meta-background.c
Normal file
1324
src/compositor/meta-background.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||||
|
|
||||||
|
#include "clutter-utils.h"
|
||||||
#include "compositor-private.h"
|
#include "compositor-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-window-group.h"
|
#include "meta-window-group.h"
|
||||||
#include "meta-background-actor-private.h"
|
#include "meta-background-actor-private.h"
|
||||||
#include "clutter-utils.h"
|
#include "meta-background-group-private.h"
|
||||||
|
|
||||||
struct _MetaWindowGroupClass
|
struct _MetaWindowGroupClass
|
||||||
{
|
{
|
||||||
@ -203,9 +204,10 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
|
||||||
cairo_region_translate (visible_region, x, y);
|
cairo_region_translate (visible_region, x, y);
|
||||||
}
|
}
|
||||||
else if (META_IS_BACKGROUND_ACTOR (l->data))
|
else if (META_IS_BACKGROUND_ACTOR (l->data) ||
|
||||||
|
META_IS_BACKGROUND_GROUP (l->data))
|
||||||
{
|
{
|
||||||
MetaBackgroundActor *background_actor = l->data;
|
ClutterActor *background_actor = l->data;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
|
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
|
||||||
@ -215,7 +217,11 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
y += paint_y_offset;
|
y += paint_y_offset;
|
||||||
|
|
||||||
cairo_region_translate (visible_region, - x, - y);
|
cairo_region_translate (visible_region, - x, - y);
|
||||||
meta_background_actor_set_visible_region (background_actor, visible_region);
|
|
||||||
|
if (META_IS_BACKGROUND_GROUP (background_actor))
|
||||||
|
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
|
||||||
|
else
|
||||||
|
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
|
||||||
cairo_region_translate (visible_region, x, y);
|
cairo_region_translate (visible_region, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ ClutterActor *meta_get_top_window_group_for_screen (MetaScreen *screen);
|
|||||||
void meta_disable_unredirect_for_screen (MetaScreen *screen);
|
void meta_disable_unredirect_for_screen (MetaScreen *screen);
|
||||||
void meta_enable_unredirect_for_screen (MetaScreen *screen);
|
void meta_enable_unredirect_for_screen (MetaScreen *screen);
|
||||||
|
|
||||||
ClutterActor *meta_get_background_actor_for_screen (MetaScreen *screen);
|
|
||||||
void meta_set_stage_input_region (MetaScreen *screen,
|
void meta_set_stage_input_region (MetaScreen *screen,
|
||||||
XserverRegion region);
|
XserverRegion region);
|
||||||
void meta_empty_stage_input_region (MetaScreen *screen);
|
void meta_empty_stage_input_region (MetaScreen *screen);
|
||||||
|
@ -24,9 +24,13 @@
|
|||||||
#define META_BACKGROUND_ACTOR_H
|
#define META_BACKGROUND_ACTOR_H
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include <meta/gradient.h>
|
||||||
#include <meta/screen.h>
|
#include <meta/screen.h>
|
||||||
|
|
||||||
|
#include <gsettings-desktop-schemas/gdesktop-enums.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MetaBackgroundActor:
|
* MetaBackgroundActor:
|
||||||
*
|
*
|
||||||
@ -60,41 +64,6 @@ 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 (void);
|
||||||
|
|
||||||
/**
|
|
||||||
* MetaSnippetHook:
|
|
||||||
* Temporary hack to work around Cogl not exporting CoglSnippetHook in
|
|
||||||
* the 1.0 API. Don't use.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
/* Per pipeline vertex hooks */
|
|
||||||
META_SNIPPET_HOOK_VERTEX = 0,
|
|
||||||
META_SNIPPET_HOOK_VERTEX_TRANSFORM,
|
|
||||||
|
|
||||||
/* Per pipeline fragment hooks */
|
|
||||||
META_SNIPPET_HOOK_FRAGMENT = 2048,
|
|
||||||
|
|
||||||
/* Per layer vertex hooks */
|
|
||||||
META_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096,
|
|
||||||
|
|
||||||
/* Per layer fragment hooks */
|
|
||||||
META_SNIPPET_HOOK_LAYER_FRAGMENT = 6144,
|
|
||||||
META_SNIPPET_HOOK_TEXTURE_LOOKUP
|
|
||||||
} MetaSnippetHook;
|
|
||||||
|
|
||||||
|
|
||||||
void meta_background_actor_add_glsl_snippet (MetaBackgroundActor *actor,
|
|
||||||
MetaSnippetHook hook,
|
|
||||||
const char *declarations,
|
|
||||||
const char *code,
|
|
||||||
gboolean is_replace);
|
|
||||||
|
|
||||||
void meta_background_actor_set_uniform_float (MetaBackgroundActor *actor,
|
|
||||||
const char *uniform_name,
|
|
||||||
int n_components,
|
|
||||||
int count,
|
|
||||||
const float *uniform,
|
|
||||||
int uniform_length);
|
|
||||||
|
|
||||||
#endif /* META_BACKGROUND_ACTOR_H */
|
#endif /* META_BACKGROUND_ACTOR_H */
|
||||||
|
46
src/meta/meta-background-group.h
Normal file
46
src/meta/meta-background-group.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
#ifndef META_BACKGROUND_GROUP_H
|
||||||
|
#define META_BACKGROUND_GROUP_H
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetaBackgroundGroup:
|
||||||
|
*
|
||||||
|
* This class is a subclass of ClutterGroup with special handling for
|
||||||
|
* MetaBackgroundActor when painting the group. It makes sure to only
|
||||||
|
* draw the parts of the backgrounds not occluded by opaque windows.
|
||||||
|
*
|
||||||
|
* See #MetaWindowGroup for more information behind the motivation,
|
||||||
|
* and details on implementation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define META_TYPE_BACKGROUND_GROUP (meta_background_group_get_type ())
|
||||||
|
#define META_BACKGROUND_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_GROUP, MetaBackgroundGroup))
|
||||||
|
#define META_BACKGROUND_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKGROUND_GROUP, MetaBackgroundGroupClass))
|
||||||
|
#define META_IS_BACKGROUND_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_GROUP))
|
||||||
|
#define META_IS_BACKGROUND_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKGROUND_GROUP))
|
||||||
|
#define META_BACKGROUND_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKGROUND_GROUP, MetaBackgroundGroupClass))
|
||||||
|
|
||||||
|
typedef struct _MetaBackgroundGroup MetaBackgroundGroup;
|
||||||
|
typedef struct _MetaBackgroundGroupClass MetaBackgroundGroupClass;
|
||||||
|
typedef struct _MetaBackgroundGroupPrivate MetaBackgroundGroupPrivate;
|
||||||
|
|
||||||
|
struct _MetaBackgroundGroupClass
|
||||||
|
{
|
||||||
|
ClutterGroupClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaBackgroundGroup
|
||||||
|
{
|
||||||
|
ClutterGroup parent;
|
||||||
|
|
||||||
|
MetaBackgroundGroupPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType meta_background_group_get_type (void);
|
||||||
|
|
||||||
|
ClutterActor *meta_background_group_new (void);
|
||||||
|
|
||||||
|
#endif /* META_BACKGROUND_GROUP_H */
|
110
src/meta/meta-background.h
Normal file
110
src/meta/meta-background.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
/*
|
||||||
|
* meta-background.h: CoglTexture for paintnig the system background
|
||||||
|
*
|
||||||
|
* Copyright 2013 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_BACKGROUND_H
|
||||||
|
#define META_BACKGROUND_H
|
||||||
|
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include <meta/gradient.h>
|
||||||
|
#include <meta/screen.h>
|
||||||
|
|
||||||
|
#include <gsettings-desktop-schemas/gdesktop-enums.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetaBackground:
|
||||||
|
*
|
||||||
|
* This class handles loading a background from file, screenshot, or
|
||||||
|
* color scheme. The resulting object can be associated with one or
|
||||||
|
* more #MetaBackgroundActor objects to handle loading the background.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define META_TYPE_BACKGROUND (meta_background_get_type ())
|
||||||
|
#define META_BACKGROUND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND, MetaBackground))
|
||||||
|
#define META_BACKGROUND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKGROUND, MetaBackgroundClass))
|
||||||
|
#define META_IS_BACKGROUND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND))
|
||||||
|
#define META_IS_BACKGROUND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKGROUND))
|
||||||
|
#define META_BACKGROUND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKGROUND, MetaBackgroundClass))
|
||||||
|
|
||||||
|
typedef struct _MetaBackground MetaBackground;
|
||||||
|
typedef struct _MetaBackgroundClass MetaBackgroundClass;
|
||||||
|
typedef struct _MetaBackgroundPrivate MetaBackgroundPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetaBackgroundEffects:
|
||||||
|
* Which effects to enable on the background
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_BACKGROUND_EFFECTS_NONE = 0,
|
||||||
|
META_BACKGROUND_EFFECTS_DESATURATE = 1 << 0,
|
||||||
|
META_BACKGROUND_EFFECTS_BLUR = 1 << 1,
|
||||||
|
META_BACKGROUND_EFFECTS_VIGNETTE = 1 << 2,
|
||||||
|
} MetaBackgroundEffects;
|
||||||
|
|
||||||
|
struct _MetaBackgroundClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaBackground
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
MetaBackgroundPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType meta_background_get_type (void);
|
||||||
|
|
||||||
|
MetaBackground *meta_background_new (MetaScreen *screen,
|
||||||
|
int monitor,
|
||||||
|
MetaBackgroundEffects effects);
|
||||||
|
MetaBackground *meta_background_copy (MetaBackground *self,
|
||||||
|
int monitor,
|
||||||
|
MetaBackgroundEffects effects);
|
||||||
|
|
||||||
|
void meta_background_load_gradient (MetaBackground *self,
|
||||||
|
GDesktopBackgroundShading shading_direction,
|
||||||
|
ClutterColor *color,
|
||||||
|
ClutterColor *second_color);
|
||||||
|
void meta_background_load_color (MetaBackground *self,
|
||||||
|
ClutterColor *color);
|
||||||
|
void meta_background_load_still_frame (MetaBackground *self);
|
||||||
|
void meta_background_load_file_async (MetaBackground *self,
|
||||||
|
const char *filename,
|
||||||
|
GDesktopBackgroundStyle style,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
gboolean meta_background_load_file_finish (MetaBackground *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
const char *meta_background_get_filename (MetaBackground *self);
|
||||||
|
GDesktopBackgroundStyle meta_background_get_style (MetaBackground *self);
|
||||||
|
GDesktopBackgroundShading meta_background_get_shading (MetaBackground *self);
|
||||||
|
const ClutterColor *meta_background_get_color (MetaBackground *self);
|
||||||
|
const ClutterColor *meta_background_get_second_color (MetaBackground *self);
|
||||||
|
|
||||||
|
#endif /* META_BACKGROUND_H */
|
Loading…
Reference in New Issue
Block a user