Index: libpanel-applet/panel-applet.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/libpanel-applet/panel-applet.c,v
retrieving revision 1.101
diff -u -3 -p -r1.101 panel-applet.c
--- libpanel-applet/panel-applet.c	9 Jan 2006 20:00:29 -0000	1.101
+++ libpanel-applet/panel-applet.c	20 Jul 2006 16:39:46 -0000
@@ -73,6 +73,9 @@ struct _PanelAppletPrivate {
 	guint                       size;
 	char                       *background;
 	GtkWidget                  *background_widget;
+	PanelAppletBackgroundType   bg_type;
+	GdkColor		    bg_color;
+	GdkPixmap		   *bg_pixmap;		  
 
 	int                         previous_width;
 	int                         previous_height;
@@ -550,6 +553,10 @@ panel_applet_finalize (GObject *object)
 			BONOBO_OBJECT (applet->priv->prop_sack));
 	applet->priv->prop_sack = NULL;
 
+	if (applet->priv->bg_pixmap)
+		g_object_unref (applet->priv->bg_pixmap);
+	applet->priv->bg_pixmap = NULL;
+
 	g_free (applet->priv->size_hints);
 	g_free (applet->priv->prefs_key);
 	g_free (applet->priv->background);
@@ -786,6 +793,50 @@ panel_applet_size_allocate (GtkWidget   
 	}
 }
 
