[Xfce4-commits] <xfce4-panel:nick/background> Add more code to support background colors and images.

Nick Schermer noreply at xfce.org
Sun May 9 14:08:02 CEST 2010


Updating branch refs/heads/nick/background
         to beecbfba2c486a2eda266ef82eafd7d8eb26eae2 (commit)
       from 4a1ea67fde82d0db94ba3c2dddeaa75e2691dab5 (commit)

commit beecbfba2c486a2eda266ef82eafd7d8eb26eae2
Author: Nick Schermer <nick at xfce.org>
Date:   Sun May 9 14:06:04 2010 +0200

    Add more code to support background colors and images.

 common/panel-dbus.h                  |    3 +
 libxfce4panel/xfce-panel-macros-46.h |   56 ++++++--
 panel/panel-application.c            |    1 +
 panel/panel-base-window.c            |  262 ++++++++++++++++++++++++++++------
 panel/panel-base-window.h            |    5 +-
 panel/panel-plugin-external-46.c     |  216 ++++++++++++++++++----------
 panel/panel-plugin-external-46.h     |    8 +-
 panel/panel-plugin-external.c        |   59 ++++++++
 panel/panel-plugin-external.h        |    6 +
 panel/panel-preferences-dialog.c     |  101 ++++++++++++--
 panel/panel-preferences-dialog.glade |    1 -
 panel/panel-window.c                 |   27 +++-
 wrapper/main.c                       |   20 ++-
 wrapper/wrapper-plug.c               |   73 +++++++++-
 wrapper/wrapper-plug.h               |    6 +
 15 files changed, 681 insertions(+), 163 deletions(-)

diff --git a/common/panel-dbus.h b/common/panel-dbus.h
index 611456c..32d8c39 100644
--- a/common/panel-dbus.h
+++ b/common/panel-dbus.h
@@ -38,6 +38,9 @@
 #define SIGNAL_WRAPPER_SET_SENSITIVE    "i"
 #define SIGNAL_WRAPPER_BACKGROUND_ALPHA "j"
 #define SIGNAL_WRAPPER_QUIT             "k"
+#define SIGNAL_WRAPPER_BACKGROUND_COLOR "l"
+#define SIGNAL_WRAPPER_BACKGROUND_IMAGE "m"
+#define SIGNAL_WRAPPER_BACKGROUND_UNSET "n"
 
 /* special types for dbus communication */
 #define PANEL_TYPE_DBUS_SET_MESSAGE \
diff --git a/libxfce4panel/xfce-panel-macros-46.h b/libxfce4panel/xfce-panel-macros-46.h
index 2a6f3e5..82644d0 100644
--- a/libxfce4panel/xfce-panel-macros-46.h
+++ b/libxfce4panel/xfce-panel-macros-46.h
@@ -50,7 +50,9 @@ enum /*< skip >*/
   PANEL_CLIENT_EVENT_SET_SIZE,
   PANEL_CLIENT_EVENT_SHOW_ABOUT,
   PANEL_CLIENT_EVENT_SHOW_CONFIGURE,
-  PANEL_CLIENT_EVENT_QUIT
+  PANEL_CLIENT_EVENT_QUIT,
+  PANEL_CLIENT_EVENT_SET_BG_COLOR,
+  PANEL_CLIENT_EVENT_UNSET_BG
 };
 
 /*< private >*/
@@ -277,6 +279,8 @@ enum /*< skip >*/
   static GdkAtom  _xpp_atom = GDK_NONE; \
   static gdouble  _xpp_alpha = 1.00; \
   static gboolean _xpp_composited = FALSE; \
+  static guint    _xpp_bg_style = 0; \
+  static GdkColor _xpp_bg_color = { 0, }; \
   \
   static void \
   _xpp_quit_main_loop (void) \
@@ -357,6 +361,19 @@ enum /*< skip >*/
             _xpp_quit_main_loop (); \
             break; \
             \
+          case PANEL_CLIENT_EVENT_SET_BG_COLOR: \
+            _xpp_bg_color.red = event->data.s[1]; \
+            _xpp_bg_color.green = event->data.s[2]; \
+            _xpp_bg_color.blue = event->data.s[3]; \
+            _xpp_bg_style = 1; \
+            gtk_widget_queue_draw (plug); \
+            break; \
+            \
+          case PANEL_CLIENT_EVENT_UNSET_BG: \
+            _xpp_bg_style = 0; \
+            gtk_widget_queue_draw (plug); \
+            break; \
+            \
           default: \
             g_warning ("Received unknow client event %d", message); \
             break; \
@@ -419,25 +436,36 @@ enum /*< skip >*/
   { \
     cairo_t  *cr; \
     GdkColor *color; \
+    gdouble   real_alpha = _xpp_composited ? _xpp_alpha : 1.00; \
     \
-    if (_xpp_composited \
-        && GTK_WIDGET_DRAWABLE (plug) \
-        && _xpp_alpha < 1.00) \
+    if (GTK_WIDGET_DRAWABLE (plug) \
+        && (real_alpha < 1.00 || _xpp_bg_style > 0)) \
       { \
         cr = gdk_cairo_create (gtk_widget_get_window (plug)); \
         cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); \
         \
-        color = &(gtk_widget_get_style (plug)->bg[GTK_STATE_NORMAL]); \
-        cairo_set_source_rgba (cr, \
-                               color->red / 65535.00, \
-                               color->green / 65535.00, \
-                               color->blue / 65535.00, \
-                               _xpp_alpha); \
-        \
-        cairo_rectangle (cr, event->area.x, event->area.y, \
-                         event->area.width, event->area.height); \
+        if (G_UNLIKELY (_xpp_bg_style == 2)) \
+          { \
+          } \
+        else \
+          { \
+            if (G_LIKELY (_xpp_bg_style == 0)) \
+              color = &(gtk_widget_get_style (plug)->bg[GTK_STATE_NORMAL]); \
+            else \
+              color = &_xpp_bg_color; \
+            \
+            cairo_set_source_rgba (cr, \
+                                   color->red / 65535.00, \
+                                   color->green / 65535.00, \
+                                   color->blue / 65535.00, \
+                                   real_alpha); \
+            \
+            cairo_rectangle (cr, event->area.x, event->area.y, \
+                             event->area.width, event->area.height); \
+            \
+            cairo_fill (cr); \
+          } \
         \
-        cairo_fill (cr); \
         cairo_destroy (cr); \
       } \
     \
