aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac5
-rw-r--r--matchbox2/Makefile.am1
-rw-r--r--matchbox2/mb-wm-comp-mgr-clutter.c411
-rw-r--r--matchbox2/tidy/tidy-texture-frame.c641
-rw-r--r--matchbox2/tidy/tidy-texture-frame.h84
5 files changed, 746 insertions, 396 deletions
diff --git a/configure.ac b/configure.ac
index d3eeada..977d8d8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,7 +30,8 @@ AC_SUBST(MBWM2_INCDIR)
MBWM2_PKGINCDIR=matchbox-wm-2/$MBWM2_API_VERSION/
AC_SUBST(MBWM2_PKGINCDIR)
-clutter_package=clutter-0.8
+clutter_package=clutter-1.0
+clutter_min_version=1.3
AC_PROG_CC
@@ -148,7 +149,7 @@ for composite_manager in $included_composite_managers; do
MBWM_EXTRA_LIBS="$MBWM_EXTRA_LIBS -lm"
;;
clutter )
- needed_pkgs="$needed_pkgs $clutter_package xcomposite xdamage "
+ needed_pkgs="$needed_pkgs $clutter_package >= $clutter_min_version xcomposite xdamage "
gmloop="yes"
;;
esac
diff --git a/matchbox2/Makefile.am b/matchbox2/Makefile.am
index 47dfdc8..d192b40 100644
--- a/matchbox2/Makefile.am
+++ b/matchbox2/Makefile.am
@@ -71,6 +71,7 @@ if COMP_MGR_BACKEND
if ENABLE_CLUTTER_COMPOSITE_MANAGER
source += mb-wm-comp-mgr-clutter.h
source += mb-wm-comp-mgr-clutter.c
+source += tidy/tidy-texture-frame.h tidy/tidy-texture-frame.c
else
source += mb-wm-comp-mgr-xrender.h
source += mb-wm-comp-mgr-xrender.c
diff --git a/matchbox2/mb-wm-comp-mgr-clutter.c b/matchbox2/mb-wm-comp-mgr-clutter.c
index 0fd5472..0fd011f 100644
--- a/matchbox2/mb-wm-comp-mgr-clutter.c
+++ b/matchbox2/mb-wm-comp-mgr-clutter.c
@@ -23,6 +23,7 @@
#include "mb-wm-comp-mgr.h"
#include "mb-wm-comp-mgr-clutter.h"
#include "mb-wm-theme.h"
+#include "tidy/tidy-texture-frame.h"
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
@@ -44,13 +45,6 @@
#define WIDTH (3*MAX_TILE_SZ)
#define HEIGHT (3*MAX_TILE_SZ)
-static ClutterActor *
-tidy_texture_frame_new (ClutterTexture *texture,
- gint left,
- gint top,
- gint right,
- gint bottom);
-
static unsigned char *
mb_wm_comp_mgr_clutter_shadow_gaussian_make_tile ();
@@ -413,19 +407,18 @@ mb_wm_comp_mgr_clutter_client_event_new (MBWMCompMgrClient *client,
ClutterAlpha * alpha;
MBWMCompMgrClutterClient * cclient = MB_WM_COMP_MGR_CLUTTER_CLIENT (client);
MBWindowManager * wm = client->wm;
- ClutterKnot knots[2];
+ ClutterPath * path;
MBGeometry geom;
if (!cclient->priv->actor)
return NULL;
- timeline = clutter_timeline_new_for_duration (duration);
+ timeline = clutter_timeline_new (duration);
if (!timeline)
return NULL;
- alpha = clutter_alpha_new_full (timeline,
- CLUTTER_ALPHA_RAMP_INC, NULL, NULL);
+ alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR);
mb_wm_client_get_coverage (client->wm_client, &geom);
@@ -433,17 +426,16 @@ mb_wm_comp_mgr_clutter_client_event_new (MBWMCompMgrClient *client,
{
case MBWMCompMgrClientEventMinimize:
behaviour =
- clutter_behaviour_scale_newx (alpha, CFX_ONE, CFX_ONE, 0, 0);
+ clutter_behaviour_scale_new (alpha, 1.0, 1.0, 0, 0);
break;
case MBWMCompMgrClientEventUnmap:
behaviour = clutter_behaviour_opacity_new (alpha, 0xff, 0);
break;
case MBWMCompMgrClientEventMap:
- knots[0].x = -wm->xdpy_width;
- knots[0].y = geom.y;
- knots[1].x = geom.x;
- knots[1].y = geom.y;
- behaviour = clutter_behaviour_path_new (alpha, &knots[0], 2);
+ path = clutter_path_new ();
+ clutter_path_add_move_to (path, -wm->xdpy_width, geom.y);
+ clutter_path_add_line_to (path, geom.x, geom.y);
+ behaviour = clutter_behaviour_path_new (alpha, path);
break;
}
@@ -1163,10 +1155,9 @@ mb_wm_comp_mgr_clutter_client_transition_fade (MBWMCompMgrClutterClient *cclient
* children, as the stacking order automatically takes care of the
* actor appearing to fade out from the first one
*/
- timeline = clutter_timeline_new_for_duration (duration);
+ timeline = clutter_timeline_new (duration);
- alpha = clutter_alpha_new_full (timeline,
- CLUTTER_ALPHA_RAMP_DEC, NULL, NULL);
+ alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR);
b = clutter_behaviour_opacity_new (alpha, 0xff, 0);
@@ -1279,17 +1270,14 @@ mb_wm_comp_mgr_clutter_client_event_real (MBWMCompMgr * mgr,
* of the list.
*/
- GSList * knots =
- clutter_behaviour_path_get_knots (
+ ClutterPath *path =
+ clutter_behaviour_path_get_path (
CLUTTER_BEHAVIOUR_PATH (eff->behaviour));
-
- if (knots)
+ if (path)
{
- ClutterKnot * k = knots->data;
-
- clutter_actor_set_position (a, k->x, k->y);
-
- g_slist_free (knots);
+ ClutterKnot k;
+ clutter_path_get_position (path, 0, &k);
+ clutter_actor_set_position (a, k.x, k.y);
}
}
@@ -1688,369 +1676,4 @@ mb_wm_comp_mgr_clutter_shadow_gaussian_make_tile ()
return data;
}
-/*
- * TidyTextureFrame copied from tidy
- */
-#include <cogl/cogl.h>
-
-#define TIDY_PARAM_READWRITE \
- (G_PARAM_READABLE | G_PARAM_WRITABLE | \
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
-
-#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ())
-
-#define TIDY_TEXTURE_FRAME(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame))
-
-#define TIDY_TEXTURE_FRAME_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
-
-#define TIDY_IS_TEXTURE_FRAME(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- TIDY_TYPE_TEXTURE_FRAME))
-
-#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- TIDY_TYPE_TEXTURE_FRAME))
-
-#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
-
-typedef struct _TidyTextureFrame TidyTextureFrame;
-typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate;
-typedef struct _TidyTextureFrameClass TidyTextureFrameClass;
-
-struct _TidyTextureFrame
-{
- ClutterCloneTexture parent;
-
- /*< priv >*/
- TidyTextureFramePrivate *priv;
-};
-
-struct _TidyTextureFrameClass
-{
- ClutterCloneTextureClass parent_class;
-};
-
-enum
- {
- PROP_0,
- PROP_LEFT,
- PROP_TOP,
- PROP_RIGHT,
- PROP_BOTTOM
- };
-
-G_DEFINE_TYPE (TidyTextureFrame,
- tidy_texture_frame,
- CLUTTER_TYPE_CLONE_TEXTURE);
-
-#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate))
-
-struct _TidyTextureFramePrivate
-{
- gint left, top, right, bottom;
-};
-
-static void
-tidy_texture_frame_paint (ClutterActor *self)
-{
- TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
- ClutterCloneTexture *clone_texture = CLUTTER_CLONE_TEXTURE (self);
- ClutterTexture *parent_texture;
- guint width, height;
- guint tex_width, tex_height;
- guint ex, ey;
- ClutterFixed tx1, ty1, tx2, ty2;
- ClutterColor col = { 0xff, 0xff, 0xff, 0xff };
- CoglHandle cogl_texture;
-
- priv = TIDY_TEXTURE_FRAME (self)->priv;
-
- /* no need to paint stuff if we don't have a texture */
- parent_texture = clutter_clone_texture_get_parent_texture (clone_texture);
- if (!parent_texture)
- return;
-
- /* parent texture may have been hidden, so need to make sure it gets
- * realized
- */
- if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture))
- clutter_actor_realize (CLUTTER_ACTOR (parent_texture));
-
- cogl_texture = clutter_texture_get_cogl_texture (parent_texture);
- if (cogl_texture == COGL_INVALID_HANDLE)
- return;
-
- cogl_push_matrix ();
-
- tex_width = cogl_texture_get_width (cogl_texture);
- tex_height = cogl_texture_get_height (cogl_texture);
-
- clutter_actor_get_size (self, &width, &height);
-
- tx1 = CLUTTER_INT_TO_FIXED (priv->left) / tex_width;
- tx2 = CLUTTER_INT_TO_FIXED (tex_width - priv->right) / tex_width;
- ty1 = CLUTTER_INT_TO_FIXED (priv->top) / tex_height;
- ty2 = CLUTTER_INT_TO_FIXED (tex_height - priv->bottom) / tex_height;
-
- col.alpha = clutter_actor_get_paint_opacity (self);
- cogl_color (&col);
-
- ex = width - priv->right;
- if (ex < 0)
- ex = priv->right; /* FIXME ? */
-
- ey = height - priv->bottom;
- if (ey < 0)
- ey = priv->bottom; /* FIXME ? */
-
-#define FX(x) CLUTTER_INT_TO_FIXED(x)
-
- /* top left corner */
- cogl_texture_rectangle (cogl_texture,
- 0,
- 0,
- FX(priv->left), /* FIXME: clip if smaller */
- FX(priv->top),
- 0,
- 0,
- tx1,
- ty1);
-
- /* top middle */
- cogl_texture_rectangle (cogl_texture,
- FX(priv->left),
- FX(priv->top),
- FX(ex),
- 0,
- tx1,
- 0,
- tx2,
- ty1);
-
- /* top right */
- cogl_texture_rectangle (cogl_texture,
- FX(ex),
- 0,
- FX(width),
- FX(priv->top),
- tx2,
- 0,
- CFX_ONE,
- ty1);
-
- /* mid left */
- cogl_texture_rectangle (cogl_texture,
- 0,
- FX(priv->top),
- FX(priv->left),
- FX(ey),
- 0,
- ty1,
- tx1,
- ty2);
-
- /* center */
- cogl_texture_rectangle (cogl_texture,
- FX(priv->left),
- FX(priv->top),
- FX(ex),
- FX(ey),
- tx1,
- ty1,
- tx2,
- ty2);
-
- /* mid right */
- cogl_texture_rectangle (cogl_texture,
- FX(ex),
- FX(priv->top),
- FX(width),
- FX(ey),
- tx2,
- ty1,
- CFX_ONE,
- ty2);
-
- /* bottom left */
- cogl_texture_rectangle (cogl_texture,
- 0,
- FX(ey),
- FX(priv->left),
- FX(height),
- 0,
- ty2,
- tx1,
- CFX_ONE);
-
- /* bottom center */
- cogl_texture_rectangle (cogl_texture,
- FX(priv->left),
- FX(ey),
- FX(ex),
- FX(height),
- tx1,
- ty2,
- tx2,
- CFX_ONE);
-
- /* bottom right */
- cogl_texture_rectangle (cogl_texture,
- FX(ex),
- FX(ey),
- FX(width),
- FX(height),
- tx2,
- ty2,
- CFX_ONE,
- CFX_ONE);
-
-
- cogl_pop_matrix ();
-#undef FX
-}
-
-
-static void
-tidy_texture_frame_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- TidyTextureFrame *ctexture = TIDY_TEXTURE_FRAME (object);
- TidyTextureFramePrivate *priv = ctexture->priv;
-
- switch (prop_id)
- {
- case PROP_LEFT:
- priv->left = g_value_get_int (value);
- break;
- case PROP_TOP:
- priv->top = g_value_get_int (value);
- break;
- case PROP_RIGHT:
- priv->right = g_value_get_int (value);
- break;
- case PROP_BOTTOM:
- priv->bottom = g_value_get_int (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-tidy_texture_frame_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- TidyTextureFrame *ctexture = TIDY_TEXTURE_FRAME (object);
- TidyTextureFramePrivate *priv = ctexture->priv;
- switch (prop_id)
- {
- case PROP_LEFT:
- g_value_set_int (value, priv->left);
- break;
- case PROP_TOP:
- g_value_set_int (value, priv->top);
- break;
- case PROP_RIGHT:
- g_value_set_int (value, priv->right);
- break;
- case PROP_BOTTOM:
- g_value_set_int (value, priv->bottom);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-tidy_texture_frame_class_init (TidyTextureFrameClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
-
- actor_class->paint = tidy_texture_frame_paint;
-
- gobject_class->set_property = tidy_texture_frame_set_property;
- gobject_class->get_property = tidy_texture_frame_get_property;
-
- g_object_class_install_property
- (gobject_class,
- PROP_LEFT,
- g_param_spec_int ("left",
- "left",
- "",
- 0, G_MAXINT,
- 0,
- TIDY_PARAM_READWRITE));
-
- g_object_class_install_property
- (gobject_class,
- PROP_TOP,
- g_param_spec_int ("top",
- "top",
- "",
- 0, G_MAXINT,
- 0,
- TIDY_PARAM_READWRITE));
-
- g_object_class_install_property
- (gobject_class,
- PROP_BOTTOM,
- g_param_spec_int ("bottom",
- "bottom",
- "",
- 0, G_MAXINT,
- 0,
- TIDY_PARAM_READWRITE));
-
- g_object_class_install_property
- (gobject_class,
- PROP_RIGHT,
- g_param_spec_int ("right",
- "right",
- "",
- 0, G_MAXINT,
- 0,
- TIDY_PARAM_READWRITE));
-
- g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate));
-}
-
-static void
-tidy_texture_frame_init (TidyTextureFrame *self)
-{
- TidyTextureFramePrivate *priv;
-
- self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self);
-}
-
-static ClutterActor*
-tidy_texture_frame_new (ClutterTexture *texture,
- gint left,
- gint top,
- gint right,
- gint bottom)
-{
- g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
-
- return g_object_new (TIDY_TYPE_TEXTURE_FRAME,
- "parent-texture", texture,
- "left", left,
- "top", top,
- "right", right,
- "bottom", bottom,
- NULL);
-}
diff --git a/matchbox2/tidy/tidy-texture-frame.c b/matchbox2/tidy/tidy-texture-frame.c
new file mode 100644
index 0000000..7ba4671
--- /dev/null
+++ b/matchbox2/tidy/tidy-texture-frame.c
@@ -0,0 +1,641 @@
+/* tidy-texture-frame.h: Expandible texture actor
+ *
+ * Copyright (C) 2007 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:tidy-texture-frame
+ * @short_description: Stretch a texture to fit the entire allocation
+ *
+ * #TidyTextureFrame
+ *
+ */
+
+#include <cogl/cogl.h>
+
+#include "tidy-texture-frame.h"
+
+#define TIDY_PARAM_READABLE \
+ (G_PARAM_READABLE | \
+ G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
+
+#define TIDY_PARAM_READWRITE \
+ (G_PARAM_READABLE | G_PARAM_WRITABLE | \
+ G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
+
+enum
+{
+ PROP_0,
+
+ PROP_PARENT_TEXTURE,
+
+ PROP_LEFT,
+ PROP_TOP,
+ PROP_RIGHT,
+ PROP_BOTTOM
+};
+
+G_DEFINE_TYPE (TidyTextureFrame, tidy_texture_frame, CLUTTER_TYPE_ACTOR);
+
+#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate))
+
+struct _TidyTextureFramePrivate
+{
+ ClutterTexture *parent_texture;
+
+ gfloat left;
+ gfloat top;
+ gfloat right;
+ gfloat bottom;
+
+ CoglHandle material;
+
+ guint needs_paint : 1;
+};
+
+static void
+tidy_texture_frame_get_preferred_width (ClutterActor *self,
+ gfloat for_height,
+ gfloat *min_width_p,
+ gfloat *natural_width_p)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
+
+ if (G_UNLIKELY (priv->parent_texture == NULL))
+ {
+ if (min_width_p)
+ *min_width_p = 0;
+
+ if (natural_width_p)
+ *natural_width_p = 0;
+ }
+ else
+ {
+ ClutterActorClass *klass;
+
+ /* by directly querying the parent texture's class implementation
+ * we are going around any override mechanism the parent texture
+ * might have in place, and we ask directly for the original
+ * preferred width
+ */
+ klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
+ klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture),
+ for_height,
+ min_width_p,
+ natural_width_p);
+ }
+}
+
+static void
+tidy_texture_frame_get_preferred_height (ClutterActor *self,
+ gfloat for_width,
+ gfloat *min_height_p,
+ gfloat *natural_height_p)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
+
+ if (G_UNLIKELY (priv->parent_texture == NULL))
+ {
+ if (min_height_p)
+ *min_height_p = 0;
+
+ if (natural_height_p)
+ *natural_height_p = 0;
+ }
+ else
+ {
+ ClutterActorClass *klass;
+
+ /* by directly querying the parent texture's class implementation
+ * we are going around any override mechanism the parent texture
+ * might have in place, and we ask directly for the original
+ * preferred height
+ */
+ klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
+ klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture),
+ for_width,
+ min_height_p,
+ natural_height_p);
+ }
+}
+
+static void
+tidy_texture_frame_realize (ClutterActor *self)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
+
+ if (priv->material != COGL_INVALID_HANDLE)
+ return;
+
+ priv->material = cogl_material_new ();
+
+ CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
+}
+
+static void
+tidy_texture_frame_unrealize (ClutterActor *self)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
+
+ if (priv->material == COGL_INVALID_HANDLE)
+ return;
+
+ cogl_handle_unref (priv->material);
+ priv->material = COGL_INVALID_HANDLE;
+
+ CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
+}
+
+static void
+tidy_texture_frame_paint (ClutterActor *self)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
+ CoglHandle cogl_texture = COGL_INVALID_HANDLE;
+ ClutterActorBox box = { 0, };
+ gfloat width, height;
+ gfloat tex_width, tex_height;
+ gfloat ex, ey;
+ gfloat tx1, ty1, tx2, ty2;
+ guint8 opacity;
+
+ /* no need to paint stuff if we don't have a texture */
+ if (G_UNLIKELY (priv->parent_texture == NULL))
+ return;
+
+ if (!priv->needs_paint)
+ return;
+
+ /* parent texture may have been hidden, so need to make sure it gets
+ * realized
+ */
+ if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture))
+ clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture));
+
+ cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture);
+ if (cogl_texture == COGL_INVALID_HANDLE)
+ return;
+
+ tex_width = cogl_texture_get_width (cogl_texture);
+ tex_height = cogl_texture_get_height (cogl_texture);
+
+ clutter_actor_get_allocation_box (self, &box);
+ width = box.x2 - box.x1;
+ height = box.y2 - box.y1;
+
+ tx1 = priv->left / tex_width;
+ tx2 = (tex_width - priv->right) / tex_width;
+ ty1 = priv->top / tex_height;
+ ty2 = (tex_height - priv->bottom) / tex_height;
+
+ ex = width - priv->right;
+ if (ex < 0)
+ ex = priv->right; /* FIXME ? */
+
+ ey = height - priv->bottom;
+ if (ey < 0)
+ ey = priv->bottom; /* FIXME ? */
+
+ opacity = clutter_actor_get_paint_opacity (self);
+
+ g_assert (priv->material != COGL_INVALID_HANDLE);
+
+ /* set the source material using the parent texture's COGL handle */
+ cogl_material_set_color4ub (priv->material, opacity, opacity, opacity, opacity);
+ cogl_material_set_layer (priv->material, 0, cogl_texture);
+ cogl_set_source (priv->material);
+
+ /* top left corner */
+ cogl_rectangle_with_texture_coords (0, 0, priv->left, priv->top,
+ 0.0, 0.0,
+ tx1, ty1);
+
+ /* top middle */
+ cogl_rectangle_with_texture_coords (priv->left, 0, ex, priv->top,
+ tx1, 0.0,
+ tx2, ty1);
+
+ /* top right */
+ cogl_rectangle_with_texture_coords (ex, 0, width, priv->top,
+ tx2, 0.0,
+ 1.0, ty1);
+
+ /* mid left */
+ cogl_rectangle_with_texture_coords (0, priv->top, priv->left, ey,
+ 0.0, ty1,
+ tx1, ty2);
+
+ /* center */
+ cogl_rectangle_with_texture_coords (priv->left, priv->top, ex, ey,
+ tx1, ty1,
+ tx2, ty2);
+
+ /* mid right */
+ cogl_rectangle_with_texture_coords (ex, priv->top, width, ey,
+ tx2, ty1,
+ 1.0, ty2);
+
+ /* bottom left */
+ cogl_rectangle_with_texture_coords (0, ey, priv->left, height,
+ 0.0, ty2,
+ tx1, 1.0);
+
+ /* bottom center */
+ cogl_rectangle_with_texture_coords (priv->left, ey, ex, height,
+ tx1, ty2,
+ tx2, 1.0);
+
+ /* bottom right */
+ cogl_rectangle_with_texture_coords (ex, ey, width, height,
+ tx2, ty2,
+ 1.0, 1.0);
+}
+
+static inline void
+tidy_texture_frame_set_frame_internal (TidyTextureFrame *frame,
+ gfloat left,
+ gfloat top,
+ gfloat right,
+ gfloat bottom)
+{
+ TidyTextureFramePrivate *priv = frame->priv;
+ GObject *gobject = G_OBJECT (frame);
+ gboolean changed = FALSE;
+
+ g_object_freeze_notify (gobject);
+
+ if (priv->top != top)
+ {
+ priv->top = top;
+ g_object_notify (gobject, "top");
+ changed = TRUE;
+ }
+
+ if (priv->right != right)
+ {
+ priv->right = right;
+ g_object_notify (gobject, "right");
+ changed = TRUE;
+ }
+
+ if (priv->bottom != bottom)
+ {
+ priv->bottom = bottom;
+ g_object_notify (gobject, "bottom");
+ changed = TRUE;
+ }
+
+ if (priv->left != left)
+ {
+ priv->left = left;
+ g_object_notify (gobject, "left");
+ changed = TRUE;
+ }
+
+ if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame))
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (frame));
+
+ g_object_thaw_notify (gobject);
+}
+
+static void
+tidy_texture_frame_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TidyTextureFrame *frame = TIDY_TEXTURE_FRAME (gobject);
+ TidyTextureFramePrivate *priv = frame->priv;
+
+ switch (prop_id)
+ {
+ case PROP_PARENT_TEXTURE:
+ tidy_texture_frame_set_parent_texture (frame,
+ g_value_get_object (value));
+ break;
+
+ case PROP_TOP:
+ tidy_texture_frame_set_frame_internal (frame,
+ priv->left,
+ g_value_get_float (value),
+ priv->right,
+ priv->bottom);
+ break;
+
+ case PROP_RIGHT:
+ tidy_texture_frame_set_frame_internal (frame,
+ priv->top,
+ g_value_get_float (value),
+ priv->bottom,
+ priv->left);
+ break;
+
+ case PROP_BOTTOM:
+ tidy_texture_frame_set_frame_internal (frame,
+ priv->top,
+ priv->right,
+ g_value_get_float (value),
+ priv->left);
+ break;
+
+ case PROP_LEFT:
+ tidy_texture_frame_set_frame_internal (frame,
+ priv->top,
+ priv->right,
+ priv->bottom,
+ g_value_get_float (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+tidy_texture_frame_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_PARENT_TEXTURE:
+ g_value_set_object (value, priv->parent_texture);
+ break;
+
+ case PROP_LEFT:
+ g_value_set_float (value, priv->left);
+ break;
+
+ case PROP_TOP:
+ g_value_set_float (value, priv->top);
+ break;
+
+ case PROP_RIGHT:
+ g_value_set_float (value, priv->right);
+ break;
+
+ case PROP_BOTTOM:
+ g_value_set_float (value, priv->bottom);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+tidy_texture_frame_dispose (GObject *gobject)
+{
+ TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
+
+ if (priv->parent_texture)
+ {
+ g_object_unref (priv->parent_texture);
+ priv->parent_texture = NULL;
+ }
+
+ if (priv->material)
+ {
+ cogl_handle_unref (priv->material);
+ priv->material = COGL_INVALID_HANDLE;
+ }
+
+ G_OBJECT_CLASS (tidy_texture_frame_parent_class)->dispose (gobject);
+}
+
+static void
+tidy_texture_frame_class_init (TidyTextureFrameClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate));
+
+ actor_class->get_preferred_width =
+ tidy_texture_frame_get_preferred_width;
+ actor_class->get_preferred_height =
+ tidy_texture_frame_get_preferred_height;
+ actor_class->realize = tidy_texture_frame_realize;
+ actor_class->unrealize = tidy_texture_frame_unrealize;
+ actor_class->paint = tidy_texture_frame_paint;
+
+ gobject_class->set_property = tidy_texture_frame_set_property;
+ gobject_class->get_property = tidy_texture_frame_get_property;
+ gobject_class->dispose = tidy_texture_frame_dispose;
+
+ pspec = g_param_spec_object ("parent-texture",
+ "Parent Texture",
+ "The parent ClutterTexture",
+ CLUTTER_TYPE_TEXTURE,
+ TIDY_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT);
+ g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec);
+
+ pspec = g_param_spec_float ("left",
+ "Left",
+ "Left offset",
+ 0, G_MAXFLOAT,
+ 0,
+ TIDY_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_LEFT, pspec);
+
+ pspec = g_param_spec_float ("top",
+ "Top",
+ "Top offset",
+ 0, G_MAXFLOAT,
+ 0,
+ TIDY_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_TOP, pspec);
+
+ pspec = g_param_spec_float ("bottom",
+ "Bottom",
+ "Bottom offset",
+ 0, G_MAXFLOAT,
+ 0,
+ TIDY_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec);
+
+ pspec = g_param_spec_float ("right",
+ "Right",
+ "Right offset",
+ 0, G_MAXFLOAT,
+ 0,
+ TIDY_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_RIGHT, pspec);
+}
+
+static void
+tidy_texture_frame_init (TidyTextureFrame *self)
+{
+ TidyTextureFramePrivate *priv;
+
+ self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self);
+
+ priv->material = COGL_INVALID_HANDLE;
+}
+
+/**
+ * tidy_texture_frame_new:
+ * @texture: a #ClutterTexture or %NULL
+ * @left: left margin preserving its content
+ * @top: top margin preserving its content
+ * @right: right margin preserving its content
+ * @bottom: bottom margin preserving its content
+ *
+ * A #TidyTextureFrame is a specialized texture that efficiently clones
+ * an area of the given @texture while keeping preserving portions of the
+ * same texture.
+ *
+ * A #TidyTextureFrame can be used to make a rectangular texture fit a
+ * given size without stretching its borders.
+ *
+ * Return value: the newly created #TidyTextureFrame
+ */
+ClutterActor*
+tidy_texture_frame_new (ClutterTexture *texture,
+ gfloat left,
+ gfloat top,
+ gfloat right,
+ gfloat bottom)
+{
+ g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
+
+ return g_object_new (TIDY_TYPE_TEXTURE_FRAME,
+ "parent-texture", texture,
+ "left", left,
+ "top", top,
+ "right", right,
+ "bottom", bottom,
+ NULL);
+}
+
+ClutterTexture *
+tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame)
+{
+ g_return_val_if_fail (TIDY_IS_TEXTURE_FRAME (frame), NULL);
+
+ return frame->priv->parent_texture;
+}
+
+void
+tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
+ ClutterTexture *texture)
+{
+ TidyTextureFramePrivate *priv;
+ gboolean was_visible;
+
+ g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
+ g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture));
+
+ priv = frame->priv;
+
+ was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame);
+
+ if (priv->parent_texture == texture)
+ return;
+
+ if (priv->parent_texture)
+ {
+ g_object_unref (priv->parent_texture);
+ priv->parent_texture = NULL;
+
+ if (was_visible)
+ clutter_actor_hide (CLUTTER_ACTOR (frame));
+ }
+
+ if (texture)
+ {
+ priv->parent_texture = g_object_ref (texture);
+
+ if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture))
+ clutter_actor_show (CLUTTER_ACTOR (frame));
+ }
+
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
+
+ g_object_notify (G_OBJECT (frame), "parent-texture");
+}
+
+void
+tidy_texture_frame_set_frame (TidyTextureFrame *frame,
+ gfloat top,
+ gfloat right,
+ gfloat bottom,
+ gfloat left)
+{
+ g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
+
+ tidy_texture_frame_set_frame_internal (frame, top, right, bottom, left);
+}
+
+void
+tidy_texture_frame_get_frame (TidyTextureFrame *frame,
+ gfloat *top,
+ gfloat *right,
+ gfloat *bottom,
+ gfloat *left)
+{
+ TidyTextureFramePrivate *priv;
+
+ g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
+
+ priv = frame->priv;
+
+ if (top)
+ *top = priv->top;
+
+ if (right)
+ *right = priv->right;
+
+ if (bottom)
+ *bottom = priv->bottom;
+
+ if (left)
+ *left = priv->left;
+}
+
+/**
+ * tidy_texture_frame_set_needs_paint:
+ * @frame: a #TidyTextureframe
+ * @needs_paint: if %FALSE, the paint will be skipped
+ *
+ * Provides a hint to the texture frame that it is totally obscured
+ * and doesn't need to be painted. This would typically be called
+ * by a parent container if it detects the condition prior to
+ * painting its children and then unset afterwards.
+ *
+ * Since it is not supposed to have any effect on display, it does
+ * not queue a repaint.
+ */
+void
+tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
+ gboolean needs_paint)
+{
+ TidyTextureFramePrivate *priv;
+
+ g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
+
+ priv = frame->priv;
+
+ priv->needs_paint = needs_paint;
+}
diff --git a/matchbox2/tidy/tidy-texture-frame.h b/matchbox2/tidy/tidy-texture-frame.h
new file mode 100644
index 0000000..71dd40c
--- /dev/null
+++ b/matchbox2/tidy/tidy-texture-frame.h
@@ -0,0 +1,84 @@
+/* tidy-texture-frame.h: Expandible texture actor
+ *
+ * Copyright (C) 2007, 2008 OpenedHand Ltd
+ * Copyright (C) 2009 Intel Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _HAVE_TIDY_TEXTURE_FRAME_H
+#define _HAVE_TIDY_TEXTURE_FRAME_H
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ())
+#define TIDY_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame))
+#define TIDY_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
+#define TIDY_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIDY_TYPE_TEXTURE_FRAME))
+#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIDY_TYPE_TEXTURE_FRAME))
+#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
+
+typedef struct _TidyTextureFrame TidyTextureFrame;
+typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate;
+typedef struct _TidyTextureFrameClass TidyTextureFrameClass;
+
+struct _TidyTextureFrame
+{
+ /*< private >*/
+ ClutterActor parent_instance;
+
+ TidyTextureFramePrivate *priv;
+};
+
+struct _TidyTextureFrameClass
+{
+ ClutterActorClass parent_class;
+
+ /* padding for future expansion */
+ void (*_clutter_box_1) (void);
+ void (*_clutter_box_2) (void);
+ void (*_clutter_box_3) (void);
+ void (*_clutter_box_4) (void);
+};
+
+GType tidy_texture_frame_get_type (void) G_GNUC_CONST;
+ClutterActor * tidy_texture_frame_new (ClutterTexture *texture,
+ gfloat top,
+ gfloat right,
+ gfloat bottom,
+ gfloat left);
+void tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
+ ClutterTexture *texture);
+ClutterTexture *tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame);
+void tidy_texture_frame_set_frame (TidyTextureFrame *frame,
+ gfloat top,
+ gfloat right,
+ gfloat bottom,
+ gfloat left);
+void tidy_texture_frame_get_frame (TidyTextureFrame *frame,
+ gfloat *top,
+ gfloat *right,
+ gfloat *bottom,
+ gfloat *left);
+
+void tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
+ gboolean needs_paint);
+
+G_END_DECLS
+
+#endif /* _HAVE_TIDY_TEXTURE_FRAME_H */