[mutter/meego-1.0: 6/30] [MutterShadow] An API allowing plugins to generate their custom shadows



commit 094cfc5eaa5db02d17bd532adff6c5281188a197
Author: Tomas Frydrych <tf linux intel com>
Date:   Thu Nov 26 12:54:33 2009 +0000

    [MutterShadow] An API allowing plugins to generate their custom shadows
    
    The commmit adds new vfunction get_shadow() to MutterPluginClass, allowing
    plugins to replace the stock gaussian shadow with a custom actor. The
    shadow is encapsulated in a MutterShadow structure that contains the custom
    actor, and four points of attachment describing the position and size of the
    shadow relative to the window.
    
    In addition, this commit replaces the MutterWindow::no-frame boolean property
    with shape-type emum property which allows to force and disable the shadow
    on a given window, or leave the compositor to decide.
    
    The plugin API version number is bumped by one.

 configure.in                                 |    2 +-
 src/Makefile.am                              |    6 +-
 src/compositor/mutter-plugin-manager.c       |   27 ++++++
 src/compositor/mutter-plugin-manager.h       |    3 +
 src/compositor/{shadow.c => mutter-shadow.c} |   35 ++++++--
 src/compositor/mutter-window.c               |  119 +++++++++++++++++---------
 src/compositor/shadow.h                      |    9 --
 src/include/mutter-plugin.h                  |    4 +
 src/include/mutter-shadow.h                  |   37 ++++++++
 9 files changed, 181 insertions(+), 61 deletions(-)
---
diff --git a/configure.in b/configure.in
index 9f07d28..632b7f7 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ m4_define([mutter_micro_version], [1])
 m4_define([mutter_version],
           [mutter_major_version.mutter_minor_version.mutter_micro_version])
 
-m4_define([mutter_plugin_api_version], [2])
+m4_define([mutter_plugin_api_version], [3])
 
 AC_INIT([mutter], [mutter_version],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
diff --git a/src/Makefile.am b/src/Makefile.am
index a3d892d..ae17abc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,8 +34,7 @@ mutter_SOURCES= 				\
 	compositor/mutter-window-private.h	\
 	compositor/mutter-window-group.c	\
 	compositor/mutter-window-group.h	\
-	compositor/shadow.c			\
-	compositor/shadow.h			\
+	compositor/mutter-shadow.c		\
 	compositor/mutter-shaped-texture.h	\
 	compositor/tidy/tidy-texture-frame.c	\
 	compositor/tidy/tidy-texture-frame.h	\
@@ -170,7 +169,8 @@ libmutterinclude_base_headers =		\
 	include/group.h				\
 	include/keybindings.h			\
 	include/mutter-plugin.h			\
-	include/mutter-window.h
+	include/mutter-window.h			\
+	include/mutter-shadow.h
 
 # Excluded from scanning for introspection but installed
 # preview-widget.h: only part of libmutter-private
diff --git a/src/compositor/mutter-plugin-manager.c b/src/compositor/mutter-plugin-manager.c
index 26e6697..c8d3d86 100644
--- a/src/compositor/mutter-plugin-manager.c
+++ b/src/compositor/mutter-plugin-manager.c
@@ -650,3 +650,30 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
 
   return FALSE;
 }
+
+MutterShadow *
+mutter_plugin_manager_get_shadow (MutterPluginManager *mgr,
+                                  MutterWindow        *window)
+{
+  GList *l;
+
+  if (!mgr)
+    return NULL;
+
+  l = mgr->plugins;
+
+  while (l)
+    {
+      MutterPlugin      *plugin = l->data;
+      MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
+
+      if (klass->get_shadow)
+        {
+          return klass->get_shadow (plugin, window);
+        }
+
+      l = l->next;
+    }
+
+  return NULL;
+}
diff --git a/src/compositor/mutter-plugin-manager.h b/src/compositor/mutter-plugin-manager.h
index e7b75de..690e61b 100644
--- a/src/compositor/mutter-plugin-manager.h
+++ b/src/compositor/mutter-plugin-manager.h
@@ -60,4 +60,7 @@ gboolean mutter_plugin_manager_switch_workspace (MutterPluginManager *mgr,
 gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
 					      XEvent *xev);
 
+MutterShadow * mutter_plugin_manager_get_shadow (MutterPluginManager *mgr,
+                                                 MutterWindow *window);
+
 #endif