diff --git a/panel/panel-application.c b/panel/panel-application.c
index 1ef2c27..13c6d15 100644
--- a/panel/panel-application.c
+++ b/panel/panel-application.c
@@ -270,6 +270,7 @@ panel_application_xfconf_window_bindings (PanelApplication *application,
     { "background-alpha", G_TYPE_UINT },
     { "background-style", G_TYPE_UINT },
     { "background-color", GDK_TYPE_COLOR },
+    { "background-image", G_TYPE_STRING },
     { "output-name", G_TYPE_STRING },
     { "position", G_TYPE_STRING },
     { "disable-struts", G_TYPE_BOOLEAN },
diff --git a/panel/panel-base-window.c b/panel/panel-base-window.c
index d085aac..4ff9d9d 100644
--- a/panel/panel-base-window.c
+++ b/panel/panel-base-window.c
@@ -61,8 +61,14 @@ static void     panel_base_window_update_provider_info        (GtkWidget
                                                                gpointer              user_data);
 static gboolean panel_base_window_active_timeout              (gpointer              user_data);
 static void     panel_base_window_active_timeout_destroyed    (gpointer              user_data);
+static void     panel_base_window_set_plugin_data             (PanelBaseWindow      *window,
+                                                               GtkCallback           func);
 static void     panel_base_window_set_plugin_background_alpha (GtkWidget            *widget,
                                                                gpointer              user_data);
+static void     panel_base_window_set_plugin_background_color (GtkWidget            *widget,
+                                                               gpointer              user_data);
+static void     panel_base_window_set_plugin_background_image (GtkWidget            *widget,
+                                                               gpointer              user_data);
 
 
 
@@ -76,23 +82,23 @@ enum
   PROP_ACTIVE,
   PROP_COMPOSITED,
   PROP_BACKGROUND_STYLE,
-  PROP_BACKGROUND_COLOR
+  PROP_BACKGROUND_COLOR,
+  PROP_BACKGROUND_IMAGE
 };
 
 struct _PanelBaseWindowPrivate
 {
-  PanelBorders borders;
+  PanelBorders     borders;
 
-  /* background options */
-  PanelBgStyle bg_style;
-  GdkColor     bg_color;
+  /* background image cache */
+  cairo_pattern_t *bg_image_cache;
 
   /* transparency settings */
-  gdouble      enter_opacity;
-  gdouble      leave_opacity;
+  gdouble          enter_opacity;
+  gdouble          leave_opacity;
 
   /* active window timeout id */
-  guint        active_timeout_id;
+  guint            active_timeout_id;
 };
 
 
@@ -159,6 +165,13 @@ panel_base_window_class_init (PanelBaseWindowClass *klass)
                                                        EXO_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
