Compare commits
	
		
			15 Commits
		
	
	
		
			gbsneto/cl
			...
			configurab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0a4cfde4e2 | ||
| 
						 | 
					c853d197e3 | ||
| 
						 | 
					bf7ae3e4d3 | ||
| 
						 | 
					2b21f1d48c | ||
| 
						 | 
					4c91e05b86 | ||
| 
						 | 
					bc91c328f3 | ||
| 
						 | 
					5bbbac65d6 | ||
| 
						 | 
					a0a0fc14d7 | ||
| 
						 | 
					cc9efe1289 | ||
| 
						 | 
					8825ded1ca | ||
| 
						 | 
					b823ef0007 | ||
| 
						 | 
					a846434bcf | ||
| 
						 | 
					825fc2c0c8 | ||
| 
						 | 
					4fbe547f16 | ||
| 
						 | 
					fc2ba0afbe | 
@@ -28,6 +28,8 @@ mutter_SOURCES= 				\
 | 
			
		||||
	compositor/meta-plugin.c		\
 | 
			
		||||
	compositor/meta-plugin-manager.c	\
 | 
			
		||||
	compositor/meta-plugin-manager.h	\
 | 
			
		||||
	compositor/meta-shadow-factory.c	\
 | 
			
		||||
	compositor/meta-shadow-factory-private.h	\
 | 
			
		||||
	compositor/meta-shaped-texture.c	\
 | 
			
		||||
	compositor/meta-shaped-texture.h	\
 | 
			
		||||
	compositor/meta-texture-tower.c		\
 | 
			
		||||
@@ -36,12 +38,13 @@ mutter_SOURCES= 				\
 | 
			
		||||
	compositor/meta-window-actor-private.h	\
 | 
			
		||||
	compositor/meta-window-group.c		\
 | 
			
		||||
	compositor/meta-window-group.h		\
 | 
			
		||||
	compositor/shadow.c			\
 | 
			
		||||
	compositor/shadow.h			\
 | 
			
		||||
	compositor/tidy/tidy-texture-frame.c	\
 | 
			
		||||
	compositor/tidy/tidy-texture-frame.h	\
 | 
			
		||||
	compositor/meta-window-shape.c		\
 | 
			
		||||
	compositor/meta-window-shape.h		\
 | 
			
		||||
	compositor/region-utils.c		\
 | 
			
		||||
	compositor/region-utils.h		\
 | 
			
		||||
	include/compositor.h			\
 | 
			
		||||
	include/meta-plugin.h			\
 | 
			
		||||
	include/meta-shadow-factory.h		\
 | 
			
		||||
	include/meta-window-actor.h		\
 | 
			
		||||
	include/compositor-mutter.h 		\
 | 
			
		||||
	core/constraints.c			\
 | 
			
		||||
@@ -167,6 +170,7 @@ libmutterinclude_base_headers =		\
 | 
			
		||||
	include/group.h				\
 | 
			
		||||
	include/keybindings.h			\
 | 
			
		||||
	include/meta-plugin.h			\
 | 
			
		||||
	include/meta-shadow-factory.h		\
 | 
			
		||||
	include/meta-window-actor.h
 | 
			
		||||
 | 
			
		||||
# Excluded from scanning for introspection but installed
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
#include "compositor-mutter.h"
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
#include "prefs.h"
 | 
			
		||||
#include "meta-shadow-factory.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-window-group.h"
 | 
			
		||||
#include "../core/window-private.h" /* to check window->hidden */
 | 
			
		||||
@@ -1017,6 +1018,26 @@ meta_repaint_func (gpointer data)
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_shadow_factory_changed (MetaShadowFactory *factory,
 | 
			
		||||
                           MetaCompositor    *compositor)
 | 
			
		||||
{
 | 
			
		||||
  GSList *screens = meta_display_get_screens (compositor->display);
 | 
			
		||||
  GList *l;
 | 
			
		||||
  GSList *sl;
 | 
			
		||||
 | 
			
		||||
  for (sl = screens; sl; sl = sl->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaScreen *screen = sl->data;
 | 
			
		||||
      MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
      if (!info)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      for (l = info->windows; l; l = l->next)
 | 
			
		||||
        meta_window_actor_invalidate_shadow (l->data);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_compositor_new: (skip)
 | 
			
		||||
 *
 | 
			
		||||
@@ -1047,6 +1068,11 @@ meta_compositor_new (MetaDisplay *display)
 | 
			
		||||
  XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
 | 
			
		||||
                False, atoms);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (meta_shadow_factory_get_default (),
 | 
			
		||||
                    "changed",
 | 
			
		||||
                    G_CALLBACK (on_shadow_factory_changed),
 | 
			
		||||
                    compositor);
 | 
			
		||||
 | 
			
		||||
  compositor->atom_x_root_pixmap = atoms[0];
 | 
			
		||||
  compositor->atom_x_set_root = atoms[1];
 | 
			
		||||
  compositor->atom_net_wm_window_opacity = atoms[2];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								src/compositor/meta-shadow-factory-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/compositor/meta-shadow-factory-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaShadowFactory:
 | 
			
		||||
 *
 | 
			
		||||
 * Create and cache shadow textures for arbitrary window shapes
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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_SHADOW_FACTORY_PRIVATE_H__
 | 
			
		||||
#define __META_SHADOW_FACTORY_PRIVATE_H__
 | 
			
		||||
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include "meta-window-shape.h"
 | 
			
		||||
#include "meta-shadow-factory.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaShadow:
 | 
			
		||||
 * #MetaShadow holds a shadow texture along with information about how to
 | 
			
		||||
 * apply that texture to draw a window texture. (E.g., it knows how big the
 | 
			
		||||
 * unscaled borders are on each side of the shadow texture.)
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaShadow MetaShadow;
 | 
			
		||||
 | 
			
		||||
MetaShadow *meta_shadow_ref         (MetaShadow            *shadow);
 | 
			
		||||
void        meta_shadow_unref       (MetaShadow            *shadow);
 | 
			
		||||
CoglHandle  meta_shadow_get_texture (MetaShadow            *shadow);
 | 
			
		||||
void        meta_shadow_paint       (MetaShadow            *shadow,
 | 
			
		||||
                                     int                    window_x,
 | 
			
		||||
                                     int                    window_y,
 | 
			
		||||
                                     int                    window_width,
 | 
			
		||||
                                     int                    window_height,
 | 
			
		||||
                                     guint8                 opacity,
 | 
			
		||||
                                     cairo_region_t        *clip);
 | 
			
		||||
void        meta_shadow_get_bounds  (MetaShadow            *shadow,
 | 
			
		||||
                                     int                    window_x,
 | 
			
		||||
                                     int                    window_y,
 | 
			
		||||
                                     int                    window_width,
 | 
			
		||||
                                     int                    window_height,
 | 
			
		||||
                                     cairo_rectangle_int_t *bounds);
 | 
			
		||||
 | 
			
		||||
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
 | 
			
		||||
                                            MetaWindowShape   *shape,
 | 
			
		||||
                                            int                width,
 | 
			
		||||
                                            int                height,
 | 
			
		||||
                                            const char        *class_name,
 | 
			
		||||
                                            gboolean           focused);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */
 | 
			
		||||
							
								
								
									
										1032
									
								
								src/compositor/meta-shadow-factory.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1032
									
								
								src/compositor/meta-shadow-factory.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -28,6 +28,8 @@ void meta_window_actor_process_damage (MetaWindowActor    *self,
 | 
			
		||||
                                       XDamageNotifyEvent *event);
 | 
			
		||||
void meta_window_actor_pre_paint      (MetaWindowActor    *self);
 | 
			
		||||
 | 
			
		||||
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_actor_effect_in_progress  (MetaWindowActor *self);
 | 
			
		||||
void     meta_window_actor_sync_actor_position (MetaWindowActor *self);
 | 
			
		||||
void     meta_window_actor_sync_visibility     (MetaWindowActor *self);
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@
 | 
			
		||||
#include <X11/extensions/Xrender.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
#include <gdk/gdk.h> /* for gdk_rectangle_union() */
 | 
			
		||||
 | 
			
		||||
#include "display.h"
 | 
			
		||||
#include "errors.h"
 | 
			
		||||
@@ -17,10 +18,9 @@
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-shadow-factory-private.h"
 | 
			
		||||
#include "meta-shaped-texture.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "shadow.h"
 | 
			
		||||
#include "tidy/tidy-texture-frame.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowActorPrivate
 | 
			
		||||
{
 | 
			
		||||
@@ -31,12 +31,27 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
  MetaScreen       *screen;
 | 
			
		||||
 | 
			
		||||
  ClutterActor     *actor;
 | 
			
		||||
  ClutterActor     *shadow;
 | 
			
		||||
 | 
			
		||||
  /* MetaShadowFactory only caches shadows that are actually in use;
 | 
			
		||||
   * to avoid unnecessary recomputation we do two things: 1) we store
 | 
			
		||||
   * both a focused and unfocused shadow for the window. If the window
 | 
			
		||||
   * doesn't have different focused and unfocused shadow parameters,
 | 
			
		||||
   * these will be the same. 2) when the shadow potentially changes we
 | 
			
		||||
   * don't immediately unreference the old shadow, we just flag it as
 | 
			
		||||
   * dirty and recompute it when we next need it (recompute_focused_shadow,
 | 
			
		||||
   * recompute_unfocused_shadow.)  Because of the our extraction of
 | 
			
		||||
   * size-invariant window shape, we'll often find that the new shadow
 | 
			
		||||
   * is the same as the old shadow.
 | 
			
		||||
   */
 | 
			
		||||
  MetaShadow       *focused_shadow;
 | 
			
		||||
  MetaShadow       *unfocused_shadow;
 | 
			
		||||
 | 
			
		||||
  Pixmap            back_pixmap;
 | 
			
		||||
 | 
			
		||||
  Damage            damage;
 | 
			
		||||
 | 
			
		||||
  guint8            opacity;
 | 
			
		||||
  guint8            shadow_opacity;
 | 
			
		||||
 | 
			
		||||
  gchar *           desc;
 | 
			
		||||
 | 
			
		||||
@@ -45,9 +60,16 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
  /* A rectangular region with the unshaped extends of the window
 | 
			
		||||
   * texture */
 | 
			
		||||
  cairo_region_t   *bounding_region;
 | 
			
		||||
  /* The region we should clip to when painting the shadow */
 | 
			
		||||
  cairo_region_t   *shadow_clip;
 | 
			
		||||
 | 
			
		||||
  /* Extracted size-invariant shape used for shadows */
 | 
			
		||||
  MetaWindowShape  *shadow_shape;
 | 
			
		||||
 | 
			
		||||
  gint              freeze_count;
 | 
			
		||||
 | 
			
		||||
  char *            shadow_class;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * These need to be counters rather than flags, since more plugins
 | 
			
		||||
   * can implement same effect; the practicality of stacking effects
 | 
			
		||||
@@ -70,7 +92,9 @@ struct _MetaWindowActorPrivate
 | 
			
		||||
  guint		    received_damage        : 1;
 | 
			
		||||
 | 
			
		||||
  guint		    needs_pixmap           : 1;
 | 
			
		||||
  guint		    needs_reshape          : 1;
 | 
			
		||||
  guint             needs_reshape          : 1;
 | 
			
		||||
  guint             recompute_focused_shadow   : 1;
 | 
			
		||||
  guint             recompute_unfocused_shadow : 1;
 | 
			
		||||
  guint		    size_changed           : 1;
 | 
			
		||||
 | 
			
		||||
  guint		    needs_destroy	   : 1;
 | 
			
		||||
@@ -87,8 +111,13 @@ enum
 | 
			
		||||
  PROP_X_WINDOW,
 | 
			
		||||
  PROP_X_WINDOW_ATTRIBUTES,
 | 
			
		||||
  PROP_NO_SHADOW,
 | 
			
		||||
  PROP_SHADOW_CLASS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_SHADOW_RADIUS 12
 | 
			
		||||
#define DEFAULT_SHADOW_X_OFFSET 0
 | 
			
		||||
#define DEFAULT_SHADOW_Y_OFFSET 8
 | 
			
		||||
 | 
			
		||||
static void meta_window_actor_dispose    (GObject *object);
 | 
			
		||||
static void meta_window_actor_finalize   (GObject *object);
 | 
			
		||||
static void meta_window_actor_constructed (GObject *object);
 | 
			
		||||
@@ -101,11 +130,18 @@ static void meta_window_actor_get_property (GObject      *object,
 | 
			
		||||
                                            GValue       *value,
 | 
			
		||||
                                            GParamSpec   *pspec);
 | 
			
		||||
 | 
			
		||||
static void meta_window_actor_paint (ClutterActor *actor);
 | 
			
		||||
#if CLUTTER_CHECK_VERSION(1, 5, 2)
 | 
			
		||||
static gboolean meta_window_actor_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
                                                    ClutterPaintVolume *volume);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void     meta_window_actor_detach     (MetaWindowActor *self);
 | 
			
		||||