diff --git a/src/compositor/shadow.c b/src/compositor/mutter-shadow.c
similarity index 91%
rename from src/compositor/shadow.c
rename to src/compositor/mutter-shadow.c
index b204440..5edde1e 100644
--- a/src/compositor/shadow.c
+++ b/src/compositor/mutter-shadow.c
@@ -17,12 +17,34 @@
 #define TILE_WIDTH  (3*MAX_TILE_SZ)
 #define TILE_HEIGHT (3*MAX_TILE_SZ)
 
+MutterShadow *
+mutter_shadow_new (void)
+{
+  return g_new0 (MutterShadow, 1);
+}
+
+void
+mutter_shadow_destroy (MutterShadow *shadow)
+{
+  clutter_actor_destroy (shadow->actor);
+  g_free (shadow);
+}
+
 static unsigned char* shadow_gaussian_make_tile (void);
 
-ClutterActor *
-mutter_create_shadow_frame (MetaCompositor *compositor)
+MutterShadow *
+mutter_shadow_create_for_window (MetaCompositor *compositor, MutterWindow *mcw)
 {
-  ClutterActor *frame;
+  ClutterActor   *frame;
+  MutterShadow   *shadow;
+  MetaWindow     *mw = mutter_window_get_meta_window (mcw);
+  MetaScreen	 *screen = meta_window_get_screen (mw);
+  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+
+  if ((shadow = mutter_plugin_manager_get_shadow (info->plugin_mgr, mcw)))
+    return shadow;
+
+  shadow = mutter_shadow_new ();
 
   if (!compositor->shadow_src)
     {
@@ -50,10 +72,11 @@ mutter_create_shadow_frame (MetaCompositor *compositor)
                                   MAX_TILE_SZ,
                                   MAX_TILE_SZ);
 
-  clutter_actor_set_position (frame,
-                              SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
+  shadow->actor       = frame;
+  shadow->attach_left = SHADOW_OFFSET_X;
+  shadow->attach_top  = SHADOW_OFFSET_Y;
 
-  return frame;
+  return shadow;
 }
 
 typedef struct GaussianMap
diff --git a/src/compositor/mutter-window.c b/src/compositor/mutter-window.c
index bca95dd..4d67f7b 100644
--- a/src/compositor/mutter-window.c
+++ b/src/compositor/mutter-window.c
@@ -19,7 +19,8 @@
 #include "compositor-private.h"
 #include "mutter-shaped-texture.h"
 #include "mutter-window-private.h"
-#include "shadow.h"
+#include "mutter-shadow.h"
+#include "mutter-enum-types.h"
 #include "tidy/tidy-texture-frame.h"
 
 struct _MutterWindowPrivate
@@ -31,7 +32,7 @@ struct _MutterWindowPrivate
   MetaScreen       *screen;
 
   ClutterActor     *actor;
-  ClutterActor     *shadow;
+  MutterShadow     *shadow;
   Pixmap            back_pixmap;
 
   MetaCompWindowType  type;
@@ -71,9 +72,9 @@ struct _MutterWindowPrivate
 
   guint		    needs_destroy	   : 1;
 
-  guint             no_shadow              : 1;
-
   guint             no_more_x_calls        : 1;
+
+  MutterShadowType  shadow_type;
 };
 
 enum
@@ -82,7 +83,7 @@ enum
   PROP_MCW_META_SCREEN,
   PROP_MCW_X_WINDOW,
   PROP_MCW_X_WINDOW_ATTRIBUTES,
-  PROP_MCW_NO_SHADOW,
+  PROP_MCW_SHADOW_TYPE,
 };
 
 enum
@@ -215,14 +216,15 @@ mutter_window_class_init (MutterWindowClass *klass)
                                    PROP_MCW_X_WINDOW_ATTRIBUTES,
                                    pspec);
 