+/* This function paints a widget's background so that it looks like the panel 
+ * would without this widget.
+ * It can (and is) used as a pre handler to the expose-event signal.
+ */
+static gboolean
+panel_applet_draw_default_background (GtkWidget *     widget, 
+				      GdkEventExpose *event,
+				      PanelApplet *   applet)
+{
+	cairo_t			  *cr;
+	int			   x, y, xapplet, yapplet;
+
+	switch (applet->priv->bg_type) {
+	case PANEL_NO_BACKGROUND:
+		break;
+	case PANEL_COLOR_BACKGROUND:
+		cr = gdk_cairo_create (event->window);
+		gdk_cairo_set_source_color (cr, &applet->priv->bg_color);
+		gdk_cairo_rectangle (cr, &event->area);
+		cairo_fill (cr);
+		cairo_destroy (cr);
+		break;
+	case PANEL_PIXMAP_BACKGROUND:
+		gdk_window_get_origin (GTK_WIDGET (applet)->window, &xapplet, &yapplet);
+		gdk_window_get_origin (event->window, &x, &y);
+		gdk_draw_drawable (event->window, 
+				   widget->style->bg_gc[GTK_STATE_NORMAL],
+				   applet->priv->bg_pixmap,
+				   x - xapplet + event->area.x,
+				   y - yapplet + event->area.y,
+				   event->area.x,
+				   event->area.y,
+				   event->area.width,
+				   event->area.height);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+	/* continue drawing */
+	return FALSE;
+}
+
 static gboolean
 panel_applet_expose (GtkWidget      *widget,
 		     GdkEventExpose *event) 
@@ -797,6 +848,8 @@ panel_applet_expose (GtkWidget      *wid
 	g_return_val_if_fail (PANEL_IS_APPLET (widget), FALSE);
 	g_return_val_if_fail (event != NULL, FALSE);
 
+	panel_applet_draw_default_background (widget, event, PANEL_APPLET (widget));
+
 	GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
 
         if (!GTK_WIDGET_HAS_FOCUS (widget))
@@ -1016,80 +1069,58 @@ panel_applet_get_pixmap (PanelApplet    
 	return retval;
 }
 
-static PanelAppletBackgroundType
-panel_applet_handle_background_string (PanelApplet  *applet,
-				       GdkColor     *color,
-				       GdkPixmap   **pixmap)
+static void
+panel_applet_handle_background_string (PanelApplet  *applet)
 {
-	PanelAppletBackgroundType   retval;
 	char                      **elements;
 
-	retval = PANEL_NO_BACKGROUND;
+	if (applet->priv->bg_pixmap)
+		g_object_unref (applet->priv->bg_pixmap);
+	applet->priv->bg_pixmap = NULL;
+	applet->priv->bg_type = PANEL_NO_BACKGROUND;
 
 	if (!GTK_WIDGET_REALIZED (applet) || !applet->priv->background)
-		return retval;
+		return;
 
 	elements = g_strsplit (applet->priv->background, ":", -1);
 
-	if (elements [0] && !strcmp (elements [0], "none" )) {
-		retval = PANEL_NO_BACKGROUND;
-		
+	if (elements[0] && !strcmp (elements [0], "none")) {
+		/* nothing to do */
 	} else if (elements [0] && !strcmp (elements [0], "color")) {
-		g_return_val_if_fail (color != NULL, PANEL_NO_BACKGROUND);
-
-		if (!elements [1] || !panel_applet_parse_color (elements [1], color)) {
-
+		if (!elements [1] || 
+		    !panel_applet_parse_color (elements [1], &applet->priv->bg_color)) {
 			g_warning (_("Incomplete '%s' background type received"), elements [0]);
 			g_strfreev (elements);
-			return PANEL_NO_BACKGROUND;
+			return;
 		}
 
-		retval = PANEL_COLOR_BACKGROUND;
+		applet->priv->bg_type = PANEL_COLOR_BACKGROUND;
 
 	} else if (elements [0] && !strcmp (elements [0], "pixmap")) {
 		GdkNativeWindow pixmap_id;
 		int             x, y;
 
-		g_return_val_if_fail (pixmap != NULL, PANEL_NO_BACKGROUND);
-
 		if (!panel_applet_parse_pixmap_str (elements [1], &pixmap_id, &x, &y)) {
 			g_warning (_("Incomplete '%s' background type received: %s"),
 				   elements [0], elements [1]);
 
 			g_strfreev (elements);
-			return PANEL_NO_BACKGROUND;
+			return;
 		}
 
-		*pixmap = panel_applet_get_pixmap (applet, pixmap_id, x, y);
-		if (!*pixmap) {
+		applet->priv->bg_pixmap = panel_applet_get_pixmap (applet, pixmap_id, x, y);
+		if (applet->priv->bg_pixmap == NULL) {
 			g_warning (_("Failed to get pixmap %s"), elements [1]);
 			g_strfreev (elements);
-			return PANEL_NO_BACKGROUND;
+			return;
 		}
 
-		retval = PANEL_PIXMAP_BACKGROUND;
+		applet->priv->bg_type = PANEL_PIXMAP_BACKGROUND;
 	} else
-		g_warning (_("Unknown background type received"));
+		g_warning (_("Unknown background type \"%s\" received"),
+			   applet->priv->background);
 
 	g_strfreev (elements);
-
-	return retval;
-}
-
-PanelAppletBackgroundType
-panel_applet_get_background (PanelApplet *applet,
-			     GdkColor *color,
-			     GdkPixmap **pixmap)
-{
-	g_return_val_if_fail (PANEL_IS_APPLET (applet), PANEL_NO_BACKGROUND);
-
-	/* initial sanity */
-	if (pixmap != NULL)
-		*pixmap = NULL;
-	if (color != NULL)
-		memset (color, 0, sizeof (GdkColor));
-
-	return panel_applet_handle_background_string (applet, color, pixmap);
 }
 
 static void
@@ -1138,70 +1169,32 @@ panel_applet_get_prop (BonoboPropertyBag
 }
 
 static void
-panel_applet_update_background_for_widget (GtkWidget                 *widget,
-					   PanelAppletBackgroundType  type,
-					   GdkColor                  *color,
-					   GdkPixmap                 *pixmap)
-{
-	GtkRcStyle *rc_style;
-	GtkStyle   *style;
-
-	/* reset style */
-	gtk_widget_set_style (widget, NULL);
-	rc_style = gtk_rc_style_new ();
-	gtk_widget_modify_style (widget, rc_style);
-	gtk_rc_style_unref (rc_style);
-
-	switch (type) {
-	case PANEL_NO_BACKGROUND:
-		break;
-	case PANEL_COLOR_BACKGROUND:
-		gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, color);
-		break;
-	case PANEL_PIXMAP_BACKGROUND:
-		style = gtk_style_copy (widget->style);
-		if (style->bg_pixmap[GTK_STATE_NORMAL])
-			g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]);
-		style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap);
-		gtk_widget_set_style (widget, style);
-		g_object_unref (style);
-		break;
-	default:
-		g_assert_not_reached ();
-		break;
-	}
-}
-
-static void
 panel_applet_handle_background (PanelApplet *applet)
 {
-	PanelAppletBackgroundType  type;
-	GdkColor                   color;
-	GdkPixmap                 *pixmap;
-
-	type = panel_applet_get_background (applet, &color, &pixmap);
+	panel_applet_handle_background_string (applet);
 
 	if (applet->priv->background_widget)
-		panel_applet_update_background_for_widget (applet->priv->background_widget,
-							   type, &color, pixmap);
+		gtk_widget_queue_draw (applet->priv->background_widget);
+	gtk_widget_queue_draw (GTK_WIDGET (applet));
 
-	switch (type) {
+	switch (applet->priv->bg_type) {
 	case PANEL_NO_BACKGROUND:
+		gtk_widget_set_app_paintable (GTK_WIDGET (applet), FALSE);
 		g_signal_emit (G_OBJECT (applet),
 			       panel_applet_signals [CHANGE_BACKGROUND],
 			       0, PANEL_NO_BACKGROUND, NULL, NULL);
 		break;
 	case PANEL_COLOR_BACKGROUND:
+		gtk_widget_set_app_paintable (GTK_WIDGET (applet), TRUE);
 		g_signal_emit (G_OBJECT (applet),
 			       panel_applet_signals [CHANGE_BACKGROUND],
-			       0, PANEL_COLOR_BACKGROUND, &color, NULL);
+			       0, PANEL_COLOR_BACKGROUND, &applet->priv->bg_color, NULL);
 		break;
 	case PANEL_PIXMAP_BACKGROUND:
+		gtk_widget_set_app_paintable (GTK_WIDGET (applet), TRUE);
 		g_signal_emit (G_OBJECT (applet),
 			       panel_applet_signals [CHANGE_BACKGROUND],
-			       0, PANEL_PIXMAP_BACKGROUND, NULL, pixmap);
-
-		g_object_unref (pixmap);
+			       0, PANEL_PIXMAP_BACKGROUND, NULL, applet->priv->bg_pixmap);
 		break;
 	default:
 		g_assert_not_reached ();
@@ -1833,17 +1826,28 @@ void
 panel_applet_set_background_widget (PanelApplet *applet,
 				    GtkWidget   *widget)
 {
+	g_return_if_fail (PANEL_IS_APPLET (applet));
+	g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+
+	/* tell people that applets do this by default now and abort */
+	if (PANEL_IS_APPLET (widget)) {
+	  g_message ("No need to call panel_applet_set_background_widget for widgets of type PanelApplet.");
+	  return;
+	}
+	g_return_if_fail (gtk_widget_is_ancestor (widget, GTK_WIDGET (applet)));
+
+	if (applet->priv->background_widget) {
+		g_signal_handlers_disconnect_by_func (applet->priv->background_widget,
+						      panel_applet_draw_default_background,
+						      applet);
+	}
+
 	applet->priv->background_widget = widget;
 
 	if (widget) {
-		PanelAppletBackgroundType  type;
-		GdkColor                   color;
-		GdkPixmap                 *pixmap;
-
-		type = panel_applet_get_background (applet, &color, &pixmap);
-		panel_applet_update_background_for_widget (widget, type,
-							   &color, pixmap);
-		if (type == PANEL_PIXMAP_BACKGROUND)
-			g_object_unref (pixmap);
+		g_signal_connect (widget, 
+				  "expose-event",
+				  G_CALLBACK (panel_applet_draw_default_background),
+				  applet);
 	}
 }