+                                   PROP_BACKGROUND_IMAGE,
+                                   g_param_spec_string ("background-image",
+                                                        NULL, NULL,
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
                                    PROP_BORDERS,
                                    g_param_spec_uint ("borders",
                                                       NULL, NULL,
@@ -190,14 +203,16 @@ panel_base_window_init (PanelBaseWindow *window)
   window->is_composited = FALSE;
   window->background_alpha = 1.00;
 
-  window->priv->bg_style = PANEL_BG_STYLE_NONE;
+  window->background_style = PANEL_BG_STYLE_NONE;
+  window->background_image = NULL;
+  window->background_color = NULL;
+  window->priv->bg_image_cache = NULL;
 
   window->priv->enter_opacity = 1.00;
   window->priv->leave_opacity = 1.00;
   window->priv->borders = PANEL_BORDER_NONE;
   window->priv->active_timeout_id = 0;
 
-  /* set colormap */
   panel_base_window_composited_changed (GTK_WIDGET (window));
 }
 
@@ -227,11 +242,15 @@ panel_base_window_get_property (GObject    *object,
       break;
 
     case PROP_BACKGROUND_STYLE:
-      g_value_set_uint (value, priv->bg_style);
+      g_value_set_uint (value, window->background_style);
       break;
 
     case PROP_BACKGROUND_COLOR:
-      g_value_set_boxed (value, &priv->bg_color);
+      g_value_set_boxed (value, window->background_color);
+      break;
+
+    case PROP_BACKGROUND_IMAGE:
+      g_value_set_string (value, window->background_image);
       break;
 
     case PROP_BORDERS:
@@ -262,8 +281,7 @@ panel_base_window_set_property (GObject      *object,
 {
   PanelBaseWindow        *window = PANEL_BASE_WINDOW (object);
   PanelBaseWindowPrivate *priv = window->priv;
-  GtkWidget              *itembar;
-  GdkColor               *bg_color;
+  PanelBgStyle            bg_style;
 
   switch (prop_id)
     {
@@ -286,21 +304,72 @@ panel_base_window_set_property (GObject      *object,
         gtk_widget_queue_draw (GTK_WIDGET (object));
 
       /* send the new background alpha to the external plugins */
-      itembar = gtk_bin_get_child (GTK_BIN (window));
-      if (G_LIKELY (itembar != NULL))
-        gtk_container_foreach (GTK_CONTAINER (itembar),
-            panel_base_window_set_plugin_background_alpha, window);
+      panel_base_window_set_plugin_data (window,
+          panel_base_window_set_plugin_background_alpha);
       break;
 
     case PROP_BACKGROUND_STYLE:
-      priv->bg_style = g_value_get_uint (value);
+      bg_style = g_value_get_uint (value);
+      if (window->background_style != bg_style)
+        {
+          window->background_style = bg_style;
+
+          if (priv->bg_image_cache != NULL)
+            {
+              /* destroy old image cache */
+              cairo_pattern_destroy (priv->bg_image_cache);
+              priv->bg_image_cache = NULL;
+            }
+
+          /* send information to external plugins */
+          if (window->background_style == PANEL_BG_STYLE_IMAGE
+              && window->background_image != NULL)
+            {
+              panel_base_window_set_plugin_data (window,
+                  panel_base_window_set_plugin_background_image);
+            }
+          else if (window->background_style == PANEL_BG_STYLE_NONE
+                   || (window->background_style == PANEL_BG_STYLE_COLOR
+                       && window->background_color != NULL))
+            {
+              panel_base_window_set_plugin_data (window,
+                  panel_base_window_set_plugin_background_color);
+            }
+
+          /* resize to update border size too */
+          gtk_widget_queue_resize (GTK_WIDGET (window));
+        }
       break;
 
     case PROP_BACKGROUND_COLOR:
-      bg_color = g_value_get_boxed (value);
-      if (bg_color != NULL && !gdk_color_equal (&priv->bg_color, bg_color))
+      if (window->background_color != NULL)
+        gdk_color_free (window->background_color);
+      window->background_color = g_value_dup_boxed (value);
+
+      if (window->background_style == PANEL_BG_STYLE_COLOR)
         {
-          priv->bg_color = *bg_color;
+          panel_base_window_set_plugin_data (window,
+              panel_base_window_set_plugin_background_color);
+          gtk_widget_queue_draw (GTK_WIDGET (window));
+        }
+      break;
+
+    case PROP_BACKGROUND_IMAGE:
+      /* store new filename */
+      g_free (window->background_image);
+      window->background_image = g_value_dup_string (value);
+
+      /* drop old cache */
+      if (priv->bg_image_cache != NULL)
+        {
+          cairo_pattern_destroy (priv->bg_image_cache);
+          priv->bg_image_cache = NULL;
+        }
+
+      if (window->background_style == PANEL_BG_STYLE_IMAGE)
+        {
+          panel_base_window_set_plugin_data (window,
+              panel_base_window_set_plugin_background_image);
           gtk_widget_queue_draw (GTK_WIDGET (window));
         }
       break;
@@ -344,11 +413,18 @@ panel_base_window_set_property (GObject      *object,
 static void
 panel_base_window_finalize (GObject *object)
 {
-  PanelBaseWindowPrivate *priv = PANEL_BASE_WINDOW (object)->priv;
+  PanelBaseWindow *window = PANEL_BASE_WINDOW (object);
 
   /* stop running marching ants timeout */
-  if (priv->active_timeout_id != 0)
-    g_source_remove (priv->active_timeout_id);
+  if (window->priv->active_timeout_id != 0)
+    g_source_remove (window->priv->active_timeout_id);
+
+  /* release bg image data */
+  g_free (window->background_image);
+  if (window->priv->bg_image_cache != NULL)
+    cairo_pattern_destroy (window->priv->bg_image_cache);
+  if (window->background_color != NULL)
+    gdk_color_free (window->background_color);
 
   (*G_OBJECT_CLASS (panel_base_window_parent_class)->finalize) (object);
 }
@@ -369,18 +445,14 @@ panel_base_window_expose_event (GtkWidget      *widget,
   const gdouble           dashes[] = { 4.00, 4.00 };
   GTimeVal                timeval;
   gboolean                result;
+  GdkPixbuf              *pixbuf;
+  GError                 *error = NULL;
 
   result = (*GTK_WIDGET_CLASS (panel_base_window_parent_class)->expose_event) (widget, event);
 
   if (!GTK_WIDGET_DRAWABLE (widget))
     return result;
 
-  /* get the background color */
-  if (priv->bg_style == PANEL_BG_STYLE_COLOR)
-    color = &priv->bg_color;
-  else
-    color = &(widget->style->bg[GTK_STATE_NORMAL]);
-
   /* create cairo context and set some default properties */
   cr = gdk_cairo_create (widget->window);
   panel_return_val_if_fail (cr != NULL, result);
@@ -388,27 +460,73 @@ panel_base_window_expose_event (GtkWidget      *widget,
   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
   cairo_set_line_width (cr, 1.00);
 
-  /* clip the drawing area */
+  /* set rectangle to clip the drawing area */
   gdk_cairo_rectangle (cr, &event->area);
 
-  /* get background alpha */
-  alpha = window->is_composited ? window->background_alpha : 1.00;
-
-  /* only do something with the background when compositing is enabled */
-  if (G_UNLIKELY (alpha < 1.00
-      || priv->bg_style != PANEL_BG_STYLE_NONE))
+  if (window->background_style == PANEL_BG_STYLE_IMAGE)
     {
-      /* clip the drawing area, but preserve the rectangle */
-      cairo_clip_preserve (cr);
+      /* clip the drawing area */
+      cairo_clip (cr);
+
+      if (G_LIKELY (priv->bg_image_cache != NULL))
+        {
+          cairo_set_source (cr, priv->bg_image_cache);
+          cairo_paint (cr);
+        }
+      else if (window->background_image != NULL)
+        {
+          /* load the image in a pixbuf */
+          pixbuf = gdk_pixbuf_new_from_file (window->background_image, &error);
+
+          if (G_LIKELY (pixbuf != NULL))
+            {
+              gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+              g_object_unref (G_OBJECT (pixbuf));
+
+              priv->bg_image_cache = cairo_get_source (cr);
+              cairo_pattern_reference (priv->bg_image_cache);
+              cairo_pattern_set_extend (priv->bg_image_cache, CAIRO_EXTEND_REPEAT);
+              cairo_paint (cr);
+            }
+          else
+            {
+              /* print error message */
+              g_warning ("Background image disabled, \"%s\" could not be loaded: %s",
+                         window->background_image, error != NULL ? error->message : "No error");
+              g_error_free (error);
 
-      /* make the background transparent */
-      panel_util_set_source_rgba (cr, color, alpha);
-      cairo_fill (cr);
+              /* disable background image mode */
+              window->background_style = PANEL_BG_STYLE_NONE;
+            }
+        }
     }
   else
     {
-      /* clip the drawing area */
-      cairo_clip (cr);
+      /* get background alpha */
+      alpha = window->is_composited ? window->background_alpha : 1.00;
+
+      /* get the background color */
+      if (window->background_style == PANEL_BG_STYLE_COLOR)
+        color = window->background_color;
+      else
+        color = &(widget->style->bg[GTK_STATE_NORMAL]);
+
+      /* only do something with the background when compositing is enabled */
+      if (G_UNLIKELY (alpha < 1.00
+          || window->background_style != PANEL_BG_STYLE_NONE))
+        {
+          /* clip the drawing area, but preserve the rectangle */
+          cairo_clip_preserve (cr);
+
+          /* draw the background */
+          panel_util_set_source_rgba (cr, color, alpha);
+          cairo_fill (cr);
+        }
+      else
+        {
+          /* clip the drawing area */
+          cairo_clip (cr);
+        }
     }
 
   /* draw marching ants selection if the timeout is running */
@@ -426,7 +544,7 @@ panel_base_window_expose_event (GtkWidget      *widget,
       cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1);
       cairo_stroke (cr);
     }
-  else
+  else if (window->background_style == PANEL_BG_STYLE_NONE)
     {
       if (PANEL_HAS_FLAG (priv->borders, PANEL_BORDER_BOTTOM | PANEL_BORDER_RIGHT))
         {
@@ -534,6 +652,13 @@ panel_base_window_composited_changed (GtkWidget *widget)
       gtk_widget_unrealize (widget);
     }
 
+  /* clear cairo image cache */
+  if (window->priv->bg_image_cache != NULL)
+    {
+      cairo_pattern_destroy (window->priv->bg_image_cache);
+      window->priv->bg_image_cache = NULL;
+    }
+
   /* get the widget screen */
   screen = gtk_window_get_screen (GTK_WINDOW (widget));
   panel_return_if_fail (GDK_IS_SCREEN (screen));
@@ -618,6 +743,19 @@ panel_base_window_active_timeout_destroyed (gpointer user_data)
 
 
 static void
+panel_base_window_set_plugin_data (PanelBaseWindow *window,
+                                   GtkCallback      func)
+{
+  GtkWidget *itembar;
+
+  itembar = gtk_bin_get_child (GTK_BIN (window));
+  if (G_LIKELY (itembar != NULL))
+    gtk_container_foreach (GTK_CONTAINER (itembar), func, window);
+}
+
+
+
+static void
 panel_base_window_set_plugin_background_alpha (GtkWidget *widget,
                                                gpointer   user_data)
 {
@@ -635,6 +773,36 @@ panel_base_window_set_plugin_background_alpha (GtkWidget *widget,
 
 
 
+static void
+panel_base_window_set_plugin_background_color (GtkWidget *widget,
+                                               gpointer   user_data)
+{
+  PanelBaseWindow *window = PANEL_BASE_WINDOW (user_data);
+  GdkColor        *color;
+
+  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (widget));
+  panel_return_if_fail (PANEL_IS_BASE_WINDOW (user_data));
+
+  /* send null if the style is not a bg color */
+  color = window->background_style == PANEL_BG_STYLE_COLOR ? window->background_color : NULL;
+
+  if (PANEL_IS_PLUGIN_EXTERNAL (widget))
+    panel_plugin_external_set_background_color (PANEL_PLUGIN_EXTERNAL (widget), color);
+  else if (PANEL_IS_PLUGIN_EXTERNAL_46 (widget))
+    panel_plugin_external_46_set_background_color (PANEL_PLUGIN_EXTERNAL_46 (widget), color);
+}
+
+
+
+static void
+panel_base_window_set_plugin_background_image (GtkWidget *widget,
+                                               gpointer   user_data)
+{
+
+}
+
+
+
 void
 panel_base_window_move_resize (PanelBaseWindow *window,
                                gint             x,
@@ -680,6 +848,8 @@ panel_base_window_get_borders (PanelBaseWindow *window)
   if (priv->active_timeout_id != 0)
     return PANEL_BORDER_TOP | PANEL_BORDER_BOTTOM
            | PANEL_BORDER_LEFT | PANEL_BORDER_RIGHT;
+  else if (window->background_style != PANEL_BG_STYLE_NONE)
+    return PANEL_BORDER_NONE;
 
   return priv->borders;
 }
diff --git a/panel/panel-base-window.h b/panel/panel-base-window.h
index ffe1ab7..0502359 100644
--- a/panel/panel-base-window.h
+++ b/panel/panel-base-window.h
@@ -64,9 +64,12 @@ struct _PanelBaseWindow
   /*< private >*/
   PanelBaseWindowPrivate *priv;
 
-  /*< private >*/
   guint                   is_composited : 1;
+
   gdouble                 background_alpha;
+  PanelBgStyle            background_style;
+  GdkColor               *background_color;
+  gchar                  *background_image;
 };
 
 GType        panel_base_window_get_type    (void) G_GNUC_CONST;
diff --git a/panel/panel-plugin-external-46.c b/panel/panel-plugin-external-46.c
index 415d615..116e346 100644
--- a/panel/panel-plugin-external-46.c
+++ b/panel/panel-plugin-external-46.c
@@ -48,53 +48,55 @@
 
 
 
-static void         panel_plugin_external_46_provider_init         (XfcePanelPluginProviderInterface *iface);
-static void         panel_plugin_external_46_finalize              (GObject                          *object);
-static void         panel_plugin_external_46_get_property          (GObject                          *object,
-                                                                    guint                             prop_id,
-                                                                    GValue                           *value,
-                                                                    GParamSpec                       *pspec);
-static void         panel_plugin_external_46_set_property          (GObject                          *object,
-                                                                    guint                             prop_id,
-                                                                    const GValue                     *value,
-                                                                    GParamSpec                       *pspec);
-static void         panel_plugin_external_46_realize               (GtkWidget                        *widget);
-static void         panel_plugin_external_46_unrealize             (GtkWidget                        *widget);
-static gboolean     panel_plugin_external_46_client_event          (GtkWidget                        *widget,
-                                                                    GdkEventClient                   *event);
-static gboolean     panel_plugin_external_46_plug_removed          (GtkSocket                        *socket);
-static void         panel_plugin_external_46_plug_added            (GtkSocket                        *socket);
-static void         panel_plugin_external_46_send_client_event     (PanelPluginExternal46            *external,
-                                                                    gint                              message,
-                                                                    gint                              value);
-static void         panel_plugin_external_46_queue_add             (PanelPluginExternal46            *external,
-                                                                    gint                              message,
-                                                                    gint                              value);
-static const gchar *panel_plugin_external_46_get_name              (XfcePanelPluginProvider          *provider);
-static gint         panel_plugin_external_46_get_unique_id         (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_set_size              (XfcePanelPluginProvider          *provider,
-                                                                    gint                              size);
-static void         panel_plugin_external_46_set_orientation       (XfcePanelPluginProvider          *provider,
-                                                                    GtkOrientation                    orientation);
-static void         panel_plugin_external_46_set_screen_position   (XfcePanelPluginProvider          *provider,
-                                                                    XfceScreenPosition                screen_position);
-static void         panel_plugin_external_46_save                  (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_get_show_configure    (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_show_configure        (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_get_show_about        (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_show_about            (XfcePanelPluginProvider          *provider);
-static void         panel_plugin_external_46_removed               (XfcePanelPluginProvider          *provider);
-static gboolean     panel_plugin_external_46_remote_event          (XfcePanelPluginProvider          *provider,
-                                                                    const gchar                      *name,
-                                                                    const GValue                     *value,
-                                                                    guint                            *handler_id);
-static void         panel_plugin_external_46_set_locked            (XfcePanelPluginProvider          *provider,
-                                                                    gboolean                          locked);
-static void         panel_plugin_external_46_set_sensitive         (PanelPluginExternal46            *external);
-static void         panel_plugin_external_46_child_watch           (GPid                              pid,
-                                                                    gint                              status,
-                                                                    gpointer                          user_data);
-static void         panel_plugin_external_46_child_watch_destroyed (gpointer                          user_data);
+static void         panel_plugin_external_46_provider_init            (XfcePanelPluginProviderInterface *iface);
+static void         panel_plugin_external_46_finalize                 (GObject                          *object);
+static void         panel_plugin_external_46_get_property             (GObject                          *object,
+                                                                       guint                             prop_id,
+                                                                       GValue                           *value,
+                                                                       GParamSpec                       *pspec);
+static void         panel_plugin_external_46_set_property             (GObject                          *object,
+                                                                       guint                             prop_id,
+                                                                       const GValue                     *value,
+                                                                       GParamSpec                       *pspec);
+static void         panel_plugin_external_46_realize                  (GtkWidget                        *widget);
+static void         panel_plugin_external_46_unrealize                (GtkWidget                        *widget);
+static gboolean     panel_plugin_external_46_client_event             (GtkWidget                        *widget,
+                                                                       GdkEventClient                   *event);
+static gboolean     panel_plugin_external_46_plug_removed             (GtkSocket                        *socket);
+static void         panel_plugin_external_46_plug_added               (GtkSocket                        *socket);
+static void         panel_plugin_external_46_send_client_event        (PanelPluginExternal46            *external,
+                                                                       GdkEventClient                   *event);
+static void         panel_plugin_external_46_send_client_event_simple (PanelPluginExternal46            *external,
+                                                                       gint                              message,
+                                                                       gint                              value);
+static void         panel_plugin_external_46_queue_add                (PanelPluginExternal46            *external,
+                                                                       gint                              message,
+                                                                       gint                              value);
+static const gchar *panel_plugin_external_46_get_name                 (XfcePanelPluginProvider          *provider);
+static gint         panel_plugin_external_46_get_unique_id            (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_46_set_size                 (XfcePanelPluginProvider          *provider,
+                                                                       gint                              size);
+static void         panel_plugin_external_46_set_orientation          (XfcePanelPluginProvider          *provider,
+                                                                       GtkOrientation                    orientation);
+static void         panel_plugin_external_46_set_screen_position      (XfcePanelPluginProvider          *provider,
+                                                                       XfceScreenPosition                screen_position);
+static void         panel_plugin_external_46_save                     (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_46_get_show_configure       (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_46_show_configure           (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_46_get_show_about           (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_46_show_about               (XfcePanelPluginProvider          *provider);
+static void         panel_plugin_external_46_removed                  (XfcePanelPluginProvider          *provider);
+static gboolean     panel_plugin_external_46_remote_event             (XfcePanelPluginProvider          *provider,
+                                                                       const gchar                      *name,
+                                                                       const GValue                     *value,
+                                                                       guint                            *handler_id);
+static void         panel_plugin_external_46_set_locked               (XfcePanelPluginProvider          *provider,
+                                                                       gboolean                          locked);
+static void         panel_plugin_external_46_set_sensitive            (PanelPluginExternal46            *external);
+static void         panel_plugin_external_46_child_watch              (GPid                              pid,
+                                                                       gint                              status,
+                                                                       gpointer                          user_data);
+static void         panel_plugin_external_46_child_watch_destroyed    (gpointer                          user_data);
 
 
 
@@ -262,7 +264,7 @@ panel_plugin_external_46_finalize (GObject *object)
   if (external->queue != NULL)
     {
       for (li = external->queue; li != NULL; li = li->next)
-        g_slice_free (QueueItem, li->data);
+        g_slice_free (GdkEventClient, li->data);
       g_slist_free (external->queue);
     }
 
@@ -433,7 +435,7 @@ panel_plugin_external_46_unrealize (GtkWidget *widget)
     }
 
   /* quit the plugin */
-  panel_plugin_external_46_send_client_event (external, PANEL_CLIENT_EVENT_QUIT, FALSE);
+  panel_plugin_external_46_send_client_event_simple (external, PANEL_CLIENT_EVENT_QUIT, FALSE);
 
   (*GTK_WIDGET_CLASS (panel_plugin_external_46_parent_class)->unrealize) (widget);
 }
@@ -547,13 +549,13 @@ panel_plugin_external_46_plug_added (GtkSocket *socket)
 {
   PanelPluginExternal46 *external = PANEL_PLUGIN_EXTERNAL_46 (socket);
   GSList                *li;
-  QueueItem             *item;
+  GdkEventClient        *event;
 
   /* plug has been added */
   external->plug_embedded = TRUE;
 
   panel_debug (PANEL_DEBUG_DOMAIN_EXTERNAL46,
-               "plugin  %d has been embedded, %d values in queue",
+               "plugin  %d has been embedded, %d events in queue",
                external->unique_id, g_slist_length (external->queue));
 
   /* send all the messages in the queue */
@@ -562,11 +564,9 @@ panel_plugin_external_46_plug_added (GtkSocket *socket)
       external->queue = g_slist_reverse (external->queue);
       for (li = external->queue; li != NULL; li = li->next)
         {
-          item = li->data;
-          panel_plugin_external_46_send_client_event (external,
-                                                      item->message,
-                                                      item->value);
-          g_slice_free (QueueItem, item);
+          event = li->data;
+          panel_plugin_external_46_send_client_event (external, event);
+          g_slice_free (GdkEventClient, event);
         }
 
       g_slist_free (external->queue);
@@ -578,30 +578,44 @@ panel_plugin_external_46_plug_added (GtkSocket *socket)
 
 static void
 panel_plugin_external_46_send_client_event (PanelPluginExternal46 *external,
-                                            gint                   message,
-                                            gint                   value)
+                                            GdkEventClient        *event)
 {
-  GdkEventClient event;
-
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
   panel_return_if_fail (panel_atom != GDK_NONE);
   panel_return_if_fail (GDK_IS_WINDOW (GTK_WIDGET (external)->window));
 
-  event.type = GDK_CLIENT_EVENT;
-  event.window = GTK_WIDGET (external)->window;
-  event.send_event = TRUE;
-  event.message_type = panel_atom;
-  event.data_format = 16;
-  event.data.s[0] = message;
-  event.data.s[1] = value;
-  event.data.s[2] = 0;
+  /* complete event information */
+  event->type = GDK_CLIENT_EVENT;
+  event->window = GTK_WIDGET (external)->window;
+  event->send_event = TRUE;
+  event->message_type = panel_atom;
 
   gdk_error_trap_push ();
-  gdk_event_send_client_message ((GdkEvent *) &event,
+  gdk_event_send_client_message ((GdkEvent *) event,
       GDK_WINDOW_XID (gtk_socket_get_plug_window (GTK_SOCKET (external))));
   gdk_flush ();
   if (gdk_error_trap_pop () != 0)
-    g_warning ("Failed to send client event %d", message);
+    g_warning ("Failed to send client event %d", event->data.s[0]);
+}
+
+
+
+static void
+panel_plugin_external_46_send_client_event_simple (PanelPluginExternal46 *external,
+                                                   gint                   message,
+                                                   gint                   value)
+{
+  GdkEventClient event;
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
+
+  /* set event data */
+  event.data_format = 16;
+  event.data.s[0] = message;
+  event.data.s[1] = value;
+  event.data.s[2] = 0;
+
+  panel_plugin_external_46_send_client_event (external, &event);
 }
 
 
@@ -611,23 +625,24 @@ panel_plugin_external_46_queue_add (PanelPluginExternal46 *external,
                                     gint                   message,
                                     gint                   value)
 {
-  QueueItem *item;
+  GdkEventClient *event;
 
   panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
 
   if (external->plug_embedded)
     {
       /* directly send the message */
-      panel_plugin_external_46_send_client_event (external, message, value);
+      panel_plugin_external_46_send_client_event_simple (external, message, value);
     }
   else
     {
       /* queue the message until the plug is embedded */
-      item = g_slice_new0 (QueueItem);
-      item->message = message;
-      item->value = value;
+      event = g_slice_new0 (GdkEventClient);
+      event->data_format = 16;
+      event->data.s[0] = message;
+      event->data.s[1] = value;
 
-      external->queue = g_slist_prepend (external->queue, item);
+      external->queue = g_slist_prepend (external->queue, event);
     }
 }
 
@@ -892,3 +907,52 @@ panel_plugin_external_46_set_background_alpha (PanelPluginExternal46 *external,
                                       PANEL_CLIENT_EVENT_SET_BACKGROUND_ALPHA,
                                       rint (alpha * 100.0));
 }
+
+
+
+void
+panel_plugin_external_46_set_background_color (PanelPluginExternal46 *external,
+                                               GdkColor              *color)
+{
+  GdkEventClient *event;
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
+
+  event = g_slice_new0 (GdkEventClient);
+
+  if (color != NULL)
+    {
+      event->data_format = 16;
+      event->data.s[0] = PANEL_CLIENT_EVENT_SET_BG_COLOR;
+      event->data.s[1] = color->red;
+      event->data.s[2] = color->green;
+      event->data.s[3] = color->blue;
+      event->data.s[4] = 0;
+    }
+  else
+    {
+      event->data_format = 16;
+      event->data.s[0] = PANEL_CLIENT_EVENT_UNSET_BG;
+    }
+
+  if (external->plug_embedded)
+    {
+      /* directly send the event */
+      panel_plugin_external_46_send_client_event (external, event);
+      g_slice_free (GdkEventClient, event);
+    }
+  else
+    {
+      /* queue the event until the plug is embedded */
+      external->queue = g_slist_prepend (external->queue, event);
+    }
+}
+
+
+
+void
+panel_plugin_external_46_set_background_image (PanelPluginExternal46 *external,
+                                               gchar                 *image)
+{
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL_46 (external));
+}
diff --git a/panel/panel-plugin-external-46.h b/panel/panel-plugin-external-46.h
index f5cb4c2..b4730a7 100644
--- a/panel/panel-plugin-external-46.h
+++ b/panel/panel-plugin-external-46.h
@@ -42,9 +42,15 @@ GtkWidget *panel_plugin_external_46_new                  (PanelModule
                                                           gint                    unique_id,
                                                           gchar                 **arguments) G_GNUC_MALLOC;
 
-void       panel_plugin_external_46_set_background_alpha (PanelPluginExternal46   *external,
+void       panel_plugin_external_46_set_background_alpha (PanelPluginExternal46  *external,
                                                           gdouble                 alpha);
 
+void       panel_plugin_external_46_set_background_color (PanelPluginExternal46  *external,
+                                                          GdkColor               *color);
+
+void       panel_plugin_external_46_set_background_image (PanelPluginExternal46  *external,
+                                                          gchar                  *image);
+
 G_END_DECLS
 
 #endif /* !__PANEL_PLUGIN_EXTERNAL_46_H__ */
diff --git a/panel/panel-plugin-external.c b/panel/panel-plugin-external.c
index a31dc45..d9ce8b8 100644
--- a/panel/panel-plugin-external.c
+++ b/panel/panel-plugin-external.c
@@ -1040,3 +1040,62 @@ panel_plugin_external_set_background_alpha (PanelPluginExternal *external,
 
   g_value_unset (&value);
 }
+
+
+
+void
+panel_plugin_external_set_background_color (PanelPluginExternal *external,
+                                            GdkColor            *color)
+{
+  GValue       value = { 0, };
+  const gchar *prop;
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+
+  if (G_LIKELY (color != NULL))
+    {
+      prop = SIGNAL_WRAPPER_BACKGROUND_COLOR;
+
+      g_value_init (&value, G_TYPE_STRING);
+      g_value_take_string (&value, gdk_color_to_string (color));
+    }
+  else
+    {
+      prop = SIGNAL_WRAPPER_BACKGROUND_UNSET;
+
+      g_value_init (&value, G_TYPE_BOOLEAN);
+      g_value_take_string (&value, FALSE);
+    }
+
+  panel_plugin_external_queue_add (external, FALSE, prop, &value);
+
+  g_value_unset (&value);
+}
+
+
+
+void
+panel_plugin_external_set_background_image (PanelPluginExternal *external,
+                                            gchar               *image)
+{
+  GValue value = { 0, };
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+
+  if (G_UNLIKELY (image != NULL))
+    {
+      g_value_init (&value, G_TYPE_STRING);
+      g_value_set_string (&value, image);
+
+      panel_plugin_external_queue_add (external, FALSE,
+                                       SIGNAL_WRAPPER_BACKGROUND_IMAGE,
+                                       &value);
+
+      g_value_unset (&value);
+    }
+  else
+    {
+      /* unset the bg */
+      panel_plugin_external_set_background_color (external, NULL);
+    }
+}
diff --git a/panel/panel-plugin-external.h b/panel/panel-plugin-external.h
index 04c0a1b..175e11b 100644
--- a/panel/panel-plugin-external.h
+++ b/panel/panel-plugin-external.h
@@ -45,6 +45,12 @@ GtkWidget *panel_plugin_external_new                  (PanelModule          *mod
 void       panel_plugin_external_set_background_alpha (PanelPluginExternal  *external,
                                                        gdouble               alpha);
 
+void       panel_plugin_external_set_background_color (PanelPluginExternal  *external,
+                                                       GdkColor             *color);
+
+void       panel_plugin_external_set_background_image (PanelPluginExternal  *external,
+                                                       gchar                *image);
+
 G_END_DECLS
 
 #endif /* !__PANEL_PLUGIN_EXTERNAL_H__ */
diff --git a/panel/panel-preferences-dialog.c b/panel/panel-preferences-dialog.c
index cc08a69..1e80f49 100644
--- a/panel/panel-preferences-dialog.c
+++ b/panel/panel-preferences-dialog.c
@@ -54,6 +54,8 @@ static void panel_preferences_dialog_bindings_update (PanelPreferencesDialog *di
 static void panel_preferences_dialog_output_changed (GtkComboBox *combobox, PanelPreferencesDialog *dialog);
 
 static void panel_preferences_dialog_bg_style_changed (PanelPreferencesDialog *dialog);
+static void panel_preferences_dialog_bg_image_file_set (GtkFileChooserButton *button, PanelPreferencesDialog *dialog);
+static void panel_preferences_dialog_bg_image_notified (PanelPreferencesDialog *dialog);
 
 static void panel_preferences_dialog_panel_combobox_changed (GtkComboBox *combobox, PanelPreferencesDialog *dialog);
 static void panel_preferences_dialog_panel_combobox_rebuild (PanelPreferencesDialog *dialog);
@@ -110,6 +112,9 @@ struct _PanelPreferencesDialog
   /* changed signal for the active panel's itembar */
   gulong            items_changed_handler_id;
 
+  /* background image watch */
+  gulong            bg_image_notify_handler_id;
+
   /* changed signal for the output selector */
   gulong            output_changed_handler_id;
 };
@@ -180,6 +185,11 @@ panel_preferences_dialog_init (PanelPreferencesDialog *dialog)
   g_signal_connect_swapped (G_OBJECT (object), "notify::visible",
       G_CALLBACK (panel_preferences_dialog_bg_style_changed), dialog);
 
+  object = gtk_builder_get_object (GTK_BUILDER (dialog), "background-image");
+  panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (object));
+  g_signal_connect (G_OBJECT (object), "file-set",
+    G_CALLBACK (panel_preferences_dialog_bg_image_file_set), dialog);
+
   /* items treeview and buttons */
   connect_signal ("item-up", "clicked", panel_preferences_dialog_item_move);
   connect_signal ("item-down", "clicked", panel_preferences_dialog_item_move);
@@ -245,12 +255,24 @@ panel_preferences_dialog_finalize (GObject *object)
   PanelPreferencesDialog *dialog = PANEL_PREFERENCES_DIALOG (object);
   GtkWidget              *itembar;
 
-  /* disconnect changed signal */
-  if (dialog->active != NULL && dialog->items_changed_handler_id != 0)
+  /* free bindings list */
+  g_slist_free (dialog->bindings);
+
+  if (dialog->active != NULL)
     {
-      itembar = gtk_bin_get_child (GTK_BIN (dialog->active));
-      g_signal_handler_disconnect (G_OBJECT (itembar),
-          dialog->items_changed_handler_id);
+      if (dialog->items_changed_handler_id != 0)
+        {
+          /* disconnect changed signal */
+          itembar = gtk_bin_get_child (GTK_BIN (dialog->active));
+          g_signal_handler_disconnect (G_OBJECT (itembar),
+              dialog->items_changed_handler_id);
+        }
+
+      if (dialog->bg_image_notify_handler_id != 0)
+        {
+          g_signal_handler_disconnect (G_OBJECT (dialog->active),
+              dialog->bg_image_notify_handler_id);
+        }
     }
 
   /* deselect all windows */
@@ -291,7 +313,7 @@ panel_preferences_dialog_bindings_unbind (PanelPreferencesDialog *dialog)
 {
   GSList *li;
 
-  if (dialog->bindings)
+  if (dialog->bindings != NULL)
     {
       /* remove all bindings */
       for (li = dialog->bindings; li != NULL; li = li->next)
@@ -300,6 +322,18 @@ panel_preferences_dialog_bindings_unbind (PanelPreferencesDialog *dialog)
       g_slist_free (dialog->bindings);
       dialog->bindings = NULL;
     }
+
+  /* disconnect image watch */
+  if (dialog->bg_image_notify_handler_id != 0)
+    {
+      if (dialog->active != NULL)
+        {
+          g_signal_handler_disconnect (G_OBJECT (dialog->active),
+              dialog->bg_image_notify_handler_id);
+        }
+
+      dialog->bg_image_notify_handler_id = 0;
+    }
 }
 
 
@@ -362,6 +396,11 @@ panel_preferences_dialog_bindings_update (PanelPreferencesDialog *dialog)
   panel_preferences_dialog_bindings_add (dialog, "background-style", "active");
   panel_preferences_dialog_bindings_add (dialog, "background-color", "color");
 
+  /* watch image changes from the panel */
+  dialog->bg_image_notify_handler_id = g_signal_connect_swapped (G_OBJECT (dialog->active),
+      "notify::background-image", G_CALLBACK (panel_preferences_dialog_bg_image_notified), dialog);
+  panel_preferences_dialog_bg_image_notified (dialog);
+
   /* get run mode of the driver (multiple screens or randr) */
   display = gtk_widget_get_display (GTK_WIDGET (dialog->active));
   n_screens = gdk_display_get_n_screens (display);
@@ -548,10 +587,54 @@ panel_preferences_dialog_bg_style_changed (PanelPreferencesDialog *dialog)
   object = gtk_builder_get_object (GTK_BUILDER (dialog), "bg-image-box");
   panel_return_if_fail (GTK_IS_WIDGET (object));
   g_object_set (G_OBJECT (object), "visible", active == 2, NULL);
+}
 
-  object = gtk_builder_get_object (GTK_BUILDER (dialog), "bg-theme-box");
-  panel_return_if_fail (GTK_IS_WIDGET (object));
-  g_object_set (G_OBJECT (object), "visible", active == 3, NULL);
+
+
+static void
+panel_preferences_dialog_bg_image_file_set (GtkFileChooserButton   *button,
+                                            PanelPreferencesDialog *dialog)
+{
+  gchar *filename;
+
+  panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
+  panel_return_if_fail (PANEL_IS_PREFERENCES_DIALOG (dialog));
+  panel_return_if_fail (PANEL_IS_WINDOW (dialog->active));
+
+  g_signal_handler_block (G_OBJECT (dialog->active),
+      dialog->bg_image_notify_handler_id);
+
+  filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button));
+  g_object_set (G_OBJECT (dialog->active), "background-image", filename, NULL);
+  g_free (filename);
+
+  g_signal_handler_unblock (G_OBJECT (dialog->active),
+      dialog->bg_image_notify_handler_id);
+}
+
+
+
+static void
+panel_preferences_dialog_bg_image_notified (PanelPreferencesDialog *dialog)
+{
+  gchar   *filename;
+  GObject *button;
+
+  panel_return_if_fail (PANEL_IS_PREFERENCES_DIALOG (dialog));
+  panel_return_if_fail (PANEL_IS_WINDOW (dialog->active));
+
+  button = gtk_builder_get_object (GTK_BUILDER (dialog), "background-image");
+  panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
+
+  g_signal_handlers_block_by_func (G_OBJECT (button),
+      G_CALLBACK (panel_preferences_dialog_bg_image_file_set), dialog);
+
+  g_object_get (G_OBJECT (dialog->active), "background-image", &filename, NULL);
+  gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (button), filename != NULL ? filename : "");
+  g_free (filename);
+
+  g_signal_handlers_unblock_by_func (G_OBJECT (button),
+      G_CALLBACK (panel_preferences_dialog_bg_image_file_set), dialog);
 }
 
 
diff --git a/panel/panel-preferences-dialog.glade b/panel/panel-preferences-dialog.glade
index f76157d..9c8485b 100644
--- a/panel/panel-preferences-dialog.glade
+++ b/panel/panel-preferences-dialog.glade
@@ -967,7 +967,6 @@ ue).</property>
       <widget name="label15"/>
       <widget name="label16"/>
       <widget name="label19"/>
-      <widget name="label20"/>
     </widgets>
   </object>
 </interface>
diff --git a/panel/panel-window.c b/panel/panel-window.c
index 3d3dcb8..7d1e58a 100644
--- a/panel/panel-window.c
+++ b/panel/panel-window.c
@@ -2326,20 +2326,41 @@ void
 panel_window_set_povider_info (PanelWindow *window,
                                GtkWidget   *provider)
 {
+  PanelBaseWindow *base_window = PANEL_BASE_WINDOW (window);
+
   panel_return_if_fail (PANEL_IS_WINDOW (window));
   panel_return_if_fail (XFCE_IS_PANEL_PLUGIN_PROVIDER (provider));
 
   xfce_panel_plugin_provider_set_locked (XFCE_PANEL_PLUGIN_PROVIDER (provider),
                                          panel_window_get_locked (window));
 
-  if (PANEL_BASE_WINDOW (window)->background_alpha < 1.0)
+  if (base_window->background_alpha < 1.0)
     {
       if (PANEL_IS_PLUGIN_EXTERNAL (provider))
         panel_plugin_external_set_background_alpha (PANEL_PLUGIN_EXTERNAL (provider),
-            PANEL_BASE_WINDOW (window)->background_alpha);
+            base_window->background_alpha);
       else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
         panel_plugin_external_46_set_background_alpha (PANEL_PLUGIN_EXTERNAL_46 (provider),
-            PANEL_BASE_WINDOW (window)->background_alpha);
+            base_window->background_alpha);
+    }
+
+  if (base_window->background_style == PANEL_BG_STYLE_COLOR)
+    {
+      if (PANEL_IS_PLUGIN_EXTERNAL (provider))
+        panel_plugin_external_set_background_color (PANEL_PLUGIN_EXTERNAL (provider),
+            base_window->background_color);
+      else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
+        panel_plugin_external_46_set_background_color (PANEL_PLUGIN_EXTERNAL_46 (provider),
+            base_window->background_color);
+    }
+  else if (base_window->background_style == PANEL_BG_STYLE_IMAGE)
+    {
+      if (PANEL_IS_PLUGIN_EXTERNAL (provider))
+        panel_plugin_external_set_background_image (PANEL_PLUGIN_EXTERNAL (provider),
+            base_window->background_image);
+      else if (PANEL_IS_PLUGIN_EXTERNAL_46 (provider))
+        panel_plugin_external_46_set_background_image (PANEL_PLUGIN_EXTERNAL_46 (provider),
+            base_window->background_image);
     }
 
   panel_window_set_plugin_orientation (provider, window);
diff --git a/wrapper/main.c b/wrapper/main.c
index 69e83d5..36a9ea8 100644
--- a/wrapper/main.c
+++ b/wrapper/main.c
@@ -90,11 +90,6 @@ wrapper_gproxy_set (DBusGProxy              *dbus_gproxy,
         xfce_panel_plugin_provider_set_screen_position (provider, g_value_get_uint (value));
       else if (strcmp (property, SIGNAL_SET_LOCKED) == 0)
         xfce_panel_plugin_provider_set_locked (provider, g_value_get_boolean (value));
-      else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_ALPHA) == 0)
-        {
-          plug = g_object_get_qdata (G_OBJECT (provider), plug_quark);
-          wrapper_plug_set_background_alpha (plug, g_value_get_double (value));
-        }
       else if (strcmp (property, SIGNAL_SAVE) == 0)
         xfce_panel_plugin_provider_save (provider);
       else if (strcmp (property, SIGNAL_SHOW_CONFIGURE) == 0)
@@ -108,7 +103,20 @@ wrapper_gproxy_set (DBusGProxy              *dbus_gproxy,
       else if (strcmp (property, SIGNAL_WRAPPER_QUIT) == 0)
         gtk_main_quit ();
       else
-        panel_assert_not_reached ();
+        {
+          plug = g_object_get_qdata (G_OBJECT (provider), plug_quark);
+
+          if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_ALPHA) == 0)
+            wrapper_plug_set_background_alpha (plug, g_value_get_double (value));
+          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_COLOR) == 0)
+            wrapper_plug_set_background_color (plug, g_value_get_string (value));
+          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_IMAGE) == 0)
+            wrapper_plug_set_background_image (plug, g_value_get_string (value));
+          else if (strcmp (property, SIGNAL_WRAPPER_BACKGROUND_UNSET) == 0)
+            wrapper_plug_set_background_color (plug, NULL);
+          else
+            panel_assert_not_reached ();
+        }
 
       g_free (property);
       g_value_unset (value);
diff --git a/wrapper/wrapper-plug.c b/wrapper/wrapper-plug.c
index fcefe9c..bd21c8d 100644
--- a/wrapper/wrapper-plug.c
+++ b/wrapper/wrapper-plug.c
@@ -29,6 +29,7 @@
 
 
 
+static void     wrapper_plug_finalize     (GObject        *object);
 static gboolean wrapper_plug_expose_event (GtkWidget      *widget,
                                            GdkEventExpose *event);
 
@@ -43,11 +44,13 @@ struct _WrapperPlug
 {
   GtkPlug __parent__;
 
-  /* background alpha */
-  gdouble background_alpha;
-
   /* whether the wrapper has a rgba colormap */
-  guint   is_composited : 1;
+  guint     is_composited : 1;
+
+  /* background information */
+  gdouble   background_alpha;
+  GdkColor *background_color;
+  gchar    *background_image;
 };
 
 
@@ -64,8 +67,12 @@ G_DEFINE_TYPE (WrapperPlug, wrapper_plug, GTK_TYPE_PLUG)
 static void
 wrapper_plug_class_init (WrapperPlugClass *klass)
 {
+  GObjectClass   *gobject_class;
   GtkWidgetClass *gtkwidget_class;
 
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = wrapper_plug_finalize;
+
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
   gtkwidget_class->expose_event = wrapper_plug_expose_event;
 }
@@ -79,6 +86,8 @@ wrapper_plug_init (WrapperPlug *plug)
   GdkScreen   *screen;
 
   plug->background_alpha = 1.00;
+  plug->background_color = NULL;
+  plug->background_image = NULL;
 
   gtk_widget_set_name (GTK_WIDGET (plug), "XfcePanelWindowWrapper");
 
@@ -110,6 +119,20 @@ wrapper_plug_init (WrapperPlug *plug)
 
 
 
+static void
+wrapper_plug_finalize (GObject *object)
+{
+  WrapperPlug *plug = WRAPPER_PLUG (object);
+
+  g_free (plug->background_image);
+  if (plug->background_color)
+    gdk_color_free (plug->background_color);
+
+  G_OBJECT_CLASS (wrapper_plug_parent_class)->finalize (object);
+}
+
+
+
 static gboolean
 wrapper_plug_expose_event (GtkWidget      *widget,
                            GdkEventExpose *event)
@@ -120,13 +143,17 @@ wrapper_plug_expose_event (GtkWidget      *widget,
   GtkStateType   state = GTK_STATE_NORMAL;
   gdouble        alpha = plug->is_composited ? plug->background_alpha : 1.00;
 
-  if (GTK_WIDGET_DRAWABLE (widget) && alpha < 1.00)
+  if (GTK_WIDGET_DRAWABLE (widget)
+      && (alpha < 1.00 || plug->background_color != NULL))
     {
       /* create the cairo context */
       cr = gdk_cairo_create (widget->window);
 
       /* get the background gdk color */
-      color = &(widget->style->bg[state]);
+      if (plug->background_color != NULL)
+        color = plug->background_color;
+      else
+        color = &(widget->style->bg[state]);
 
       /* set the cairo source color */
       cairo_set_source_rgba (cr, PANEL_GDKCOLOR_TO_DOUBLE (color),
@@ -181,3 +208,37 @@ wrapper_plug_set_background_alpha (WrapperPlug *plug,
   if (plug->is_composited)
     gtk_widget_queue_draw (GTK_WIDGET (plug));
 }
+
+
+
+
+void
+wrapper_plug_set_background_color (WrapperPlug *plug,
+                                   const gchar *color_string)
+{
+  GdkColor color = { 0, };
+
+  panel_return_if_fail (WRAPPER_IS_PLUG (plug));
+
+  if (plug->background_color != NULL)
+    gdk_color_free (plug->background_color);
+  plug->background_color = NULL;
+
+  g_free (plug->background_image);
+  plug->background_image = NULL;
+
+  if (color_string != NULL
+      && gdk_color_parse (color_string, &color))
+    plug->background_color = gdk_color_copy (&color);
+g_message ("got color %p", plug->background_color);
+  gtk_widget_queue_draw (GTK_WIDGET (plug));
+}
+
+
+
+void
+wrapper_plug_set_background_image (WrapperPlug *plug,
+                                   const gchar *image)
+{
+  panel_return_if_fail (WRAPPER_IS_PLUG (plug));
+}
diff --git a/wrapper/wrapper-plug.h b/wrapper/wrapper-plug.h
index 5a089af..ab0d3f5 100644
--- a/wrapper/wrapper-plug.h
+++ b/wrapper/wrapper-plug.h
@@ -44,6 +44,12 @@ WrapperPlug  *wrapper_plug_new                  (GdkNativeWindow  socket_id);
 void          wrapper_plug_set_background_alpha (WrapperPlug     *plug,
                                                  gdouble          alpha);
 
+void          wrapper_plug_set_background_color (WrapperPlug     *plug,
+                                                 const gchar     *color_string);
+
+void          wrapper_plug_set_background_image (WrapperPlug     *plug,
+                                                 const gchar     *image);
+
 G_END_DECLS
 
 #endif /* !__WRAPPER_PLUG_H__ */



More information about the Xfce4-commits mailing list