-  pspec = g_param_spec_boolean ("no-shadow",
-                                "No shadow",
-                                "Do not add shaddow to this window",
-                                FALSE,
-                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+  pspec = g_param_spec_enum ("shadow-type",
+                             "Shadow Type",
+                             "Whether this window should have shadow",
+                             MUTTER_TYPE_SHADOW_TYPE,
+                             MUTTER_SHADOW_AUTOMATIC,
+                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
 
   g_object_class_install_property (object_class,
-                                   PROP_MCW_NO_SHADOW,
+                                   PROP_MCW_SHADOW_TYPE,
                                    pspec);
 
   signals[WINDOW_DESTROYED] =
@@ -308,13 +310,7 @@ mutter_meta_window_decorated_notify (MetaWindow *mw,
 
   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);
-
+      mutter_shadow_destroy (priv->shadow);
       priv->shadow = NULL;
     }
 
@@ -362,9 +358,17 @@ mutter_window_constructed (GObject *object)
 
   if (mutter_window_has_shadow (self))
     {
-      priv->shadow = mutter_create_shadow_frame (compositor);
+      priv->shadow = mutter_shadow_create_for_window (compositor, self);
 
-      clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
+      if (priv->shadow)
+        {
+          clutter_actor_set_position (priv->shadow->actor,
+                                      priv->shadow->attach_left,
+                                      priv->shadow->attach_top);
+
+          clutter_container_add_actor (CLUTTER_CONTAINER (self),
+                                       priv->shadow->actor);
+        }
     }
 
   if (!priv->actor)
@@ -422,6 +426,9 @@ mutter_window_dispose (GObject *object)
   xdisplay = meta_display_get_xdisplay (display);
   info     = meta_screen_get_compositor_data (screen);
 
+  if (priv->shadow)
+    mutter_shadow_destroy (priv->shadow);
+
   mutter_window_detach (self);
 
   mutter_window_clear_shape_region (self);
@@ -482,23 +489,28 @@ mutter_window_set_property (GObject      *object,
     case PROP_MCW_X_WINDOW_ATTRIBUTES:
       priv->attrs = *((XWindowAttributes*)g_value_get_boxed (value));
       break;
-    case PROP_MCW_NO_SHADOW:
+    case PROP_MCW_SHADOW_TYPE:
       {
-        gboolean oldv = priv->no_shadow ? TRUE : FALSE;
-        gboolean newv = g_value_get_boolean (value);
+        MutterShadowType oldv = priv->shadow_type;
+        MutterShadowType newv = g_value_get_enum (value);
 
         if (oldv == newv)
           return;
 
-        priv->no_shadow = newv;
+        /*
+         * Setting the stored value to the new type at this point means that
+         * mutter_window_has_shadow() will do the right thing for us in the
+         * ifs below.
+         */
+        priv->shadow_type = newv;
 
-        if (newv && priv->shadow)
+        if (priv->shadow && !mutter_window_has_shadow (self))
           {
-            clutter_container_remove_actor (CLUTTER_CONTAINER (object),
-                                            priv->shadow);
+            mutter_shadow_destroy (priv->shadow);
+
             priv->shadow = NULL;
           }
-        else if (!newv && !priv->shadow && mutter_window_has_shadow (self))
+        else if (!priv->shadow && mutter_window_has_shadow (self))
           {
             gfloat       w, h;
             MetaDisplay *display = meta_screen_get_display (priv->screen);
@@ -508,11 +520,23 @@ mutter_window_set_property (GObject      *object,
 
             clutter_actor_get_size (CLUTTER_ACTOR (self), &w, &h);
 
-            priv->shadow = mutter_create_shadow_frame (compositor);
-
-            clutter_actor_set_size (priv->shadow, w, h);
-
-            clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
+            priv->shadow = mutter_shadow_create_for_window (compositor, self);
+
+            if (priv->shadow)
+              {
+                clutter_actor_set_position (priv->shadow->actor,
+                                            priv->shadow->attach_left,
+                                            priv->shadow->attach_top);
+                clutter_actor_set_size (priv->shadow->actor,
+                                        w + priv->shadow->attach_right -
+                                        priv->shadow->attach_left,
+                                        h + priv->shadow->attach_bottom -
+                                        priv->shadow->attach_top);
+
+                clutter_container_add_actor (CLUTTER_CONTAINER (self),
+                                             priv->shadow->actor);
+                clutter_actor_lower (priv->shadow->actor, priv->actor);
+              }
           }
       }
       break;
@@ -544,8 +568,8 @@ mutter_window_get_property (GObject      *object,
     case PROP_MCW_X_WINDOW_ATTRIBUTES:
       g_value_set_boxed (value, &priv->attrs);
       break;
-    case PROP_MCW_NO_SHADOW:
-      g_value_set_boolean (value, priv->no_shadow);
+    case PROP_MCW_SHADOW_TYPE:
+      g_value_set_enum (value, priv->shadow_type);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -584,9 +608,12 @@ mutter_window_has_shadow (MutterWindow *self)
 {
   MutterWindowPrivate * priv = self->priv;
 
-  if (priv->no_shadow)
+  if (priv->shadow_type == MUTTER_SHADOW_NEVER)
     return FALSE;
 
+  if (priv->shadow_type == MUTTER_SHADOW_ALWAYS)
+    return TRUE;
+
   /*
    * Always put a shadow around windows with a frame - This should override
    * the restriction about not putting a shadow around shaped windows
@@ -1458,7 +1485,7 @@ mutter_window_set_visible_region_beneath (MutterWindow *self,
        * the shadow is completely obscured and doesn't need to be drawn
        * at all.
        */
-      clutter_actor_get_allocation_box (priv->shadow, &box);
+      clutter_actor_get_allocation_box (priv->shadow->actor, &box);
 
       shadow_rect.x = roundf (box.x1);
       shadow_rect.y = roundf (box.y1);
@@ -1467,8 +1494,10 @@ mutter_window_set_visible_region_beneath (MutterWindow *self,
 
       overlap = gdk_region_rect_in (beneath_region, &shadow_rect);
 
-      tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow),
-                                          overlap != GDK_OVERLAP_RECTANGLE_OUT);
+      if (TIDY_IS_TEXTURE_FRAME (priv->shadow->actor))
+        tidy_texture_frame_set_needs_paint (
+                                      TIDY_TEXTURE_FRAME (priv->shadow->actor),
+                                      overlap != GDK_OVERLAP_RECTANGLE_OUT);
     }
 }
 
@@ -1486,8 +1515,10 @@ mutter_window_reset_visible_regions (MutterWindow *self)
 
   mutter_shaped_texture_set_clip_region (MUTTER_SHAPED_TEXTURE (priv->actor),
                                          NULL);
-  if (priv->shadow)
-    tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow), TRUE);
+  if (priv->shadow && TIDY_IS_TEXTURE_FRAME (priv->shadow->actor))
+    tidy_texture_frame_set_needs_paint (
+                                     TIDY_TEXTURE_FRAME (priv->shadow->actor),
+                                     TRUE);
 }
 
 static void
