diff options
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | matchbox2/Makefile.am | 1 | ||||
-rw-r--r-- | matchbox2/mb-wm-comp-mgr-clutter.c | 411 | ||||
-rw-r--r-- | matchbox2/tidy/tidy-texture-frame.c | 641 | ||||
-rw-r--r-- | matchbox2/tidy/tidy-texture-frame.h | 84 |
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 */ |