static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
 | 
			
		||||
 | 
			
		||||
static void meta_window_actor_clear_shape_region    (MetaWindowActor *self);
 | 
			
		||||
static void meta_window_actor_clear_bounding_region (MetaWindowActor *self);
 | 
			
		||||
static void meta_window_actor_clear_shadow_clip     (MetaWindowActor *self);
 | 
			
		||||
 | 
			
		||||
static gboolean is_shaped                (MetaDisplay  *display,
 | 
			
		||||
                                          Window        xwindow);
 | 
			
		||||
@@ -161,6 +197,7 @@ static void
 | 
			
		||||
meta_window_actor_class_init (MetaWindowActorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
 | 
			
		||||
  GParamSpec   *pspec;
 | 
			
		||||
 | 
			
		||||
  g_type_class_add_private (klass, sizeof (MetaWindowActorPrivate));
 | 
			
		||||
@@ -171,6 +208,11 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
 | 
			
		||||
  object_class->get_property = meta_window_actor_get_property;
 | 
			
		||||
  object_class->constructed  = meta_window_actor_constructed;
 | 
			
		||||
 | 
			
		||||
  actor_class->paint = meta_window_actor_paint;
 | 
			
		||||
#if CLUTTER_CHECK_VERSION(1, 5, 2)
 | 
			
		||||
  actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_object ("meta-window",
 | 
			
		||||
                               "MetaWindow",
 | 
			
		||||
                               "The displayed MetaWindow",
 | 
			
		||||
@@ -216,11 +258,21 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
 | 
			
		||||
                                "No shadow",
 | 
			
		||||
                                "Do not add shaddow to this window",
 | 
			
		||||
                                FALSE,
 | 
			
		||||
                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
 | 
			
		||||
                                G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_NO_SHADOW,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_string ("shadow-class",
 | 
			
		||||
                               "Name of the shadow class for this window.",
 | 
			
		||||
                               "NULL means to use the default shadow class for this window type",
 | 
			
		||||
                               NULL,
 | 
			
		||||
                               G_PARAM_READWRITE);
 | 
			
		||||
 | 
			
		||||
  g_object_class_install_property (object_class,
 | 
			
		||||
                                   PROP_SHADOW_CLASS,
 | 
			
		||||
                                   pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -232,6 +284,7 @@ meta_window_actor_init (MetaWindowActor *self)
 | 
			
		||||
						   META_TYPE_WINDOW_ACTOR,
 | 
			
		||||
						   MetaWindowActorPrivate);
 | 
			
		||||
  priv->opacity = 0xff;
 | 
			
		||||
  priv->shadow_class = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -291,18 +344,6 @@ window_decorated_notify (MetaWindow *mw,
 | 
			
		||||
 | 
			
		||||
  g_object_set (self, "x-window-attributes", &attrs, NULL);
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterActor *p = clutter_actor_get_parent (priv->shadow);
 | 
			
		||||
 | 
			
		||||
      if (CLUTTER_IS_CONTAINER (p))
 | 
			
		||||
        clutter_container_remove_actor (CLUTTER_CONTAINER (p), priv->shadow);
 | 
			
		||||
      else
 | 
			
		||||
        clutter_actor_unparent (priv->shadow);
 | 
			
		||||
 | 
			
		||||
      priv->shadow = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Recreate the contents.
 | 
			
		||||
   */
 | 
			
		||||
@@ -344,13 +385,6 @@ meta_window_actor_constructed (GObject *object)
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_update_opacity (self);
 | 
			
		||||
 | 
			
		||||
  if (meta_window_actor_has_shadow (self))
 | 
			
		||||
    {
 | 
			
		||||
      priv->shadow = meta_create_shadow_frame (compositor);
 | 
			
		||||
 | 
			
		||||
      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!priv->actor)
 | 
			
		||||
    {
 | 
			
		||||
      priv->actor = meta_shaped_texture_new ();
 | 
			
		||||
@@ -406,6 +440,31 @@ meta_window_actor_dispose (GObject *object)
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_clear_shape_region (self);
 | 
			
		||||
  meta_window_actor_clear_bounding_region (self);
 | 
			
		||||
  meta_window_actor_clear_shadow_clip (self);
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow_class != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (priv->shadow_class);
 | 
			
		||||
      priv->shadow_class = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->focused_shadow != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_shadow_unref (priv->focused_shadow);
 | 
			
		||||
      priv->focused_shadow = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->unfocused_shadow != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_shadow_unref (priv->unfocused_shadow);
 | 
			
		||||
      priv->unfocused_shadow = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow_shape != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_window_shape_unref (priv->shadow_shape);
 | 
			
		||||
      priv->shadow_shape = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (priv->damage != None)
 | 
			
		||||
    {
 | 
			
		||||
@@ -463,36 +522,27 @@ meta_window_actor_set_property (GObject      *object,
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_NO_SHADOW:
 | 
			
		||||
      {
 | 
			
		||||
        gboolean oldv = priv->no_shadow ? TRUE : FALSE;
 | 
			
		||||
        gboolean newv = g_value_get_boolean (value);
 | 
			
		||||
 | 
			
		||||
        if (oldv == newv)
 | 
			
		||||
        if (newv == priv->no_shadow)
 | 
			
		||||
          return;
 | 
			
		||||
 | 
			
		||||
        priv->no_shadow = newv;
 | 
			
		||||
 | 
			
		||||
        if (newv && priv->shadow)
 | 
			
		||||
          {
 | 
			
		||||
            clutter_container_remove_actor (CLUTTER_CONTAINER (object),
 | 
			
		||||
                                            priv->shadow);
 | 
			
		||||
            priv->shadow = NULL;
 | 
			
		||||
          }
 | 
			
		||||
        else if (!newv && !priv->shadow && meta_window_actor_has_shadow (self))
 | 
			
		||||
          {
 | 
			
		||||
            gfloat       w, h;
 | 
			
		||||
            MetaDisplay *display = meta_screen_get_display (priv->screen);
 | 
			
		||||
            MetaCompositor *compositor;
 | 
			
		||||
        meta_window_actor_invalidate_shadow (self);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_SHADOW_CLASS:
 | 
			
		||||
      {
 | 
			
		||||
        const char *newv = g_value_get_string (value);
 | 
			
		||||
 | 
			
		||||
            compositor = meta_display_get_compositor (display);
 | 
			
		||||
        if (g_strcmp0 (newv, priv->shadow_class) == 0)
 | 
			
		||||
          return;
 | 
			
		||||
 | 
			
		||||
            clutter_actor_get_size (CLUTTER_ACTOR (self), &w, &h);
 | 
			
		||||
        g_free (priv->shadow_class);
 | 
			
		||||
        priv->shadow_class = g_strdup (newv);
 | 
			
		||||
 | 
			
		||||
            priv->shadow = meta_create_shadow_frame (compositor);
 | 
			
		||||
 | 
			
		||||
            clutter_actor_set_size (priv->shadow, w, h);
 | 
			
		||||
 | 
			
		||||
            clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
 | 
			
		||||
          }
 | 
			
		||||
        meta_window_actor_invalidate_shadow (self);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
@@ -526,12 +576,164 @@ meta_window_actor_get_property (GObject      *object,
 | 
			
		||||
    case PROP_NO_SHADOW:
 | 
			
		||||
      g_value_set_boolean (value, priv->no_shadow);
 | 
			
		||||
      break;
 | 
			
		||||
    case PROP_SHADOW_CLASS:
 | 
			
		||||
      g_value_set_string (value, priv->shadow_class);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
meta_window_actor_get_shadow_class (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow_class != NULL)
 | 
			
		||||
    return priv->shadow_class;
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindowType window_type = meta_window_get_window_type (priv->window);
 | 
			
		||||
 | 
			
		||||
      switch (window_type)
 | 
			
		||||
        {
 | 
			
		||||
        case META_WINDOW_DROPDOWN_MENU:
 | 
			
		||||
          return "dropdown-menu";
 | 
			
		||||
        case META_WINDOW_POPUP_MENU:
 | 
			
		||||
          return "popup-menu";
 | 
			
		||||
        default:
 | 
			
		||||
          {
 | 
			
		||||
            MetaFrameType frame_type = meta_window_get_frame_type (priv->window);
 | 
			
		||||
            return meta_frame_type_to_string (frame_type);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_get_shadow_params (MetaWindowActor  *self,
 | 
			
		||||
                                     gboolean          appears_focused,
 | 
			
		||||
                                     MetaShadowParams *params)
 | 
			
		||||
{
 | 
			
		||||
  const char *shadow_class = meta_window_actor_get_shadow_class (self);
 | 
			
		||||
 | 
			
		||||
  meta_shadow_factory_get_params (meta_shadow_factory_get_default (),
 | 
			
		||||
                                  shadow_class, appears_focused,
 | 
			
		||||
                                  params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_get_shape_bounds (MetaWindowActor       *self,
 | 
			
		||||
                                    cairo_rectangle_int_t *bounds)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  /* We need to be defensive here because there are corner cases
 | 
			
		||||
   * where getting the shape fails on a window being destroyed
 | 
			
		||||
   * and similar.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->shaped && priv->shape_region)
 | 
			
		||||
    cairo_region_get_extents (priv->shape_region, bounds);
 | 
			
		||||
  else if (priv->bounding_region)
 | 
			
		||||
    cairo_region_get_extents (priv->bounding_region, bounds);
 | 
			
		||||
  else
 | 
			
		||||
    bounds->x = bounds->y = bounds->width = bounds->height = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_get_shadow_bounds (MetaWindowActor       *self,
 | 
			
		||||
                                     gboolean               appears_focused,
 | 
			
		||||
                                     cairo_rectangle_int_t *bounds)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
 | 
			
		||||
  cairo_rectangle_int_t shape_bounds;
 | 
			
		||||
  MetaShadowParams params;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_get_shape_bounds (self, &shape_bounds);
 | 
			
		||||
  meta_window_actor_get_shadow_params (self, appears_focused, ¶ms);
 | 
			
		||||
 | 
			
		||||
  meta_shadow_get_bounds (shadow,
 | 
			
		||||
                          params.x_offset + shape_bounds.x,
 | 
			
		||||
                          params.y_offset + shape_bounds.y,
 | 
			
		||||
                          shape_bounds.width,
 | 
			
		||||
                          shape_bounds.height,
 | 
			
		||||
                          bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *self = META_WINDOW_ACTOR (actor);
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  gboolean appears_focused = meta_window_appears_focused (priv->window);
 | 
			
		||||
  MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
 | 
			
		||||
 | 
			
		||||
  if (shadow != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      MetaShadowParams params;
 | 
			
		||||
      cairo_rectangle_int_t shape_bounds;
 | 
			
		||||
 | 
			
		||||
      meta_window_actor_get_shape_bounds (self, &shape_bounds);
 | 
			
		||||
      meta_window_actor_get_shadow_params (self, appears_focused, ¶ms);
 | 
			
		||||
 | 
			
		||||
      meta_shadow_paint (shadow,
 | 
			
		||||
                         params.x_offset + shape_bounds.x,
 | 
			
		||||
                         params.y_offset + shape_bounds.y,
 | 
			
		||||
                         shape_bounds.width,
 | 
			
		||||
                         shape_bounds.height,
 | 
			
		||||
                         (clutter_actor_get_paint_opacity (actor) * params.opacity) / 255,
 | 
			
		||||
                         priv->shadow_clip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->paint (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if CLUTTER_CHECK_VERSION(1, 5, 2)
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_window_actor_get_paint_volume (ClutterActor       *actor,
 | 
			
		||||
                                    ClutterPaintVolume *volume)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *self = META_WINDOW_ACTOR (actor);
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  cairo_rectangle_int_t bounds;
 | 
			
		||||
  gboolean appears_focused = meta_window_appears_focused (priv->window);
 | 
			
		||||
  ClutterVertex origin;
 | 
			
		||||
 | 
			
		||||
  /* The paint volume is computed before paint functions are called
 | 
			
		||||
   * so our bounds might not be updated yet. Force an update. */
 | 
			
		||||
  meta_window_actor_pre_paint (self);
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_get_shape_bounds (self, &bounds);
 | 
			
		||||
 | 
			
		||||
  if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t shadow_bounds;
 | 
			
		||||
 | 
			
		||||
      /* We could compute an full clip region as we do for the window
 | 
			
		||||
       * texture, but the shadow is relatively cheap to draw, and
 | 
			
		||||
       * a little more complex to clip, so we just catch the case where
 | 
			
		||||
       * the shadow is completely obscured and doesn't need to be drawn
 | 
			
		||||
       * at all.
 | 
			
		||||
       */
 | 
			
		||||
 | 
			
		||||
      meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
 | 
			
		||||
      gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  origin.x = bounds.x;
 | 
			
		||||
  origin.y = bounds.y;
 | 
			
		||||
  origin.z = 0.0f;
 | 
			
		||||
  clutter_paint_volume_set_origin (volume, &origin);
 | 
			
		||||
 | 
			
		||||
  clutter_paint_volume_set_width (volume, bounds.width);
 | 
			
		||||
  clutter_paint_volume_set_height (volume, bounds.height);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
#endif /* CLUTTER_CHECK_VERSION */
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_shaped (MetaDisplay *display, Window xwindow)
 | 
			
		||||
{
 | 
			
		||||
@@ -560,10 +762,16 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
  if (priv->no_shadow)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  /* Leaving out shadows for maximized and fullscreen windows is an effeciency
 | 
			
		||||
   * win and also prevents the unsightly effect of the shadow of maximized
 | 
			
		||||
   * window appearing on an adjacent window */
 | 
			
		||||
  if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
 | 
			
		||||
      meta_window_is_fullscreen (priv->window))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Always put a shadow around windows with a frame - This should override
 | 
			
		||||
   * the restriction about not putting a shadow around shaped windows
 | 
			
		||||
   * as the frame might be the reason the window is shaped
 | 
			
		||||
   * the restriction about not putting a shadow around ARGB windows.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->window)
 | 
			
		||||
    {
 | 
			
		||||
@@ -576,7 +784,8 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Do not add shadows to ARGB windows (since they are probably transparent)
 | 
			
		||||
   * Do not add shadows to ARGB windows; eventually we should generate a
 | 
			
		||||
   * shadow from the input shape for such windows.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->argb32 || priv->opacity != 0xff)
 | 
			
		||||
    {
 | 
			
		||||
@@ -585,19 +794,8 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Never put a shadow around shaped windows
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->shaped)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("Window 0x%x has no shadow as it is shaped\n",
 | 
			
		||||
		    (guint)priv->xwindow);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Add shadows to override redirect windows (e.g., Gtk menus).
 | 
			
		||||
   * This must have lower priority than window shape test.
 | 
			
		||||
   */
 | 
			
		||||
  if (priv->attrs.override_redirect)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1358,6 +1556,18 @@ meta_window_actor_clear_bounding_region (MetaWindowActor *self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_clear_shadow_clip (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow_clip)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_region_destroy (priv->shadow_clip);
 | 
			
		||||
      priv->shadow_clip = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_actor_update_bounding_region (MetaWindowActor *self,
 | 
			
		||||
                                          int              width,
 | 
			
		||||
@@ -1366,9 +1576,26 @@ meta_window_actor_update_bounding_region (MetaWindowActor *self,
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  cairo_rectangle_int_t bounding_rectangle = { 0, 0, width, height };
 | 
			
		||||
 | 
			
		||||
  if (priv->bounding_region != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t old_bounding_rectangle;
 | 
			
		||||
      cairo_region_get_extents (priv->bounding_region, &old_bounding_rectangle);
 | 
			
		||||
 | 
			
		||||
      if (old_bounding_rectangle.width == width && old_bounding_rectangle.height == height)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_clear_bounding_region (self);
 | 
			
		||||
 | 
			
		||||
  priv->bounding_region = cairo_region_create_rectangle (&bounding_rectangle);
 | 
			
		||||
 | 
			
		||||
  /* When we're shaped, we use the shape region to generate the shadow; the shape
 | 
			
		||||
   * region only changes when we get ShapeNotify event; but for unshaped windows
 | 
			
		||||
   * we generate the shadow from the bounding region, so we need to recompute
 | 
			
		||||
   * the shadow when the size changes.
 | 
			
		||||
   */
 | 
			
		||||
  if (!priv->shaped)
 | 
			
		||||
    meta_window_actor_invalidate_shadow (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1497,30 +1724,12 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
 | 
			
		||||
                                              cairo_region_t  *beneath_region)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  gboolean appears_focused = meta_window_appears_focused (priv->window);
 | 
			
		||||
 | 
			
		||||
  if (priv->shadow)
 | 
			
		||||
  if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t shadow_rect;
 | 
			
		||||
      ClutterActorBox box;
 | 
			
		||||
      cairo_region_overlap_t overlap;
 | 
			
		||||
 | 
			
		||||
      /* We could compute an full clip region as we do for the window
 | 
			
		||||
       * texture, but the shadow is relatively cheap to draw, and
 | 
			
		||||
       * a little more complex to clip, so we just catch the case where
 | 
			
		||||
       * the shadow is completely obscured and doesn't need to be drawn
 | 
			
		||||
       * at all.
 | 
			
		||||
       */
 | 
			
		||||
      clutter_actor_get_allocation_box (priv->shadow, &box);
 | 
			
		||||
 | 
			
		||||
      shadow_rect.x = roundf (box.x1);
 | 
			
		||||
      shadow_rect.y = roundf (box.y1);
 | 
			
		||||
      shadow_rect.width = roundf (box.x2 - box.x1);
 | 
			
		||||
      shadow_rect.height = roundf (box.y2 - box.y1);
 | 
			
		||||
 | 
			
		||||
      overlap = cairo_region_contains_rectangle (beneath_region, &shadow_rect);
 | 
			
		||||
 | 
			
		||||
      tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow),
 | 
			
		||||
                                          overlap != CAIRO_REGION_OVERLAP_OUT);
 | 
			
		||||
      meta_window_actor_clear_shadow_clip (self);
 | 
			
		||||
      priv->shadow_clip = cairo_region_copy (beneath_region);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1538,8 +1747,7 @@ meta_window_actor_reset_visible_regions (MetaWindowActor *self)
 | 
			
		||||
 | 
			
		||||
  meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
 | 
			
		||||
                                       NULL);
 | 
			
		||||
  if (priv->shadow)
 | 
			
		||||
    tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow), TRUE);
 | 
			
		||||
  meta_window_actor_clear_shadow_clip (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1622,9 +1830,6 @@ check_needs_pixmap (MetaWindowActor *self)
 | 
			
		||||
                    "pixmap-height", &pxm_height,
 | 
			
		||||
                    NULL);
 | 
			
		||||
 | 
			
		||||
      if (priv->shadow)
 | 
			
		||||
        clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
 | 
			
		||||
 | 
			
		||||
      meta_window_actor_update_bounding_region (self, pxm_width, pxm_height);
 | 
			
		||||
 | 
			
		||||
      full = TRUE;
 | 
			
		||||
@@ -1635,6 +1840,77 @@ check_needs_pixmap (MetaWindowActor *self)
 | 
			
		||||
  priv->needs_pixmap = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_needs_shadow (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
  MetaShadow *old_shadow = NULL;
 | 
			
		||||
  MetaShadow **shadow_location;
 | 
			
		||||
  gboolean recompute_shadow;
 | 
			
		||||
  gboolean should_have_shadow;
 | 
			
		||||
  gboolean appears_focused;
 | 
			
		||||
 | 
			
		||||
  if (!priv->mapped)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
 | 
			
		||||
   * and avoids the need to explicitly handle window type changes, which
 | 
			
		||||
   * we would do if tried to keep track of when we might be adding or removing
 | 
			
		||||
   * a shadow more explicitly. We only keep track of changes to the *shape* of
 | 
			
		||||
   * the shadow with priv->recompute_shadow.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  should_have_shadow = meta_window_actor_has_shadow (self);
 | 
			
		||||
  appears_focused = meta_window_appears_focused (priv->window);
 | 
			
		||||
 | 
			
		||||
  if (appears_focused)
 | 
			
		||||
    {
 | 
			
		||||
      recompute_shadow = priv->recompute_focused_shadow;
 | 
			
		||||
      priv->recompute_focused_shadow = FALSE;
 | 
			
		||||
      shadow_location = &priv->focused_shadow;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      recompute_shadow = priv->recompute_unfocused_shadow;
 | 
			
		||||
      priv->recompute_unfocused_shadow = FALSE;
 | 
			
		||||
      shadow_location = &priv->unfocused_shadow;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!should_have_shadow || recompute_shadow)
 | 
			
		||||
    {
 | 
			
		||||
      if (*shadow_location != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          old_shadow = *shadow_location;
 | 
			
		||||
          *shadow_location = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (*shadow_location == NULL && should_have_shadow)
 | 
			
		||||
    {
 | 
			
		||||
      MetaShadowFactory *factory = meta_shadow_factory_get_default ();
 | 
			
		||||
      const char *shadow_class = meta_window_actor_get_shadow_class (self);
 | 
			
		||||
      cairo_rectangle_int_t shape_bounds;
 | 
			
		||||
 | 
			
		||||
      if (priv->shadow_shape == NULL)
 | 
			
		||||
        {
 | 
			
		||||
          if (priv->shaped)
 | 
			
		||||
            priv->shadow_shape = meta_window_shape_new (priv->shape_region);
 | 
			
		||||
          else
 | 
			
		||||
            priv->shadow_shape = meta_window_shape_new (priv->bounding_region);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_window_actor_get_shape_bounds (self, &shape_bounds);
 | 
			
		||||
 | 
			
		||||
      *shadow_location = meta_shadow_factory_get_shadow (factory,
 | 
			
		||||
                                                         priv->shadow_shape,
 | 
			
		||||
                                                         shape_bounds.width, shape_bounds.height,
 | 
			
		||||
                                                         shadow_class, appears_focused);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (old_shadow != NULL)
 | 
			
		||||
    meta_shadow_unref (old_shadow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_frozen (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
@@ -1733,6 +2009,7 @@ check_needs_reshape (MetaWindowActor *self)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  priv->needs_reshape = FALSE;
 | 
			
		||||
  meta_window_actor_invalidate_shadow (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1743,6 +2020,11 @@ meta_window_actor_update_shape (MetaWindowActor   *self,
 | 
			
		||||
 | 
			
		||||
  priv->shaped = shaped;
 | 
			
		||||
  priv->needs_reshape = TRUE;
 | 
			
		||||
  if (priv->shadow_shape != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_window_shape_unref (priv->shadow_shape);
 | 
			
		||||
      priv->shadow_shape = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_redraw (priv->actor);
 | 
			
		||||
}
 | 
			
		||||
@@ -1770,8 +2052,19 @@ meta_window_actor_pre_paint (MetaWindowActor *self)
 | 
			
		||||
      priv->received_damage = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  check_needs_reshape (self);
 | 
			
		||||
  check_needs_pixmap (self);
 | 
			
		||||
  check_needs_reshape (self);
 | 
			
		||||
  check_needs_shadow (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_actor_invalidate_shadow (MetaWindowActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->recompute_focused_shadow = TRUE;
 | 
			
		||||
  priv->recompute_unfocused_shadow = TRUE;
 | 
			
		||||
  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										253
									
								
								src/compositor/meta-window-shape.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								src/compositor/meta-window-shape.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,253 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaWindowShape
 | 
			
		||||
 *
 | 
			
		||||
 * Extracted invariant window shape
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-window-shape.h"
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowShape
 | 
			
		||||
{
 | 
			
		||||
  guint ref_count;
 | 
			
		||||
 | 
			
		||||
  int top, right, bottom, left;
 | 
			
		||||
  int n_rectangles;
 | 
			
		||||
  cairo_rectangle_int_t *rectangles;
 | 
			
		||||
  guint hash;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
MetaWindowShape *
 | 
			
		||||
meta_window_shape_new (cairo_region_t *region)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowShape *shape;
 | 
			
		||||
  MetaRegionIterator iter;
 | 
			
		||||
  cairo_rectangle_int_t extents;
 | 
			
		||||
  int max_yspan_y1 = 0;
 | 
			
		||||
  int max_yspan_y2 = 0;
 | 
			
		||||
  int max_xspan_x1 = -1;
 | 
			
		||||
  int max_xspan_x2 = -1;
 | 
			
		||||
  guint hash;
 | 
			
		||||
 | 
			
		||||
  shape = g_slice_new0 (MetaWindowShape);
 | 
			
		||||
  shape->ref_count = 1;
 | 
			
		||||
 | 
			
		||||
  cairo_region_get_extents (region, &extents);
 | 
			
		||||
 | 
			
		||||
  shape->n_rectangles = cairo_region_num_rectangles (region);
 | 
			
		||||
 | 
			
		||||
  if (shape->n_rectangles == 0)
 | 
			
		||||
    {
 | 
			
		||||
      shape->rectangles = NULL;
 | 
			
		||||
      shape->top = shape->right = shape->bottom = shape->left = 0;
 | 
			
		||||
      shape->hash = 0;
 | 
			
		||||
      return shape;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (meta_region_iterator_init (&iter, region);
 | 
			
		||||
       !meta_region_iterator_at_end (&iter);
 | 
			
		||||
       meta_region_iterator_next (&iter))
 | 
			
		||||
    {
 | 
			
		||||
      int max_line_xspan_x1 = -1;
 | 
			
		||||
      int max_line_xspan_x2 = -1;
 | 
			
		||||
 | 
			
		||||
      if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
 | 
			
		||||
        {
 | 
			
		||||
          max_line_xspan_x1 = iter.rectangle.x;
 | 
			
		||||
          max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (iter.line_end)
 | 
			
		||||
        {
 | 
			
		||||
          if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
 | 
			
		||||
            {
 | 
			
		||||
              max_yspan_y1 = iter.rectangle.y;
 | 
			
		||||
              max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (max_xspan_x1 < 0) /* First line */
 | 
			
		||||
            {
 | 
			
		||||
              max_xspan_x1 = max_line_xspan_x1;
 | 
			
		||||
              max_xspan_x2 = max_line_xspan_x2;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
 | 
			
		||||
              max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
 | 
			
		||||
 | 
			
		||||
              if (max_xspan_x2 < max_xspan_x1)
 | 
			
		||||
                max_xspan_x2 = max_xspan_x1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
 | 
			
		||||
           max_xspan_x1, max_xspan_x2,
 | 
			
		||||
           max_yspan_y1, max_yspan_y2);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  shape->top = max_yspan_y1 - extents.y;
 | 
			
		||||
  shape->right = extents.x + extents.width - max_xspan_x2;
 | 
			
		||||
  shape->bottom = extents.y + extents.height - max_yspan_y2;
 | 
			
		||||
  shape->left = max_xspan_x1 - extents.x;
 | 
			
		||||
 | 
			
		||||
  shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
 | 
			
		||||
 | 
			
		||||
  hash = 0;
 | 
			
		||||
  for (meta_region_iterator_init (&iter, region);
 | 
			
		||||
       !meta_region_iterator_at_end (&iter);
 | 
			
		||||
       meta_region_iterator_next (&iter))
 | 
			
		||||
    {
 | 
			
		||||
      int x1, x2, y1, y2;
 | 
			
		||||
 | 
			
		||||
      x1 = iter.rectangle.x;
 | 
			
		||||
      x2 = iter.rectangle.x + iter.rectangle.width;
 | 
			
		||||
      y1 = iter.rectangle.y;
 | 
			
		||||
      y2 = iter.rectangle.y + iter.rectangle.height;
 | 
			
		||||
 | 
			
		||||
      if (x1 > max_xspan_x1)
 | 
			
		||||
        x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
 | 
			
		||||
      if (x2 > max_xspan_x1)
 | 
			
		||||
        x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
 | 
			
		||||
      if (y1 > max_yspan_y1)
 | 
			
		||||
        y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
 | 
			
		||||
      if (y2 > max_yspan_y1)
 | 
			
		||||
        y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
 | 
			
		||||
 | 
			
		||||
      shape->rectangles[iter.i].x = x1 - extents.x;
 | 
			
		||||
      shape->rectangles[iter.i].y = y1 - extents.y;
 | 
			
		||||
      shape->rectangles[iter.i].width = x2 - x1;
 | 
			
		||||
      shape->rectangles[iter.i].height = y2 - y1;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
      g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
 | 
			
		||||
               i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
 | 
			
		||||
               shape->rectangles[i].x, shape->rectangles[i].y, shape->rectangles[i].width, shape->rectangles[i].height);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
      hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  shape->hash = hash;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  return shape;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWindowShape *
 | 
			
		||||
meta_window_shape_ref (MetaWindowShape *shape)
 | 
			
		||||
{
 | 
			
		||||
  shape->ref_count++;
 | 
			
		||||
 | 
			
		||||
  return shape;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_shape_unref (MetaWindowShape *shape)
 | 
			
		||||
{
 | 
			
		||||
  shape->ref_count--;
 | 
			
		||||
  if (shape->ref_count == 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (shape->rectangles);
 | 
			
		||||
      g_slice_free (MetaWindowShape, shape);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
meta_window_shape_hash (MetaWindowShape *shape)
 | 
			
		||||
{
 | 
			
		||||
  return shape->hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_window_shape_equal (MetaWindowShape *shape_a,
 | 
			
		||||
                         MetaWindowShape *shape_b)
 | 
			
		||||
{
 | 
			
		||||
  if (shape_a->n_rectangles != shape_b->n_rectangles)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return memcmp (shape_a->rectangles, shape_b->rectangles,
 | 
			
		||||
                 sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_shape_get_borders (MetaWindowShape *shape,
 | 
			
		||||
                               int             *border_top,
 | 
			
		||||
                               int             *border_right,
 | 
			
		||||
                               int             *border_bottom,
 | 
			
		||||
                               int             *border_left)
 | 
			
		||||
{
 | 
			
		||||
  if (border_top)
 | 
			
		||||
    *border_top = shape->top;
 | 
			
		||||
  if (border_right)
 | 
			
		||||
    *border_right = shape->right;
 | 
			
		||||
  if (border_bottom)
 | 
			
		||||
    *border_bottom = shape->bottom;
 | 
			
		||||
  if (border_left)
 | 
			
		||||
    *border_left = shape->left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_shape_to_region:
 | 
			
		||||
 * @shape: a #MetaWindowShape
 | 
			
		||||
 * @center_width: size of the central region horizontally
 | 
			
		||||
 * @center_height: size of the central region vertically
 | 
			
		||||
 *
 | 
			
		||||
 * Converts the shape to to a cairo_region_t using the given width
 | 
			
		||||
 * and height for the central scaled region.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: a newly created region
 | 
			
		||||
 */
 | 
			
		||||
cairo_region_t *
 | 
			
		||||
meta_window_shape_to_region (MetaWindowShape *shape,
 | 
			
		||||
                             int              center_width,
 | 
			
		||||
                             int              center_height)
 | 
			
		||||
{
 | 
			
		||||
  cairo_region_t *region;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  region = cairo_region_create ();
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < shape->n_rectangles; i++)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t rect = shape->rectangles[i];
 | 
			
		||||
 | 
			
		||||
      if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
 | 
			
		||||
        rect.width += center_width;
 | 
			
		||||
      else if (rect.x >= shape->left + 1)
 | 
			
		||||
        rect.x += center_width;
 | 
			
		||||
 | 
			
		||||
      if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
 | 
			
		||||
        rect.height += center_height;
 | 
			
		||||
      else if (rect.y >= shape->top + 1)
 | 
			
		||||
        rect.y += center_height;
 | 
			
		||||
 | 
			
		||||
      cairo_region_union_rectangle (region, &rect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return region;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								src/compositor/meta-window-shape.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/compositor/meta-window-shape.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaWindowShape
 | 
			
		||||
 *
 | 
			
		||||
 * Extracted invariant window shape
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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_WINDOW_SHAPE_H__
 | 
			
		||||
#define __META_WINDOW_SHAPE_H__
 | 
			
		||||
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaWindowShape:
 | 
			
		||||
 * #MetaWindowShape represents a 9-sliced region with borders on all sides that
 | 
			
		||||
 * are unscaled, and a constant central region that is scaled. For example,
 | 
			
		||||
 * if you the regions representing two windows that around rounded rectangles,
 | 
			
		||||
 * with the same corner regions, but different sizes, they have the
 | 
			
		||||
 * same MetaWindowShape.
 | 
			
		||||
 *
 | 
			
		||||
 * #MetaWindowShape is designed to be used as part of a hash table key, so has
 | 
			
		||||
 * efficient hash and equal functions.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaWindowShape MetaWindowShape;
 | 
			
		||||
 | 
			
		||||
MetaWindowShape *  meta_window_shape_new         (cairo_region_t  *region);
 | 
			
		||||
MetaWindowShape *  meta_window_shape_ref         (MetaWindowShape *shape);
 | 
			
		||||
void               meta_window_shape_unref       (MetaWindowShape *shape);
 | 
			
		||||
guint              meta_window_shape_hash        (MetaWindowShape *shape);
 | 
			
		||||
gboolean           meta_window_shape_equal       (MetaWindowShape *shape_a,
 | 
			
		||||
                                                  MetaWindowShape *shape_b);
 | 
			
		||||
void               meta_window_shape_get_borders (MetaWindowShape *shape,
 | 
			
		||||
                                                  int             *border_top,
 | 
			
		||||
                                                  int             *border_right,
 | 
			
		||||
                                                  int             *border_bottom,
 | 
			
		||||
                                                  int             *border_left);
 | 
			
		||||
cairo_region_t    *meta_window_shape_to_region   (MetaWindowShape *shape,
 | 
			
		||||
                                                  int              center_width,
 | 
			
		||||
                                                  int              center_height);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_WINDOW_SHAPE_H __*/
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										334
									
								
								src/compositor/region-utils.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								src/compositor/region-utils.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,334 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Utilities for region manipulation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
/* MetaRegionBuilder */
 | 
			
		||||
 | 
			
		||||
/* Various algorithms in this file require unioning together a set of rectangles
 | 
			
		||||
 * that are unsorted or overlap; unioning such a set of rectangles 1-by-1
 | 
			
		||||
 * using cairo_region_union_rectangle() produces O(N^2) behavior (if the union
 | 
			
		||||
 * adds or removes rectangles in the middle of the region, then it has to
 | 
			
		||||
 * move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder
 | 
			
		||||
 * creates regions for small groups of rectangles and merges them together in
 | 
			
		||||
 * a binary tree.
 | 
			
		||||
 *
 | 
			
		||||
 * Possible improvement: From a glance at the code, accumulating all the rectangles
 | 
			
		||||
 *  into a flat array and then calling the (not usefully documented)
 | 
			
		||||
 *  cairo_region_create_rectangles() would have the same behavior and would be
 | 
			
		||||
 *  simpler and a bit more efficient.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
 | 
			
		||||
 * But using 8 may be more robust to systems with slow malloc(). */
 | 
			
		||||
#define MAX_CHUNK_RECTANGLES 8
 | 
			
		||||
#define MAX_LEVELS 16
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  /* To merge regions in a binary tree, we need to keep track of The way these are filled is in the pattern:
 | 
			
		||||
   *
 | 
			
		||||
   * |a  |
 | 
			
		||||
   * |b  |a  |
 | 
			
		||||
   * |c  |   |ab |
 | 
			
		||||
   * |d  |c  |ab |
 | 
			
		||||
   * |e  |   |   |abcd|
 | 
			
		||||
   */
 | 
			
		||||
  cairo_region_t *levels[MAX_LEVELS];
 | 
			
		||||
  int n_levels;
 | 
			
		||||
} MetaRegionBuilder;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_region_builder_init (MetaRegionBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  for (i = 0; i < MAX_LEVELS; i++)
 | 
			
		||||
    builder->levels[i] = NULL;
 | 
			
		||||
  builder->n_levels = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
 | 
			
		||||
                                   int                x,
 | 
			
		||||
                                   int                y,
 | 
			
		||||
                                   int                width,
 | 
			
		||||
                                   int                height)
 | 
			
		||||
{
 | 
			
		||||
  cairo_rectangle_int_t rect;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (builder->levels[0] == NULL)
 | 
			
		||||
    builder->levels[0] = cairo_region_create ();
 | 
			
		||||
 | 
			
		||||
  rect.x = x;
 | 
			
		||||
  rect.y = y;
 | 
			
		||||
  rect.width = width;
 | 
			
		||||
  rect.height = height;
 | 
			
		||||
 | 
			
		||||
  cairo_region_union_rectangle (builder->levels[0], &rect);
 | 
			
		||||
  if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES)
 | 
			
		||||
    {
 | 
			
		||||
      for (i = 1; i < builder->n_levels + 1; i++)
 | 
			
		||||
        {
 | 
			
		||||
          if (builder->levels[i] == NULL)
 | 
			
		||||
            {
 | 
			
		||||
              if (i < MAX_LEVELS)
 | 
			
		||||
                {
 | 
			
		||||
                  builder->levels[i] = builder->levels[i - 1];
 | 
			
		||||
                  builder->levels[i - 1] = NULL;
 | 
			
		||||
                  if (i == builder->n_levels)
 | 
			
		||||
                    builder->n_levels++;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              cairo_region_union (builder->levels[i], builder->levels[i - 1]);
 | 
			
		||||
              cairo_region_destroy (builder->levels[i - 1]);
 | 
			
		||||
              builder->levels[i - 1] = NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
meta_region_builder_finish (MetaRegionBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
  cairo_region_t *result = NULL;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < builder->n_levels; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (builder->levels[i])
 | 
			
		||||
        {
 | 
			
		||||
          if (result == NULL)
 | 
			
		||||
            result = builder->levels[i];
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              cairo_region_union(result, builder->levels[i]);
 | 
			
		||||
              cairo_region_destroy (builder->levels[i]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (result == NULL)
 | 
			
		||||
    result = cairo_region_create ();
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* MetaRegionIterator */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_region_iterator_init (MetaRegionIterator *iter,
 | 
			
		||||
                           cairo_region_t     *region)
 | 
			
		||||
{
 | 
			
		||||
  iter->region = region;
 | 
			
		||||
  iter->i = 0;
 | 
			
		||||
  iter->n_rectangles = cairo_region_num_rectangles (region);
 | 
			
		||||
  iter->line_start = TRUE;
 | 
			
		||||
 | 
			
		||||
  if (iter->n_rectangles > 1)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_region_get_rectangle (region, 0, &iter->rectangle);
 | 
			
		||||
      cairo_region_get_rectangle (region, 1, &iter->next_rectangle);
 | 
			
		||||
 | 
			
		||||
      iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
 | 
			
		||||
    }
 | 
			
		||||
  else if (iter->n_rectangles > 0)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_region_get_rectangle (region, 0, &iter->rectangle);
 | 
			
		||||
      iter->line_end = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_region_iterator_at_end (MetaRegionIterator *iter)
 | 
			
		||||
{
 | 
			
		||||
  return iter->i >= iter->n_rectangles;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_region_iterator_next (MetaRegionIterator *iter)
 | 
			
		||||
{
 | 
			
		||||
  iter->i++;
 | 
			
		||||
  iter->rectangle = iter->next_rectangle;
 | 
			
		||||
  iter->line_start = iter->line_end;
 | 
			
		||||
 | 
			
		||||
  if (iter->i < iter->n_rectangles)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle);
 | 
			
		||||
      iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      iter->line_end = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
add_expanded_rect (MetaRegionBuilder  *builder,
 | 
			
		||||
                   int                 x,
 | 
			
		||||
                   int                 y,
 | 
			
		||||
                   int                 width,
 | 
			
		||||
                   int                 height,
 | 
			
		||||
                   int                 x_amount,
 | 
			
		||||
                   int                 y_amount,
 | 
			
		||||
                   gboolean            flip)
 | 
			
		||||
{
 | 
			
		||||
  if (flip)
 | 
			
		||||
    meta_region_builder_add_rectangle (builder,
 | 
			
		||||
                                         y - y_amount, x - x_amount,
 | 
			
		||||
                                         height + 2 * y_amount, width + 2 * x_amount);
 | 
			
		||||
  else
 | 
			
		||||
    meta_region_builder_add_rectangle (builder,
 | 
			
		||||
                                         x - x_amount, y - y_amount,
 | 
			
		||||
                                         width + 2 * x_amount, height + 2 * y_amount);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
expand_region (cairo_region_t *region,
 | 
			
		||||
               int             x_amount,
 | 
			
		||||
               int             y_amount,
 | 
			
		||||
               gboolean        flip)
 | 
			
		||||
{
 | 
			
		||||
  MetaRegionBuilder builder;
 | 
			
		||||
  int n;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  meta_region_builder_init (&builder);
 | 
			
		||||
 | 
			
		||||
  n = cairo_region_num_rectangles (region);
 | 
			
		||||
  for (i = 0; i < n; i++)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t rect;
 | 
			
		||||
 | 
			
		||||
      cairo_region_get_rectangle (region, i, &rect);
 | 
			
		||||
      add_expanded_rect (&builder,
 | 
			
		||||
                         rect.x, rect.y, rect.width, rect.height,
 | 
			
		||||
                         x_amount, y_amount, flip);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_region_builder_finish (&builder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This computes a (clipped version) of the inverse of the region
 | 
			
		||||
 * and expands it by the given amount */
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
expand_region_inverse (cairo_region_t *region,
 | 
			
		||||
                       int             x_amount,
 | 
			
		||||
                       int             y_amount,
 | 
			
		||||
                       gboolean        flip)
 | 
			
		||||
{
 | 
			
		||||
  MetaRegionBuilder builder;
 | 
			
		||||
  MetaRegionIterator iter;
 | 
			
		||||
  cairo_rectangle_int_t extents;
 | 
			
		||||
  cairo_region_t *chunk;
 | 
			
		||||
 | 
			
		||||
  int last_x;
 | 
			
		||||
 | 
			
		||||
  meta_region_builder_init (&builder);
 | 
			
		||||
 | 
			
		||||
  cairo_region_get_extents (region, &extents);
 | 
			
		||||
  add_expanded_rect (&builder,
 | 
			
		||||
                     extents.x, extents.y - 1, extents.width, 1,
 | 
			
		||||
                     x_amount, y_amount, flip);
 | 
			
		||||
  add_expanded_rect (&builder,
 | 
			
		||||
                     extents.x - 1, extents.y, 1, extents.height,
 | 
			
		||||
                     x_amount, y_amount, flip);
 | 
			
		||||
  add_expanded_rect (&builder,
 | 
			
		||||
                     extents.x + extents.width, extents.y, 1, extents.height,
 | 
			
		||||
                     x_amount, y_amount, flip);
 | 
			
		||||
  add_expanded_rect (&builder,
 | 
			
		||||
                     extents.x, extents.y + extents.height, extents.width, 1,
 | 
			
		||||
                     x_amount, y_amount, flip);
 | 
			
		||||
 | 
			
		||||
  chunk = NULL;
 | 
			
		||||
 | 
			
		||||
  last_x = extents.x;
 | 
			
		||||
  for (meta_region_iterator_init (&iter, region);
 | 
			
		||||
       !meta_region_iterator_at_end (&iter);
 | 
			
		||||
       meta_region_iterator_next (&iter))
 | 
			
		||||
    {
 | 
			
		||||
      if (chunk == NULL)
 | 
			
		||||
        chunk = cairo_region_create ();
 | 
			
		||||
 | 
			
		||||
      if (iter.rectangle.x > last_x)
 | 
			
		||||
        add_expanded_rect (&builder,
 | 
			
		||||
                           last_x, iter.rectangle.y,
 | 
			
		||||
                           iter.rectangle.x - last_x, iter.rectangle.height,
 | 
			
		||||
                           x_amount, y_amount, flip);
 | 
			
		||||
 | 
			
		||||
      if (iter.line_end)
 | 
			
		||||
        {
 | 
			
		||||
          if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width)
 | 
			
		||||
            add_expanded_rect (&builder,
 | 
			
		||||
                               iter.rectangle.x + iter.rectangle.width, iter.rectangle.y,
 | 
			
		||||
                               (extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height,
 | 
			
		||||
                               x_amount, y_amount, flip);
 | 
			
		||||
          last_x = extents.x;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        last_x = iter.rectangle.x + iter.rectangle.width;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_region_builder_finish (&builder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_make_border_region:
 | 
			
		||||
 * @region: a #cairo_region_t
 | 
			
		||||
 * @x_amount: distance from the border to extend horizontally
 | 
			
		||||
 * @y_amount: distance from the border to extend vertically
 | 
			
		||||
 * @flip: if true, the result is computed with x and y interchanged
 | 
			
		||||
 *
 | 
			
		||||
 * Computes the "border region" of a given region, which is roughly
 | 
			
		||||
 * speaking the set of points near the boundary of the region.  If we
 | 
			
		||||
 * define the operation of growing a region as computing the set of
 | 
			
		||||
 * points within a given manhattan distance of the region, then the
 | 
			
		||||
 * border is 'grow(region) intersect grow(inverse(region))'.
 | 
			
		||||
 *
 | 
			
		||||
 * If we create an image by filling the region with a solid color,
 | 
			
		||||
 * the border is the region affected by blurring the region.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: a new region which is the border of the given region
 | 
			
		||||
 */
 | 
			
		||||
cairo_region_t *
 | 
			
		||||
meta_make_border_region (cairo_region_t *region,
 | 
			
		||||
                         int             x_amount,
 | 
			
		||||
                         int             y_amount,
 | 
			
		||||
                         gboolean        flip)
 | 
			
		||||
{
 | 
			
		||||
  cairo_region_t *border_region;
 | 
			
		||||
  cairo_region_t *inverse_region;
 | 
			
		||||
 | 
			
		||||
  border_region = expand_region (region, x_amount, y_amount, flip);
 | 
			
		||||
  inverse_region = expand_region_inverse (region, x_amount, y_amount, flip);
 | 
			
		||||
  cairo_region_intersect (border_region, inverse_region);
 | 
			
		||||
  cairo_region_destroy (inverse_region);
 | 
			
		||||
 | 
			
		||||
  return border_region;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								src/compositor/region-utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/compositor/region-utils.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * Utilities for region manipulation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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_REGION_UTILS_H__
 | 
			
		||||
#define __META_REGION_UTILS_H__
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaRegionIterator:
 | 
			
		||||
 * @region: region being iterated
 | 
			
		||||
 * @rectangle: current rectangle
 | 
			
		||||
 * @line_start: whether the current rectangle starts a horizontal band
 | 
			
		||||
 * @line_end: whether the current rectangle ends a horizontal band
 | 
			
		||||
 *
 | 
			
		||||
 * cairo_region_t is a yx banded region; sometimes its useful to iterate through
 | 
			
		||||
 * such a region treating the start and end of each horizontal band in a distinct
 | 
			
		||||
 * fashion.
 | 
			
		||||
 *
 | 
			
		||||
 * Usage:
 | 
			
		||||
 *
 | 
			
		||||
 *  MetaRegionIterator iter;
 | 
			
		||||
 *  for (meta_region_iterator_init (&iter, region);
 | 
			
		||||
 *       !meta_region_iterator_at_end (&iter);
 | 
			
		||||
 *       meta_region_iterator_next (&iter))
 | 
			
		||||
 *  {
 | 
			
		||||
 *    [ Use iter.rectangle, iter.line_start, iter.line_end ]
 | 
			
		||||
 *  }
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaRegionIterator MetaRegionIterator;
 | 
			
		||||
 | 
			
		||||
struct _MetaRegionIterator {
 | 
			
		||||
  cairo_region_t *region;
 | 
			
		||||
  cairo_rectangle_int_t rectangle;
 | 
			
		||||
  gboolean line_start;
 | 
			
		||||
  gboolean line_end;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  /*< private >*/
 | 
			
		||||
  int n_rectangles;
 | 
			
		||||
  cairo_rectangle_int_t next_rectangle;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void     meta_region_iterator_init      (MetaRegionIterator *iter,
 | 
			
		||||
                                         cairo_region_t     *region);
 | 
			
		||||
gboolean meta_region_iterator_at_end    (MetaRegionIterator *iter);
 | 
			
		||||
void     meta_region_iterator_next      (MetaRegionIterator *iter);
 | 
			
		||||
 | 
			
		||||
cairo_region_t *meta_make_border_region (cairo_region_t *region,
 | 
			
		||||
                                         int             x_amount,
 | 
			
		||||
                                         int             y_amount,
 | 
			
		||||
                                         gboolean        flip);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_REGION_UTILS_H__ */
 | 
			
		||||
@@ -1,350 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE /* For M_PI */
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "shadow.h"
 | 
			
		||||
#include "tidy/tidy-texture-frame.h"
 | 
			
		||||
 | 
			
		||||
#define SHADOW_RADIUS 8
 | 
			
		||||
#define SHADOW_OPACITY	0.9
 | 
			
		||||
#define SHADOW_OFFSET_X	(SHADOW_RADIUS)
 | 
			
		||||
#define SHADOW_OFFSET_Y	(SHADOW_RADIUS)
 | 
			
		||||
 | 
			
		||||
#define MAX_TILE_SZ 8 	/* Must be <= shaddow radius */
 | 
			
		||||
#define TILE_WIDTH  (3*MAX_TILE_SZ)
 | 
			
		||||
#define TILE_HEIGHT (3*MAX_TILE_SZ)
 | 
			
		||||
 | 
			
		||||
static unsigned char* shadow_gaussian_make_tile (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *
 | 
			
		||||
meta_create_shadow_frame (MetaCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor *frame;
 | 
			
		||||
 | 
			
		||||
  if (!compositor->shadow_src)
 | 
			
		||||
    {
 | 
			
		||||
      guchar *data;
 | 
			
		||||
 | 
			
		||||
      data = shadow_gaussian_make_tile ();
 | 
			
		||||
 | 
			
		||||
      compositor->shadow_src = clutter_texture_new ();
 | 
			
		||||
 | 
			
		||||
      clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
 | 
			
		||||
                                         data,
 | 
			
		||||
                                         TRUE,
 | 
			
		||||
                                         TILE_WIDTH,
 | 
			
		||||
                                         TILE_HEIGHT,
 | 
			
		||||
                                         TILE_WIDTH*4,
 | 
			
		||||
                                         4,
 | 
			
		||||
                                         0,
 | 
			
		||||
                                         NULL);
 | 
			
		||||
      g_free (data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
 | 
			
		||||
                                  MAX_TILE_SZ,
 | 
			
		||||
                                  MAX_TILE_SZ,
 | 
			
		||||
                                  MAX_TILE_SZ,
 | 
			
		||||
                                  MAX_TILE_SZ);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_set_position (frame,
 | 
			
		||||
                              SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
 | 
			
		||||
 | 
			
		||||
  return frame;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct GaussianMap
 | 
			
		||||
{
 | 
			
		||||
  int	   size;
 | 
			
		||||
  double * data;
 | 
			
		||||
} GaussianMap;
 | 
			
		||||
 | 
			
		||||
static double
 | 
			
		||||
gaussian (double r, double x, double y)
 | 
			
		||||
{
 | 
			
		||||
  return ((1 / (sqrt (2 * M_PI * r))) *
 | 
			
		||||
	  exp ((- (x * x + y * y)) / (2 * r * r)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static GaussianMap *
 | 
			
		||||
make_gaussian_map (double r)
 | 
			
		||||
{
 | 
			
		||||
  GaussianMap  *c;
 | 
			
		||||
  int	          size = ((int) ceil ((r * 3)) + 1) & ~1;
 | 
			
		||||
  int	          center = size / 2;
 | 
			
		||||
  int	          x, y;
 | 
			
		||||
  double          t = 0.0;
 | 
			
		||||
  double          g;
 | 
			
		||||
 | 
			
		||||
  c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
 | 
			
		||||
  c->size = size;
 | 
			
		||||
 | 
			
		||||
  c->data = (double *) (c + 1);
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < size; y++)
 | 
			
		||||
    for (x = 0; x < size; x++)
 | 
			
		||||
      {
 | 
			
		||||
	g = gaussian (r, (double) (x - center), (double) (y - center));
 | 
			
		||||
	t += g;
 | 
			
		||||
	c->data[y * size + x] = g;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < size; y++)
 | 
			
		||||
    for (x = 0; x < size; x++)
 | 
			
		||||
      c->data[y*size + x] /= t;
 | 
			
		||||
 | 
			
		||||
  return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned char
 | 
			
		||||
sum_gaussian (GaussianMap * map, double opacity,
 | 
			
		||||
              int x, int y, int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  int	           fx, fy;
 | 
			
		||||
  double         * g_data;
 | 
			
		||||
  double         * g_line = map->data;
 | 
			
		||||
  int	           g_size = map->size;
 | 
			
		||||
  int	           center = g_size / 2;
 | 
			
		||||
  int	           fx_start, fx_end;
 | 
			
		||||
  int	           fy_start, fy_end;
 | 
			
		||||
  double           v;
 | 
			
		||||
  unsigned int     r;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Compute set of filter values which are "in range",
 | 
			
		||||
   * that's the set with:
 | 
			
		||||
   *	0 <= x + (fx-center) && x + (fx-center) < width &&
 | 
			
		||||
   *  0 <= y + (fy-center) && y + (fy-center) < height
 | 
			
		||||
   *
 | 
			
		||||
   *  0 <= x + (fx - center)	x + fx - center < width
 | 
			
		||||
   *  center - x <= fx	fx < width + center - x
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  fx_start = center - x;
 | 
			
		||||
  if (fx_start < 0)
 | 
			
		||||
    fx_start = 0;
 | 
			
		||||
  fx_end = width + center - x;
 | 
			
		||||
  if (fx_end > g_size)
 | 
			
		||||
    fx_end = g_size;
 | 
			
		||||
 | 
			
		||||
  fy_start = center - y;
 | 
			
		||||
  if (fy_start < 0)
 | 
			
		||||
    fy_start = 0;
 | 
			
		||||
  fy_end = height + center - y;
 | 
			
		||||
  if (fy_end > g_size)
 | 
			
		||||
    fy_end = g_size;
 | 
			
		||||
 | 
			
		||||
  g_line = g_line + fy_start * g_size + fx_start;
 | 
			
		||||
 | 
			
		||||
  v = 0;
 | 
			
		||||
  for (fy = fy_start; fy < fy_end; fy++)
 | 
			
		||||
    {
 | 
			
		||||
      g_data = g_line;
 | 
			
		||||
      g_line += g_size;
 | 
			
		||||
 | 
			
		||||
      for (fx = fx_start; fx < fx_end; fx++)
 | 
			
		||||
	v += *g_data++;
 | 
			
		||||
    }
 | 
			
		||||
  if (v > 1)
 | 
			
		||||
    v = 1;
 | 
			
		||||
 | 
			
		||||
  v *= (opacity * 255.0);
 | 
			
		||||
 | 
			
		||||
  r = (unsigned int) v;
 | 
			
		||||
 | 
			
		||||
  return (unsigned char) r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned char *
 | 
			
		||||
shadow_gaussian_make_tile ()
 | 
			
		||||
{
 | 
			
		||||
  unsigned char              * data;
 | 
			
		||||
  int		               size;
 | 
			
		||||
  int		               center;
 | 
			
		||||
  int		               x, y;
 | 
			
		||||
  unsigned char                d;
 | 
			
		||||
  int                          pwidth, pheight;
 | 
			
		||||
  double                       opacity = SHADOW_OPACITY;
 | 
			
		||||
  static GaussianMap       * gaussian_map = NULL;
 | 
			
		||||
 | 
			
		||||
  struct _mypixel
 | 
			
		||||
  {
 | 
			
		||||
    unsigned char r;
 | 
			
		||||
    unsigned char g;
 | 
			
		||||
    unsigned char b;
 | 
			
		||||
    unsigned char a;
 | 
			
		||||
  } * _d;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  if (!gaussian_map)
 | 
			
		||||
    gaussian_map =
 | 
			
		||||
      make_gaussian_map (SHADOW_RADIUS);
 | 
			
		||||
 | 
			
		||||
  size   = gaussian_map->size;
 | 
			
		||||
  center = size / 2;
 | 
			
		||||
 | 
			
		||||
  /* Top & bottom */
 | 
			
		||||
 | 
			
		||||
  pwidth  = MAX_TILE_SZ;
 | 
			
		||||
  pheight = MAX_TILE_SZ;
 | 
			
		||||
 | 
			
		||||
  data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
  _d = (struct _mypixel*) data;
 | 
			
		||||
 | 
			
		||||
  /* N */
 | 
			
		||||
  for (y = 0; y < pheight; y++)
 | 
			
		||||
    {
 | 
			
		||||
      d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                        center, y - center,
 | 
			
		||||
                        TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
      for (x = 0; x < pwidth; x++)
 | 
			
		||||
	{
 | 
			
		||||
	  _d[y*3*pwidth + x + pwidth].r = 0;
 | 
			
		||||
	  _d[y*3*pwidth + x + pwidth].g = 0;
 | 
			
		||||
	  _d[y*3*pwidth + x + pwidth].b = 0;
 | 
			
		||||
	  _d[y*3*pwidth + x + pwidth].a = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* S */
 | 
			
		||||
  pwidth = MAX_TILE_SZ;
 | 
			
		||||
  pheight = MAX_TILE_SZ;
 | 
			
		||||
 | 
			
		||||
  for (y = 0; y < pheight; y++)
 | 
			
		||||
    {
 | 
			
		||||
      d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                        center, y - center,
 | 
			
		||||
                        TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
      for (x = 0; x < pwidth; x++)
 | 
			
		||||
	{
 | 
			
		||||
	  _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].r = 0;
 | 
			
		||||
	  _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].g = 0;
 | 
			
		||||
	  _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].b = 0;
 | 
			
		||||
	  _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].a = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* w */
 | 
			
		||||
  pwidth = MAX_TILE_SZ;
 | 
			
		||||
  pheight = MAX_TILE_SZ;
 | 
			
		||||
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    {
 | 
			
		||||
      d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                        x - center, center,
 | 
			
		||||
                        TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
      for (y = 0; y < pheight; y++)
 | 
			
		||||
	{
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + x].r = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + x].g = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + x].b = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + x].a = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* E */
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    {
 | 
			
		||||
      d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
					       x - center, center,
 | 
			
		||||
					       TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
      for (y = 0; y < pheight; y++)
 | 
			
		||||
	{
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].r = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].g = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].b = 0;
 | 
			
		||||
	  _d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].a = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* NW */
 | 
			
		||||
  pwidth = MAX_TILE_SZ;
 | 
			
		||||
  pheight = MAX_TILE_SZ;
 | 
			
		||||
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    for (y = 0; y < pheight; y++)
 | 
			
		||||
      {
 | 
			
		||||
	d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                          x-center, y-center,
 | 
			
		||||
                          TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
	_d[y*3*pwidth + x].r = 0;
 | 
			
		||||
	_d[y*3*pwidth + x].g = 0;
 | 
			
		||||
	_d[y*3*pwidth + x].b = 0;
 | 
			
		||||
	_d[y*3*pwidth + x].a = d;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  /* SW */
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    for (y = 0; y < pheight; y++)
 | 
			
		||||
      {
 | 
			
		||||
	d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                          x-center, y-center,
 | 
			
		||||
                          TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].r = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].g = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].b = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].a = d;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  /* SE */
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    for (y = 0; y < pheight; y++)
 | 
			
		||||
      {
 | 
			
		||||
	d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                          x-center, y-center,
 | 
			
		||||
                          TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
 | 
			
		||||
	   2*pwidth].r = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
 | 
			
		||||
	   2*pwidth].g = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
 | 
			
		||||
	   2*pwidth].b = 0;
 | 
			
		||||
	_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
 | 
			
		||||
	   2*pwidth].a = d;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  /* NE */
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    for (y = 0; y < pheight; y++)
 | 
			
		||||
      {
 | 
			
		||||
	d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                          x-center, y-center,
 | 
			
		||||
                          TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
	_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].r = 0;
 | 
			
		||||
	_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].g = 0;
 | 
			
		||||
	_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].b = 0;
 | 
			
		||||
	_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].a = d;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  /* center */
 | 
			
		||||
  pwidth = MAX_TILE_SZ;
 | 
			
		||||
  pheight = MAX_TILE_SZ;
 | 
			
		||||
 | 
			
		||||
  d = sum_gaussian (gaussian_map, opacity,
 | 
			
		||||
                    center, center, TILE_WIDTH, TILE_HEIGHT);
 | 
			
		||||
 | 
			
		||||
  for (x = 0; x < pwidth; x++)
 | 
			
		||||
    for (y = 0; y < pheight; y++)
 | 
			
		||||
      {
 | 
			
		||||
	_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].r = 0;
 | 
			
		||||
	_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].g = 0;
 | 
			
		||||
	_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].b = 0;
 | 
			
		||||
	_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].a = 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
#ifndef SHADOW_H
 | 
			
		||||
#define SHADOW_H
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include "compositor.h"
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_create_shadow_frame (MetaCompositor *compositor);
 | 
			
		||||
 | 
			
		||||
#endif /* SHADOW_H */
 | 
			
		||||
@@ -1,641 +0,0 @@
 | 
			
		||||
/* 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,84 +0,0 @@
 | 
			
		||||
/* 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 */
 | 
			
		||||
@@ -117,65 +117,8 @@ meta_core_get (Display *xdisplay,
 | 
			
		||||
        *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
 | 
			
		||||
        break; 
 | 
			
		||||
      case META_CORE_GET_FRAME_TYPE:
 | 
			
		||||
          {
 | 
			
		||||
          MetaFrameType base_type = META_FRAME_TYPE_LAST;
 | 
			
		||||
 | 
			
		||||
          switch (window->type)
 | 
			
		||||
            {
 | 
			
		||||
            case META_WINDOW_NORMAL:
 | 
			
		||||
              base_type = META_FRAME_TYPE_NORMAL;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case META_WINDOW_DIALOG:
 | 
			
		||||
              base_type = META_FRAME_TYPE_DIALOG;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case META_WINDOW_MODAL_DIALOG:
 | 
			
		||||
              base_type = META_FRAME_TYPE_MODAL_DIALOG;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case META_WINDOW_MENU:
 | 
			
		||||
              base_type = META_FRAME_TYPE_MENU;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case META_WINDOW_UTILITY:
 | 
			
		||||
              base_type = META_FRAME_TYPE_UTILITY;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case META_WINDOW_DESKTOP:
 | 
			
		||||
            case META_WINDOW_DOCK:
 | 
			
		||||
            case META_WINDOW_TOOLBAR:
 | 
			
		||||
            case META_WINDOW_SPLASHSCREEN:
 | 
			
		||||
	    case META_WINDOW_DROPDOWN_MENU:
 | 
			
		||||
	    case META_WINDOW_POPUP_MENU:
 | 
			
		||||
	    case META_WINDOW_TOOLTIP:
 | 
			
		||||
	    case META_WINDOW_NOTIFICATION:
 | 
			
		||||
	    case META_WINDOW_COMBO:
 | 
			
		||||
	    case META_WINDOW_DND:
 | 
			
		||||
	    case META_WINDOW_OVERRIDE_OTHER:
 | 
			
		||||
              /* No frame */
 | 
			
		||||
              base_type = META_FRAME_TYPE_LAST;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (base_type == META_FRAME_TYPE_LAST)
 | 
			
		||||
            {
 | 
			
		||||
              /* can't add border if undecorated */
 | 
			
		||||
              *((MetaFrameType*)answer) = META_FRAME_TYPE_LAST; 
 | 
			
		||||
            }
 | 
			
		||||
          else if (window->border_only)
 | 
			
		||||
            {
 | 
			
		||||
              /* override base frame type */
 | 
			
		||||
              *((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER; 
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              *((MetaFrameType*)answer) = base_type;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          break; 
 | 
			
		||||
          }
 | 
			
		||||
        *((MetaFrameType*)answer) = meta_window_get_frame_type (window);
 | 
			
		||||
        break;
 | 
			
		||||
      case META_CORE_GET_MINI_ICON:
 | 
			
		||||
        *((GdkPixbuf**)answer) = window->mini_icon;
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
@@ -461,8 +461,6 @@ void        meta_window_update_fullscreen_monitors (MetaWindow    *window,
 | 
			
		||||
                                                    unsigned long  left,
 | 
			
		||||
                                                    unsigned long  right);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_appears_focused (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
/* args to move are window pos, not frame pos */
 | 
			
		||||
void        meta_window_move               (MetaWindow  *window,
 | 
			
		||||
                                            gboolean     user_op,
 | 
			
		||||
 
 | 
			
		||||
@@ -3158,6 +3158,32 @@ meta_window_maximize (MetaWindow        *window,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_get_maximized:
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the current maximization state of the window, as combination
 | 
			
		||||
 * of the %META_MAXIMIZE_HORIZONTAL and %META_MAXIMIZE_VERTICAL flags;
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: current maximization state
 | 
			
		||||
 */
 | 
			
		||||
MetaMaximizeFlags
 | 
			
		||||
meta_window_get_maximized (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  return ((window->maximized_horizontally ? META_MAXIMIZE_HORIZONTAL : 0) |
 | 
			
		||||
          (window->maximized_vertically ? META_MAXIMIZE_VERTICAL : 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_is_fullscreen:
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: %TRUE if the window is currently fullscreen
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_window_is_fullscreen (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  return window->fullscreen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_tile (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
@@ -9275,9 +9301,22 @@ transient_has_focus (MetaWindow *window,
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_appears_focused:
 | 
			
		||||
 * @window: a #MetaWindow
 | 
			
		||||
 *
 | 
			
		||||
 * Determines if the window should be drawn with a focused appearance. This is
 | 
			
		||||
 * true for focused windows but also true for windows with a focused modal
 | 
			
		||||
 * dialog attached.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: %TRUE if the window should be drawn with a focused frame
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_window_appears_focused (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  /* FIXME: meta_window_foreach_transient() iterates over all windows; we
 | 
			
		||||
   *  should eat the complexity to cache a bit for this.
 | 
			
		||||
   */
 | 
			
		||||
  if (!window->has_focus && meta_prefs_get_attach_modal_dialogs ())
 | 
			
		||||
    {
 | 
			
		||||
      gboolean focus = FALSE;
 | 
			
		||||
@@ -9655,3 +9694,74 @@ meta_window_get_mutter_hints (MetaWindow *window)
 | 
			
		||||
 | 
			
		||||
  return window->mutter_hints;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_get_frame_type:
 | 
			
		||||
 * @window: a #MetaWindow
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the type of window decorations that should be used for this window.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the frame type
 | 
			
		||||
 */
 | 
			
		||||
MetaFrameType
 | 
			
		||||
meta_window_get_frame_type (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaFrameType base_type = META_FRAME_TYPE_LAST;
 | 
			
		||||
 | 
			
		||||
  switch (window->type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_WINDOW_NORMAL:
 | 
			
		||||
      base_type = META_FRAME_TYPE_NORMAL;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_WINDOW_DIALOG:
 | 
			
		||||
      base_type = META_FRAME_TYPE_DIALOG;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_WINDOW_MODAL_DIALOG:
 | 
			
		||||
      if (meta_prefs_get_attach_modal_dialogs () &&
 | 
			
		||||
          meta_window_get_transient_for (window) != NULL)
 | 
			
		||||
        base_type = META_FRAME_TYPE_ATTACHED;
 | 
			
		||||
      else
 | 
			
		||||
        base_type = META_FRAME_TYPE_MODAL_DIALOG;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_WINDOW_MENU:
 | 
			
		||||
      base_type = META_FRAME_TYPE_MENU;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_WINDOW_UTILITY:
 | 
			
		||||
      base_type = META_FRAME_TYPE_UTILITY;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_WINDOW_DESKTOP:
 | 
			
		||||
    case META_WINDOW_DOCK:
 | 
			
		||||
    case META_WINDOW_TOOLBAR:
 | 
			
		||||
    case META_WINDOW_SPLASHSCREEN:
 | 
			
		||||
    case META_WINDOW_DROPDOWN_MENU:
 | 
			
		||||
    case META_WINDOW_POPUP_MENU:
 | 
			
		||||
    case META_WINDOW_TOOLTIP:
 | 
			
		||||
    case META_WINDOW_NOTIFICATION:
 | 
			
		||||
    case META_WINDOW_COMBO:
 | 
			
		||||
    case META_WINDOW_DND:
 | 
			
		||||
    case META_WINDOW_OVERRIDE_OTHER:
 | 
			
		||||
      /* No frame */
 | 
			
		||||
      base_type = META_FRAME_TYPE_LAST;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (base_type == META_FRAME_TYPE_LAST)
 | 
			
		||||
    {
 | 
			
		||||
      /* can't add border if undecorated */
 | 
			
		||||
      return META_FRAME_TYPE_LAST;
 | 
			
		||||
    }
 | 
			
		||||
  else if (window->border_only && base_type != META_FRAME_TYPE_ATTACHED)
 | 
			
		||||
    {
 | 
			
		||||
      /* override base frame type */
 | 
			
		||||
      return META_FRAME_TYPE_BORDER;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      return base_type;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -195,6 +195,7 @@ typedef enum
 | 
			
		||||
  META_FRAME_TYPE_UTILITY,
 | 
			
		||||
  META_FRAME_TYPE_MENU,
 | 
			
		||||
  META_FRAME_TYPE_BORDER,
 | 
			
		||||
  META_FRAME_TYPE_ATTACHED,
 | 
			
		||||
  META_FRAME_TYPE_LAST
 | 
			
		||||
} MetaFrameType;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										86
									
								
								src/include/meta-shadow-factory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/include/meta-shadow-factory.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * MetaShadowFactory:
 | 
			
		||||
 *
 | 
			
		||||
 * Create and cache shadow textures for arbitrary window shapes
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2010 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_SHADOW_FACTORY_H__
 | 
			
		||||
#define __META_SHADOW_FACTORY_H__
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaShadowParams:
 | 
			
		||||
 * The #MetaShadowParams structure holds information about how to draw
 | 
			
		||||
 * a particular style of shadow.
 | 
			
		||||
 * @radius: the radius (gaussian standard deviation) of the shadow
 | 
			
		||||
 * @top_fade: if >= 0, the shadow doesn't extend above the top
 | 
			
		||||
 *  of the shape, and fades out over the given number of pixels
 | 
			
		||||
 * @x_offset: horizontal offset of the shadow with respect to the
 | 
			
		||||
 *  shape being shadowed, in pixels
 | 
			
		||||
 * @y_offset: vertical offset of the shadow with respect to the
 | 
			
		||||
 *  shape being shadowed, in pixels
 | 
			
		||||
 * @opacity: opacity of the shadow, from 0 to 255
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaShadowParams MetaShadowParams;
 | 
			
		||||
 | 
			
		||||
struct _MetaShadowParams
 | 
			
		||||
{
 | 
			
		||||
  int radius;
 | 
			
		||||
  int top_fade;
 | 
			
		||||
  int x_offset;
 | 
			
		||||
  int y_offset;
 | 
			
		||||
  guint8 opacity;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_SHADOW_FACTORY            (meta_shadow_factory_get_type ())
 | 
			
		||||
#define META_SHADOW_FACTORY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SHADOW_FACTORY, MetaShadowFactory))
 | 
			
		||||
#define META_SHADOW_FACTORY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_SHADOW_FACTORY, MetaShadowFactoryClass))
 | 
			
		||||
#define META_IS_SHADOW_FACTORY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHADOW_FACTORY))
 | 
			
		||||
#define META_IS_SHADOW_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_SHADOW_FACTORY))
 | 
			
		||||
#define META_SHADOW_FACTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_SHADOW_FACTORY, MetaShadowFactoryClass))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaShadowFactory:
 | 
			
		||||
 * #MetaShadowFactory is used to create window shadows. It caches shadows internally
 | 
			
		||||
 * so that multiple shadows created for the same shape with the same radius will
 | 
			
		||||
 * share the same MetaShadow.
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaShadowFactory      MetaShadowFactory;
 | 
			
		||||
typedef struct _MetaShadowFactoryClass MetaShadowFactoryClass;
 | 
			
		||||
 | 
			
		||||
MetaShadowFactory *meta_shadow_factory_get_default (void);
 | 
			
		||||
 | 
			
		||||
GType meta_shadow_factory_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaShadowFactory *meta_shadow_factory_new        (void);
 | 
			
		||||
 | 
			
		||||
void meta_shadow_factory_set_params (MetaShadowFactory *factory,
 | 
			
		||||
                                     const char        *class_name,
 | 
			
		||||
                                     gboolean           focused,
 | 
			
		||||
                                     MetaShadowParams  *params);
 | 
			
		||||
void meta_shadow_factory_get_params (MetaShadowFactory *factory,
 | 
			
		||||
                                     const char        *class_name,
 | 
			
		||||
                                     gboolean           focused,
 | 
			
		||||
                                     MetaShadowParams  *params);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_SHADOW_FACTORY_H__ */
 | 
			
		||||
@@ -28,6 +28,8 @@
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
gboolean meta_is_verbose  (void);
 | 
			
		||||
void     meta_set_verbose (gboolean setting);
 | 
			
		||||
gboolean meta_is_debugging (void);
 | 
			
		||||
@@ -91,6 +93,7 @@ guint meta_unsigned_long_hash  (gconstpointer v);
 | 
			
		||||
 | 
			
		||||
void meta_print_backtrace (void);
 | 
			
		||||
 | 
			
		||||
const char* meta_frame_type_to_string (MetaFrameType type);
 | 
			
		||||
const char* meta_gravity_to_string (int gravity);
 | 
			
		||||
 | 
			
		||||
#include <libintl.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,7 @@ GType meta_window_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaFrame *meta_window_get_frame (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_has_focus (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_appears_focused (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_shaded (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_override_redirect (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
 | 
			
		||||
@@ -119,6 +120,9 @@ void     meta_window_foreach_ancestor         (MetaWindow            *window,
 | 
			
		||||
                                               MetaWindowForeachFunc  func,
 | 
			
		||||
                                               void                  *user_data);
 | 
			
		||||
 | 
			
		||||
MetaMaximizeFlags meta_window_get_maximized (MetaWindow *window);
 | 
			
		||||
gboolean          meta_window_is_fullscreen (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_is_mapped (MetaWindow  *window);
 | 
			
		||||
gboolean meta_window_toplevel_is_mapped (MetaWindow  *window);
 | 
			
		||||
gboolean meta_window_get_icon_geometry (MetaWindow    *window,
 | 
			
		||||
@@ -143,4 +147,7 @@ const char *meta_window_get_client_machine (MetaWindow *window);
 | 
			
		||||
gboolean    meta_window_is_remote (MetaWindow *window);
 | 
			
		||||
gboolean    meta_window_is_modal (MetaWindow *window);
 | 
			
		||||
const char *meta_window_get_mutter_hints (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
MetaFrameType meta_window_get_frame_type (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
 * look out for.
 | 
			
		||||
 */
 | 
			
		||||
#define THEME_MAJOR_VERSION 3
 | 
			
		||||
#define THEME_MINOR_VERSION 1
 | 
			
		||||
#define THEME_MINOR_VERSION 2
 | 
			
		||||
#define THEME_VERSION (1000 * THEME_MAJOR_VERSION + THEME_MINOR_VERSION)
 | 
			
		||||
 | 
			
		||||
#define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml"
 | 
			
		||||
@@ -1257,7 +1257,8 @@ parse_toplevel_element (GMarkupParseContext  *context,
 | 
			
		||||
 | 
			
		||||
      type = meta_frame_type_from_string (type_name);
 | 
			
		||||
 | 
			
		||||
      if (type == META_FRAME_TYPE_LAST)
 | 
			
		||||
      if (type == META_FRAME_TYPE_LAST ||
 | 
			
		||||
          (type == META_FRAME_TYPE_ATTACHED && peek_required_version (info) < 3002))
 | 
			
		||||
        {
 | 
			
		||||
          set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
 | 
			
		||||
                     _("Unknown type \"%s\" on <%s> element"),
 | 
			
		||||
 
 | 
			
		||||
@@ -1189,7 +1189,6 @@ const char*           meta_frame_resize_to_string      (MetaFrameResize        r
 | 
			
		||||
MetaFrameFocus        meta_frame_focus_from_string     (const char            *str);
 | 
			
		||||
const char*           meta_frame_focus_to_string       (MetaFrameFocus         focus);
 | 
			
		||||
MetaFrameType         meta_frame_type_from_string      (const char            *str);
 | 
			
		||||
const char*           meta_frame_type_to_string        (MetaFrameType          type);
 | 
			
		||||
MetaGradientType      meta_gradient_type_from_string   (const char            *str);
 | 
			
		||||
const char*           meta_gradient_type_to_string     (MetaGradientType       type);
 | 
			
		||||
GtkStateType          meta_gtk_state_from_string       (const char            *str);
 | 
			
		||||
 
 | 
			
		||||
@@ -407,6 +407,10 @@ get_window_contents (MetaFrameType  type,
 | 
			
		||||
    case META_FRAME_TYPE_BORDER:
 | 
			
		||||
      *title = _("Border");
 | 
			
		||||
      return border_only_contents ();
 | 
			
		||||
 | 
			
		||||
    case META_FRAME_TYPE_ATTACHED:
 | 
			
		||||
      *title = _("Attached Modal Dialog");
 | 
			
		||||
      return dialog_contents ();
 | 
			
		||||
      
 | 
			
		||||
    case META_FRAME_TYPE_LAST:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
@@ -454,6 +458,9 @@ get_window_flags (MetaFrameType type)
 | 
			
		||||
 | 
			
		||||
    case META_FRAME_TYPE_BORDER:
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case META_FRAME_TYPE_ATTACHED:
 | 
			
		||||
      break;
 | 
			
		||||
      
 | 
			
		||||
    case META_FRAME_TYPE_LAST:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
 
 | 
			
		||||
@@ -4992,7 +4992,7 @@ meta_theme_validate (MetaTheme *theme,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < (int)META_FRAME_TYPE_LAST; i++)
 | 
			
		||||
    if (theme->style_sets_by_type[i] == NULL)
 | 
			
		||||
    if (i != (int)META_FRAME_TYPE_ATTACHED && theme->style_sets_by_type[i] == NULL)
 | 
			
		||||
      {
 | 
			
		||||
        g_set_error (error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
 | 
			
		||||
                     _("No frame style set for window type \"%s\" in theme \"%s\", add a <window type=\"%s\" style_set=\"whatever\"/> element"),
 | 
			
		||||
@@ -5074,7 +5074,10 @@ theme_get_style (MetaTheme     *theme,
 | 
			
		||||
 | 
			
		||||
  style_set = theme->style_sets_by_type[type];
 | 
			
		||||
 | 
			
		||||
  /* Right now the parser forces a style set for all types,
 | 
			
		||||
  if (style_set == NULL && type == META_FRAME_TYPE_ATTACHED)
 | 
			
		||||
    style_set = theme->style_sets_by_type[META_FRAME_TYPE_BORDER];
 | 
			
		||||
 | 
			
		||||
  /* Right now the parser forces a style set for all other types,
 | 
			
		||||
   * but this fallback code is here in case I take that out.
 | 
			
		||||
   */
 | 
			
		||||
  if (style_set == NULL)
 | 
			
		||||
@@ -6004,6 +6007,8 @@ meta_frame_type_from_string (const char *str)
 | 
			
		||||
    return META_FRAME_TYPE_MENU;
 | 
			
		||||
  else if (strcmp ("border", str) == 0)
 | 
			
		||||
    return META_FRAME_TYPE_BORDER;
 | 
			
		||||
  else if (strcmp ("attached", str) == 0)
 | 
			
		||||
    return META_FRAME_TYPE_ATTACHED;
 | 
			
		||||
#if 0
 | 
			
		||||
  else if (strcmp ("toolbar", str) == 0)
 | 
			
		||||
    return META_FRAME_TYPE_TOOLBAR;
 | 
			
		||||
@@ -6012,6 +6017,14 @@ meta_frame_type_from_string (const char *str)
 | 
			
		||||
    return META_FRAME_TYPE_LAST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_frame_type_to_string:
 | 
			
		||||
 *
 | 
			
		||||
 * Converts a frame type enum value to the name string that would
 | 
			
		||||
 * appear in the theme definition file.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the string value
 | 
			
		||||
 */
 | 
			
		||||
const char*
 | 
			
		||||
meta_frame_type_to_string (MetaFrameType type)
 | 
			
		||||
{
 | 
			
		||||
@@ -6029,6 +6042,8 @@ meta_frame_type_to_string (MetaFrameType type)
 | 
			
		||||
      return "menu";
 | 
			
		||||
    case META_FRAME_TYPE_BORDER:
 | 
			
		||||
      return "border";
 | 
			
		||||
    case META_FRAME_TYPE_ATTACHED:
 | 
			
		||||
      return "attached";
 | 
			
		||||
#if 0
 | 
			
		||||
    case META_FRAME_TYPE_TOOLBAR:
 | 
			
		||||
      return "toolbar";
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user