@@ -1567,7 +1598,11 @@ check_needs_repair (MutterWindow *self)
                     NULL);
 
       if (priv->shadow)
-        clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
+        clutter_actor_set_size (priv->shadow->actor,
+                                pxm_width + priv->shadow->attach_right -
+                                priv->shadow->attach_left,
+                                pxm_height + priv->shadow->attach_bottom -
+                                priv->shadow->attach_top);
 
       mutter_window_update_bounding_region (self, pxm_width, pxm_height);
 
diff --git a/src/include/mutter-plugin.h b/src/include/mutter-plugin.h
index 282b272..cab678c 100644
--- a/src/include/mutter-plugin.h
+++ b/src/include/mutter-plugin.h
@@ -27,6 +27,7 @@
 #include "types.h"
 #include "compositor.h"
 #include "compositor-mutter.h"
+#include "mutter-shadow.h"
 
 #include <clutter/clutter.h>
 #include <X11/extensions/Xfixes.h>
@@ -115,6 +116,9 @@ struct _MutterPluginClass
                              XEvent             *event);
 
   const MutterPluginInfo * (*plugin_info) (MutterPlugin *plugin);
+
+  MutterShadow           * (*get_shadow) (MutterPlugin *plugin,
+                                          MutterWindow *window);
 };
 
 struct _MutterPluginInfo
diff --git a/src/include/mutter-shadow.h b/src/include/mutter-shadow.h
new file mode 100644
index 0000000..92055e8
--- /dev/null
+++ b/src/include/mutter-shadow.h
@@ -0,0 +1,37 @@
+#ifndef MUTTER_SHADOW_H
+#define MUTTER_SHADOW_H
+
+#include <clutter/clutter.h>
+#include "compositor.h"
+
+/**
+ * MutterShadowType:
+ * @MUTTER_SHADOW_AUTOMATIC: The compositor decides whether window should
+ * have shadow based on window type
+ * @MUTTER_SHADOW_ALWAYS: The window should have shadow
+ * @MUTTER_SHADOW_NEWER:  The window should not have a shadow
+ */
+typedef enum
+{
+  MUTTER_SHADOW_AUTOMATIC,
+  MUTTER_SHADOW_ALWAYS,
+  MUTTER_SHADOW_NEVER
+} MutterShadowType;
+
+typedef struct _MutterShadow MutterShadow;
+
+struct _MutterShadow
+{
+  ClutterActor *actor;
+  gint          attach_left;
+  gint          attach_top;
+  gint          attach_right;
+  gint          attach_bottom;
+};
+
+MutterShadow * mutter_shadow_new               (void);
+void           mutter_shadow_destroy           (MutterShadow *shadow);
+MutterShadow * mutter_shadow_create_for_window (MetaCompositor *compositor,
+                                                MutterWindow   *window);
+
+#endif /* MUTTER_SHADOW_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]