implement Control.setBackgroundImage()
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Canvas.java
index eb69100..49382a9 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Canvas.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Canvas.java
@@ -70,6 +70,13 @@
 	super (parent, style);
 }
 
+public void drawBackground (GC gc, int x, int y, int width, int height) {
+	checkWidget ();
+	if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+	if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+	super.drawBackground (gc, x, y, width, height);
+}
+
 /**
  * Returns the caret.
  * <p>
@@ -119,10 +126,10 @@
 	return result;
 }
 
-void redrawWidget (int x, int y, int width, int height, boolean all) {
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean all, boolean trim) {
 	boolean isFocus = caret != null && caret.isFocusCaret ();
 	if (isFocus) caret.killFocus ();
-	super.redrawWidget (x, y, width, height, all);
+	super.redrawWidget (x, y, width, height, redrawAll, all, trim);
 	if (isFocus) caret.setFocus ();
 }
 
@@ -181,46 +188,53 @@
 	if (copyRect.width != 0 && copyRect.height != 0) {
 		update ();
 	}
-//	GC gc = new GC (this);
-//	gc.copyArea (x, y, width, height, destX, destY);
-//	gc.dispose ();
-	int /*long*/ gdkGC = OS.gdk_gc_new (window);
-	OS.gdk_gc_set_exposures (gdkGC, true);
-	OS.gdk_draw_drawable (window, gdkGC, window, copyRect.x, copyRect.y, copyRect.x + deltaX, copyRect.y + deltaY, copyRect.width, copyRect.height);
-	OS.g_object_unref (gdkGC);
-	boolean disjoint = (destX + width < x) || (x + width < destX) || (destY + height < y) || (y + height < destY);
-	if (disjoint) {
-		GdkRectangle rect = new GdkRectangle ();
-		rect.x = x;
-		rect.y = y;
-		rect.width = width;
-		rect.height = height;
-		OS.gdk_region_union_with_rect (invalidateRegion, rect);
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	if (control.backgroundImage != null) {
+		redrawWidget (x, y, width, height, false, false, false);
+		redrawWidget (destX, destY, width, height, false, false, false);
 	} else {
-		GdkRectangle rect = new GdkRectangle ();
-		if (deltaX != 0) {
-			int newX = destX - deltaX;
-			if (deltaX < 0) newX = destX + width;
-			rect.x = newX;
+//		GC gc = new GC (this);
+//		gc.copyArea (x, y, width, height, destX, destY);
+//		gc.dispose ();
+		int /*long*/ gdkGC = OS.gdk_gc_new (window);
+		OS.gdk_gc_set_exposures (gdkGC, true);
+		OS.gdk_draw_drawable (window, gdkGC, window, copyRect.x, copyRect.y, copyRect.x + deltaX, copyRect.y + deltaY, copyRect.width, copyRect.height);
+		OS.g_object_unref (gdkGC);
+		boolean disjoint = (destX + width < x) || (x + width < destX) || (destY + height < y) || (y + height < destY);
+		if (disjoint) {
+			GdkRectangle rect = new GdkRectangle ();
+			rect.x = x;
 			rect.y = y;
-			rect.width = Math.abs(deltaX);
+			rect.width = width;
 			rect.height = height;
 			OS.gdk_region_union_with_rect (invalidateRegion, rect);
-		}
-		if (deltaY != 0) {
-			int newY = destY - deltaY;
-			if (deltaY < 0) newY = destY + height;
-			rect.x = x;
-			rect.y = newY;
-			rect.width = width;
-			rect.height = Math.abs(deltaY);
-			OS.gdk_region_union_with_rect (invalidateRegion, rect);
-		}
-	}	
-	OS.gdk_window_invalidate_region(window, invalidateRegion, all);
-	OS.gdk_region_destroy (visibleRegion);
-	OS.gdk_region_destroy (copyRegion);
-	OS.gdk_region_destroy (invalidateRegion);
+		} else {
+			GdkRectangle rect = new GdkRectangle ();
+			if (deltaX != 0) {
+				int newX = destX - deltaX;
+				if (deltaX < 0) newX = destX + width;
+				rect.x = newX;
+				rect.y = y;
+				rect.width = Math.abs(deltaX);
+				rect.height = height;
+				OS.gdk_region_union_with_rect (invalidateRegion, rect);
+			}
+			if (deltaY != 0) {
+				int newY = destY - deltaY;
+				if (deltaY < 0) newY = destY + height;
+				rect.x = x;
+				rect.y = newY;
+				rect.width = width;
+				rect.height = Math.abs(deltaY);
+				OS.gdk_region_union_with_rect (invalidateRegion, rect);
+			}
+		}	
+		OS.gdk_window_invalidate_region(window, invalidateRegion, all);
+		OS.gdk_region_destroy (visibleRegion);
+		OS.gdk_region_destroy (copyRegion);
+		OS.gdk_region_destroy (invalidateRegion);
+	}
 	if (all) {
 		Control [] children = _getChildren ();
 		for (int i=0; i<children.length; i++) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
index 53a1f85..fcb6e29 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Composite.java
@@ -306,6 +306,29 @@
 	if (socketHandle != 0) display.removeWidget (socketHandle);
 }
 
+void drawBackground (GC gc, int x, int y, int width, int height) {
+	int gdkGC = gc.handle;
+	GdkGCValues values = new GdkGCValues ();
+	OS.gdk_gc_get_values (gdkGC, values);
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	if (control.backgroundImage != null) {
+		Point pt = display.map (this, control, 0, 0);
+		OS.gdk_gc_set_fill (gdkGC, OS.GDK_TILED);
+		OS.gdk_gc_set_ts_origin (gdkGC, -pt.x, -pt.y);
+		OS.gdk_gc_set_tile (gdkGC, control.backgroundImage.pixmap);
+		gc.fillRectangle (x, y, width, height);
+		OS.gdk_gc_set_fill (gdkGC, values.fill);
+		OS.gdk_gc_set_ts_origin (gdkGC, values.ts_x_origin, values.ts_y_origin);
+	} else {
+		gc.setBackground (control.getBackground ());
+		gc.fillRectangle (x, y, width, height);
+		GdkColor color = new GdkColor ();
+		color.pixel = values.background_pixel;
+		OS.gdk_gc_set_background (gdkGC, color);
+	}
+}
+
 void enableWidget (boolean enabled) {
 	if ((state & CANVAS) != 0) return;
 	super.enableWidget (enabled);
@@ -628,11 +651,12 @@
 }
 
 int /*long*/ gtk_style_set (int /*long*/ widget, int /*long*/ previousStyle) {
+	int result = super.gtk_style_set (widget, previousStyle);
 	if ((style & SWT.NO_BACKGROUND) != 0) {
 		int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
 		if (window != 0) OS.gdk_window_set_back_pixmap (window, 0, false);
 	}
-	return 0;
+	return result;
 }
 
 boolean hasBorder () {
@@ -646,7 +670,7 @@
 		if (scrolledHandle != 0) {
 			OS.g_signal_connect_closure (scrolledHandle, OS.scroll_child, display.closures [SCROLL_CHILD], false);
 		}
-		if ((style & SWT.NO_BACKGROUND) != 0) {
+		if ((state & PARENT_BACKGROUND) == 0 && (style & SWT.NO_BACKGROUND) != 0) {
 			OS.g_signal_connect_closure_by_id (handle, display.signalIds [STYLE_SET], 0, display.closures [STYLE_SET], false);
 		}
 	}
@@ -942,6 +966,18 @@
 	return fixedHandle != 0 ? fixedHandle : handle;
 }
 
+void redrawChildren () {
+	super.redrawChildren ();
+	Control [] children = _getChildren ();
+	for (int i = 0; i < children.length; i++) {
+		Control child = children [i];
+		if ((child.state & PARENT_BACKGROUND) != 0) {
+			child.redrawWidget (0, 0, 0, 0, true, false, true);
+			child.redrawChildren ();
+		}
+	}
+}
+
 void register () {
 	super.register ();
 	if (socketHandle != 0) display.addWidget (socketHandle, this);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
index a249691..74bd455 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Control.java
@@ -45,6 +45,7 @@
 	Composite parent;
 	Cursor cursor;
 	Menu menu;
+	Image backgroundImage;
 	Font font;
 	String toolTipText;
 	Object layoutData;
@@ -218,6 +219,10 @@
 		OS.g_signal_connect_closure (imHandle, OS.preedit_changed, display.closures [PREEDIT_CHANGED], false);
 	}
 	
+	if ((state & PARENT_BACKGROUND) != 0) {
+		OS.g_signal_connect_closure_by_id (handle, display.signalIds [STYLE_SET], 0, display.closures [STYLE_SET], false);
+	}
+
 	int /*long*/ topHandle = topHandle ();
 	OS.g_signal_connect_closure_by_id (topHandle, display.signalIds [MAP], 0, display.closures [MAP], true);
 }
@@ -616,6 +621,10 @@
 	}
 	int result = 0;
 	if (move && !sameOrigin) {
+		Control control = findBackgroundControl ();
+		if (control != null && control.backgroundImage != null) {
+			if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true);
+		}
 		sendEvent (SWT.Move);
 		result |= MOVED;
 	}
@@ -1457,6 +1466,11 @@
 	return false;
 }
 
+Control findBackgroundControl () {
+	if ((state & BACKGROUND) != 0 || backgroundImage != null) return this;
+	return (state & PARENT_BACKGROUND) != 0 ? parent.findBackgroundControl () : null;
+}
+
 Menu [] findMenus (Control control) {
 	if (menu != null && this != control) return new Menu [] {menu};
 	return new Menu [0];
@@ -1538,13 +1552,22 @@
  */
 public Color getBackground () {
 	checkWidget();
-	return Color.gtk_new (display, getBackgroundColor ());
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	return Color.gtk_new (display, control.getBackgroundColor ());
 }
 
 GdkColor getBackgroundColor () {
 	return getBgColor ();
 }
 
+public Image getBackgroundImage () {
+	checkWidget ();
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	return control.backgroundImage;
+}
+
 GdkColor getBgColor () {
 	int /*long*/ fontHandle = fontHandle ();
 	OS.gtk_widget_realize (fontHandle);
@@ -2071,6 +2094,13 @@
 		int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
 		OS.gtk_im_context_set_client_window (imHandle, window);
 	}
+	if ((state & PARENT_BACKGROUND) != 0 && (state & BACKGROUND) == 0 && backgroundImage == null) {
+		setParentBackground ();
+	}
+	if (backgroundImage != null) {
+		int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
+		if (window != 0) OS.gdk_window_set_back_pixmap (window, backgroundImage.pixmap, false);
+	}
 	return 0;
 }
 
@@ -2095,6 +2125,17 @@
 	return sendHelpEvent (helpType) ? 1 : 0;
 }
 
+int /*long*/ gtk_style_set (int /*long*/ widget, int /*long*/ previousStyle) {
+	if ((state & PARENT_BACKGROUND) != 0 && (state & BACKGROUND) == 0 && backgroundImage == null) {
+		setParentBackground ();
+	}
+	if (backgroundImage != null) {
+		int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
+		if (window != 0) OS.gdk_window_set_back_pixmap (window, backgroundImage.pixmap, false);
+	}
+	return 0;
+}
+
 int /*long*/ gtk_unrealize (int /*long*/ widget) {
 	int /*long*/ imHandle = imHandle ();
 	if (imHandle != 0) OS.gtk_im_context_set_client_window (imHandle, 0);
@@ -2150,8 +2191,10 @@
 		}
 		data.drawable = window;
 		data.device = display;
-		data.background = getBackgroundColor ();
 		data.foreground = getForegroundColor ();
+		Control control = findBackgroundControl ();
+		if (control == null) control = this;
+		data.background = control.getBackgroundColor ();
 		data.font = font != null ? font.handle : defaultFont (); 
 	}	
 	return gdkGC;
@@ -2342,10 +2385,7 @@
 //	checkWidget();
 	if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return;
 	forceResize ();
-	int /*long*/ paintHandle = paintHandle ();
-	int width = OS.GTK_WIDGET_WIDTH (paintHandle);
-	int height = OS.GTK_WIDGET_HEIGHT (paintHandle);
-	redrawWidget (0, 0, width, height, all);
+	redrawWidget (0, 0, 0, 0, true, all, false);
 }
 
 /**
@@ -2380,17 +2420,26 @@
 public void redraw (int x, int y, int width, int height, boolean all) {
 	checkWidget();
 	if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return;
-	redrawWidget (x, y, width, height, all);
+	redrawWidget (x, y, width, height, false, all, false);
 }
 
-void redrawWidget (int x, int y, int width, int height, boolean all) {
+void redrawChildren () {
+}
+
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean all, boolean trim) {
 	if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) == 0) return;
 	int /*long*/ window = paintWindow ();
 	GdkRectangle rect = new GdkRectangle ();
-	rect.x = x;
-	rect.y = y;
-	rect.width = width;
-	rect.height = height;
+	if (redrawAll) {
+		int /*long*/ widget = paintHandle ();
+		rect.width = OS.GTK_WIDGET_WIDTH (widget);
+		rect.height = OS.GTK_WIDGET_HEIGHT (widget);
+	} else {
+		rect.x = x;
+		rect.y = y;
+		rect.width = width;
+		rect.height = height;
+	}
 	OS.gdk_window_invalidate_rect (window, rect, all);
 }
 
@@ -2567,6 +2616,7 @@
 			state |= BACKGROUND;
 		}
 		setBackgroundColor (gdkColor);
+		redrawChildren ();
 	}
 }
 
@@ -2586,8 +2636,27 @@
 	OS.gtk_rc_style_set_color_flags (style, index, flags);
 	OS.gtk_widget_modify_style (handle, style);
 }
+
 void setBackgroundColor (GdkColor color) {
-	setBackgroundColor(handle, color);
+	setBackgroundColor (handle, color);
+}
+
+public void setBackgroundImage (Image image) {
+	checkWidget ();
+	if (image != null && image.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+	if (image == backgroundImage) return;
+	this.backgroundImage = image;
+	if (backgroundImage != null) {
+		int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
+		if (window != 0) {
+			OS.gdk_window_set_back_pixmap (window, backgroundImage.pixmap, false);
+		}
+		redrawWidget (0, 0, 0, 0, true, false, false);
+	} else {
+		int /*long*/ style = OS.gtk_widget_get_modifier_style (handle);
+		OS.gtk_widget_modify_style (handle, style);
+	}
+	redrawChildren ();
 }
 
 /**
@@ -2928,6 +2997,15 @@
 	return true;
 }
 
+void setParentBackground () {
+	int /*long*/ window = OS.GTK_WIDGET_WINDOW (handle);
+	if (window != 0) OS.gdk_window_set_back_pixmap (window, 0, true);
+	if (fixedHandle != 0) {
+		window = OS.GTK_WIDGET_WINDOW (fixedHandle);
+		if (window != 0) OS.gdk_window_set_back_pixmap (window, 0, true);
+	}
+}
+
 boolean setRadioSelection (boolean value) {
 	return false;
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
index a6ae545..37b126c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
@@ -3332,7 +3332,9 @@
 	int /*long*/ imHandle = control.imHandle ();
 	OS.gtk_im_context_get_preedit_string (imHandle, preeditString, pangoAttrs, null);
 	if (preeditString [0] != 0 && OS.strlen (preeditString [0]) > 0) {
-		OS.gtk_widget_modify_bg (preeditWindow,  OS.GTK_STATE_NORMAL, control.getBackgroundColor ());
+		Control widget = control.findBackgroundControl ();
+		if (widget == null) widget = control;
+		OS.gtk_widget_modify_bg (preeditWindow,  OS.GTK_STATE_NORMAL, widget.getBackgroundColor ());
 		OS.gtk_widget_modify_fg (preeditLabel,  OS.GTK_STATE_NORMAL, control.getForegroundColor ());		
 		OS.gtk_widget_modify_font (preeditLabel, control.getFontDescription ());
 		if (pangoAttrs [0] != 0) OS.gtk_label_set_attributes (preeditLabel, pangoAttrs[0]);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
index eeeafb7..01a91ad 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Scrollable.java
@@ -293,6 +293,28 @@
 	return true;
 }
 
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean all, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, all, trim);
+	if ((OS.GTK_WIDGET_FLAGS (handle) & OS.GTK_REALIZED) == 0) return;
+	if (!trim) return;
+	int /*long*/ topHandle = topHandle (), paintHandle = paintHandle ();
+	if (topHandle == paintHandle) return;
+	int /*long*/ window = OS.GTK_WIDGET_WINDOW (topHandle);
+	GdkRectangle rect = new GdkRectangle ();
+	if (redrawAll) {
+		rect.width = OS.GTK_WIDGET_WIDTH (topHandle);
+		rect.height = OS.GTK_WIDGET_HEIGHT (topHandle);
+	} else {
+		int [] destX = new int [1], destY = new int [1];
+		OS.gtk_widget_translate_coordinates (paintHandle, topHandle, x, y, destX, destY);
+		rect.x = destX [0];
+		rect.y = destY [0];
+		rect.width = width;
+		rect.height = height;
+	}
+	OS.gdk_window_invalidate_rect (window, rect, all);
+}
+
 void register () {
 	super.register ();
 	if (scrolledHandle != 0) display.addWidget (scrolledHandle, this);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
index 7bad728..d848907 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Shell.java
@@ -580,6 +580,10 @@
 	OS.gtk_widget_realize (shellHandle);
 }
 
+Control findBackgroundControl () {
+	return (state & BACKGROUND) != 0 || backgroundImage != null ? this : null;
+}
+
 Composite findDeferredControl () {
 	return layoutCount > 0 ? this : null;
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
index 26ec9fd..c3170b5 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Widget.java
@@ -74,20 +74,21 @@
 	static final int HIDDEN = 1<<11;
 	static final int FOREGROUND = 1<<12;
 	static final int BACKGROUND = 1<<13;
-	static final int FONT = 1<<14;
+	static final int PARENT_BACKGROUND = 1<<14;
+	static final int FONT = 1<<15;
 	
 	/* A layout was requested on this widget */
-	static final int LAYOUT_NEEDED	= 1<<15;
+	static final int LAYOUT_NEEDED	= 1<<16;
 	
 	/* The preferred size of a child has changed */
-	static final int LAYOUT_CHANGED = 1<<16;
+	static final int LAYOUT_CHANGED = 1<<17;
 	
 	/* A layout was requested in this widget hierachy */
-	static final int LAYOUT_CHILD = 1<<17;
+	static final int LAYOUT_CHILD = 1<<18;
 
 	/* More global state flags */
-	static final int RELEASED = 1<<18;
-	static final int DISPOSE_SENT = 1<<19;
+	static final int RELEASED = 1<<19;
+	static final int DISPOSE_SENT = 1<<20;
 	
 	/* Default size for widgets */
 	static final int DEFAULT_WIDTH	= 64;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GC.java
index 79a3e37..b4e368b 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GC.java
@@ -181,6 +181,11 @@
 	if (deltaX == 0 && deltaY == 0) return;
 	int xDisplay = data.display;
 	int xDrawable = data.drawable;
+	if (data.backgroundImage != null && paint) {
+		OS.XClearArea (xDisplay, xDrawable, x, y, width, height, true);
+		OS.XClearArea (xDisplay, xDrawable, destX, destY, width, height, true);
+		return;
+	}
 	if (data.image == null && paint) OS.XSetGraphicsExposures (xDisplay, handle, true);
 	OS.XCopyArea(xDisplay, xDrawable, xDrawable, handle, x, y, width, height, destX, destY);
 	if (data.image == null && paint) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GCData.java
index 8a16349..8c1a5fa 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GCData.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/graphics/GCData.java
@@ -31,6 +31,7 @@
 	public int drawable;
 	public int foreground = -1;
 	public int background = -1;
+	public Image backgroundImage;
 	public Pattern foregroundPattern;
 	public Pattern backgroundPattern;
 	public Font font;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Canvas.java
index 0ecf92d..d193db9 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Canvas.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Canvas.java
@@ -70,6 +70,12 @@
 public Canvas (Composite parent, int style) {
 	super (parent, style);
 }
+public void drawBackground (GC gc, int x, int y, int width, int height) {
+	checkWidget ();
+	if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+	if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+	super.drawBackground (gc, x, y, width, height);
+}
 /**
  * Returns the caret.
  * <p>
@@ -95,10 +101,10 @@
 Caret getIMCaret () {
 	return caret;
 }
-void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren) {
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
 	boolean isFocus = caret != null && caret.isFocusCaret ();
 	if (isFocus) caret.killFocus ();
-	super.redrawWidget (x, y, width, height, redrawAll, allChildren);
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
 	if (isFocus) caret.setFocus ();
 }
 
@@ -155,22 +161,29 @@
 		}
 		OS.XtFree (xEvent);
 	}
-	int xGC = OS.XCreateGC (xDisplay, xWindow, 0, null);
-	OS.XCopyArea (xDisplay, xWindow, xWindow, xGC, x, y, width, height, destX, destY);
-	OS.XFreeGC (xDisplay, xGC);
-	boolean disjoint = (destX + width < x) || (x + width < destX) || (destY + height < y) || (y + height < destY);
-	if (disjoint) {
-		OS.XClearArea (xDisplay, xWindow, x, y, width, height, true);
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	if (control.backgroundImage != null) {
+		redrawWidget (x, y, width, height, false, false, false);
+		redrawWidget (destX, destY, width, height, false, false, false);
 	} else {
-		if (deltaX != 0) {
-			int newX = destX - deltaX;
-			if (deltaX < 0) newX = destX + width;
-			OS.XClearArea (xDisplay, xWindow, newX, y, Math.abs (deltaX), height, true);
-		}
-		if (deltaY != 0) {
-			int newY = destY - deltaY;
-			if (deltaY < 0) newY = destY + height;
-			OS.XClearArea (xDisplay, xWindow, x, newY, width, Math.abs (deltaY), true);
+		int xGC = OS.XCreateGC (xDisplay, xWindow, 0, null);
+		OS.XCopyArea (xDisplay, xWindow, xWindow, xGC, x, y, width, height, destX, destY);
+		OS.XFreeGC (xDisplay, xGC);
+		boolean disjoint = (destX + width < x) || (x + width < destX) || (destY + height < y) || (y + height < destY);
+		if (disjoint) {
+			OS.XClearArea (xDisplay, xWindow, x, y, width, height, true);
+		} else {
+			if (deltaX != 0) {
+				int newX = destX - deltaX;
+				if (deltaX < 0) newX = destX + width;
+				OS.XClearArea (xDisplay, xWindow, newX, y, Math.abs (deltaX), height, true);
+			}
+			if (deltaY != 0) {
+				int newY = destY - deltaY;
+				if (deltaY < 0) newY = destY + height;
+				OS.XClearArea (xDisplay, xWindow, x, newY, width, Math.abs (deltaY), true);
+			}
 		}
 	}
 	if (all) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Caret.java
index 253651b..db91b50 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Caret.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Caret.java
@@ -93,10 +93,10 @@
 	int gc = OS.XCreateGC (xDisplay, window, 0, null);
 	int color;
 	if (OS.IsSunOS) {
-		int [] argList = {OS.XmNforeground, 0, OS.XmNbackground, 0};
-		OS.XtGetValues (handle, argList, argList.length / 2);
-		int foreground = argList [1];
-		int background = argList [3];
+		int foreground = parent.getForegroundPixel ();
+		Control control = parent.findBackgroundControl ();
+		if (control == null) control = parent;
+		int background = control.getBackgroundPixel ();
 		color = foreground ^ background;
 	} else {
 		int screenNum = OS.XDefaultScreen (xDisplay);	
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Composite.java
index fe49379..d49a1f2 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Composite.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Composite.java
@@ -284,6 +284,33 @@
 	super.deregister ();
 	if (focusHandle != 0) display.removeWidget (focusHandle);
 }
+void drawBackground (GC gc, int x, int y, int width, int height) {
+	int xDisplay = OS.XtDisplay (handle);
+	if (xDisplay == 0) return;
+	int xGC = gc.handle;
+	XGCValues values = new XGCValues();
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	if (control.backgroundImage != null) {
+		OS.XGetGCValues (xDisplay, xGC, OS.GCFillStyle | OS.GCTile | OS.GCTileStipXOrigin | OS.GCTileStipYOrigin, values);
+		short [] root_x = new short [1], root_y = new short [1];
+		OS.XtTranslateCoords (handle, (short) 0, (short) 0, root_x, root_y);
+		short [] control_x = new short [1], control_y = new short [1];
+		OS.XtTranslateCoords (control.handle, (short) 0, (short) 0, control_x, control_y);
+		int tileX = root_x[0] - control_x[0], tileY = root_y[0] - control_y[0];
+		OS.XSetFillStyle (xDisplay, xGC, OS.FillTiled);
+		OS.XSetTSOrigin (xDisplay, xGC, -tileX, -tileY);
+		OS.XSetTile (xDisplay, xGC, control.backgroundImage.pixmap);
+		gc.fillRectangle (x, y, width, height);
+		OS.XSetFillStyle (xDisplay, xGC, values.fill_style);
+		OS.XSetTSOrigin (xDisplay, xGC, values.ts_x_origin, values.ts_y_origin);
+	} else {
+		OS.XGetGCValues (xDisplay, xGC, OS.GCBackground, values);
+		gc.setBackground (control.getBackground ());
+		gc.fillRectangle (x, y, width, height);
+		OS.XSetBackground (xDisplay, xGC, values.background);
+	}
+}
 Composite findDeferredControl () {
 	return layoutCount > 0 ? this : parent.findDeferredControl ();
 }
@@ -798,18 +825,29 @@
 		}
 	}
 }
+void redrawChildren () {
+	super.redrawChildren ();
+	Control [] children = _getChildren ();
+	for (int i = 0; i < children.length; i++) {
+		Control child = children [i];
+		if ((child.state & PARENT_BACKGROUND) != 0) {
+			child.redrawWidget (0, 0, 0, 0, true, false, true);
+			child.redrawChildren ();
+		}
+	}
+}
 void register () {
 	super.register ();
 	if (focusHandle != 0) display.addWidget (focusHandle, this);
 }
-void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren) {
-	super.redrawWidget (x, y, width, height, redrawAll, allChildren);
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
 	if (!allChildren) return;
 	Control [] children = _getChildren ();
 	for (int i = 0; i < children.length; i++) {
 		Control child = children [i];
 		Point location = child.getClientLocation ();
-		child.redrawWidget (x - location.x, y - location.y, width, height, redrawAll, allChildren);
+		child.redrawWidget (x - location.x, y - location.y, width, height, redrawAll, allChildren, true);
 	}
 }
 void release (boolean destroy) {
@@ -1045,6 +1083,11 @@
 	} 
 	this.tabList = tabList;
 }
+void setParentBackground () {
+	super.setParentBackground ();	
+	if (scrolledHandle != 0) setParentBackground (scrolledHandle);
+	if (formHandle != 0) setParentBackground (formHandle);
+}
 boolean setScrollBarVisible (ScrollBar bar, boolean visible) {
 	boolean changed = super.setScrollBarVisible (bar, visible);
 	if (changed && layout != null) {
@@ -1200,7 +1243,8 @@
 		gc.setBackground (getBackground ());
 		gc.setFont (getFont ());
 		if ((style & SWT.NO_BACKGROUND) != 0) {
-			paintGC.copyArea(image, 0, 0);
+			/* This code is intentionaly commented because it is really slow to copy bits from the screen */
+//			paintGC.copyArea(image, 0, 0);
 		} else {
 			gc.fillRectangle(0, 0, width, height);
 		}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java
index c4adf8f..68b813e 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java
@@ -41,6 +41,7 @@
 	Composite parent;
 	Cursor cursor;
 	Menu menu;
+	Image backgroundImage;
 	Font font;
 	String toolTipText;
 	Object layoutData;
@@ -509,6 +510,10 @@
 void enableWidget (boolean enabled) {
 	enableHandle (enabled, handle);
 }
+Control findBackgroundControl () {
+	if ((state & BACKGROUND) != 0 || backgroundImage != null) return this;
+	return (state & PARENT_BACKGROUND) != 0 ? parent.findBackgroundControl () : null;
+}
 char findMnemonic (String string) {
 	int index = 0;
 	int length = string.length ();
@@ -624,7 +629,15 @@
  */
 public Color getBackground () {
 	checkWidget();
-	return Color.motif_new (display, getXColor (getBackgroundPixel ()));
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	return Color.motif_new (display, getXColor (control.getBackgroundPixel ()));
+}
+public Image getBackgroundImage () {
+	checkWidget ();
+	Control control = findBackgroundControl ();
+	if (control == null) control = this;
+	return control.backgroundImage;
 }
 int getBackgroundPixel () {
 	int [] argList = {OS.XmNbackground, 0};
@@ -1112,8 +1125,6 @@
 	int xGC = OS.XCreateGC (xDisplay, xWindow, 0, null);
 	if (xGC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
 	OS.XSetGraphicsExposures (xDisplay, xGC, false);
-	int [] argList = {OS.XmNforeground, 0, OS.XmNbackground, 0, OS.XmNcolormap, 0};
-	OS.XtGetValues (handle, argList, argList.length / 2);
 	if (data != null) {
 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
 		if ((data.style & mask) == 0) {
@@ -1122,10 +1133,15 @@
 		data.device = display;
 		data.display = xDisplay;
 		data.drawable = xWindow;
-		data.foreground = argList [1];
-		data.background = argList [3];
+		data.foreground = getForegroundPixel ();
+		Control control = findBackgroundControl ();
+		if (control == null) control = this;
+		data.background = control.getBackgroundPixel ();
+		data.backgroundImage = control.backgroundImage;
 		data.font = font;
-		data.colormap = argList [5];
+		int [] argList = {OS.XmNcolormap, 0};
+		OS.XtGetValues (handle, argList, argList.length / 2);
+		data.colormap = argList [1];
 	}
 	return xGC;
 }
@@ -1396,16 +1412,20 @@
 }
 void realizeChildren () {
 	if (isEnabled ()) {
-		if (cursor == null) return;
-		int xWindow = OS.XtWindow (handle);
-		if (xWindow == 0) return;
-		int xDisplay = OS.XtDisplay (handle);
-		if (xDisplay == 0) return;
-		OS.XDefineCursor (xDisplay, xWindow, cursor.handle);
-		OS.XFlush (xDisplay);
+		if (cursor != null) {
+			int xWindow = OS.XtWindow (handle);
+			if (xWindow == 0) return;
+			int xDisplay = OS.XtDisplay (handle);
+			if (xDisplay == 0) return;
+			OS.XDefineCursor (xDisplay, xWindow, cursor.handle);
+			OS.XFlush (xDisplay);
+		}
 	} else {
 		propagateWidget (false);
 	}
+	if ((state & PARENT_BACKGROUND) != 0) {
+		setParentBackground ();
+	}
 }
 /**
  * Causes the entire bounds of the receiver to be marked
@@ -1427,7 +1447,7 @@
  */
 public void redraw () {
 	checkWidget();
-	redrawWidget (0, 0, 0, 0, true, false);
+	redrawWidget (0, 0, 0, 0, true, false, false);
 }
 /**
  * Causes the rectangular area of the receiver specified by
@@ -1461,10 +1481,12 @@
 public void redraw (int x, int y, int width, int height, boolean all) {
 	checkWidget ();
 	if (width > 0 && height > 0) {
-		redrawWidget (x, y, width, height, false, all);
+		redrawWidget (x, y, width, height, false, all, false);
 	}
 }
-void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren) {
+void redrawChildren () {
+}
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
 	redrawHandle (x, y, width, height, redrawAll, handle);
 }
 void releaseHandle () {
@@ -1831,11 +1853,32 @@
 public void setBackground (Color color) {
 	checkWidget();
 	if (color == null) {
+		state &= ~BACKGROUND;
 		setBackgroundPixel (defaultBackground ());
 	} else {
 		if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+		state |= BACKGROUND;
 		setBackgroundPixel (color.handle.pixel);
 	}
+	if ((state & PARENT_BACKGROUND) != 0 && (state & BACKGROUND) == 0 && backgroundImage == null) {
+		setParentBackground ();
+		redrawWidget (0, 0, 0, 0, true, false, false);
+	}
+	redrawChildren ();
+}
+public void setBackgroundImage (Image image) {
+	checkWidget ();
+	if (image != null && image.isDisposed ()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+	if (image == backgroundImage) return;
+	this.backgroundImage = image;
+	int pixmap = image != null ? image.pixmap : OS.XmUNSPECIFIED_PIXMAP;
+	int [] argList = {OS.XmNbackgroundPixmap, pixmap};
+	OS.XtSetValues (handle, argList, argList.length / 2);
+	if ((state & PARENT_BACKGROUND) != 0 && (state & BACKGROUND) == 0 && backgroundImage == null) {
+		setParentBackground ();
+		redrawWidget (0, 0, 0, 0, true, false, false);
+	}
+	redrawChildren ();
 }
 void setBackgroundPixel (int pixel) {
 	int [] argList = {OS.XmNforeground, 0, OS.XmNhighlightColor, 0};
@@ -1870,7 +1913,13 @@
 		}
 		OS.XtConfigureWidget (topHandle, x, y, width, height, argList [9]);
 		updateIM ();
-		if (!sameOrigin) sendEvent (SWT.Move);
+		if (!sameOrigin) {
+			Control control = findBackgroundControl ();
+			if (control != null && control.backgroundImage != null) {
+				if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true);
+			}
+			sendEvent (SWT.Move);
+		}
 		if (!sameExtent) sendEvent (SWT.Resize);
 		return true;
 	}
@@ -1879,6 +1928,10 @@
 		OS.XtGetValues (topHandle, argList, argList.length / 2);
 		if (x == (short) argList [1] && y == (short) argList [3]) return false;
 		OS.XtMoveWidget (topHandle, x, y);
+		Control control = findBackgroundControl ();
+		if (control != null && control.backgroundImage != null) {
+			if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true);
+		}
 		sendEvent (SWT.Move);
 		return true;
 	}
@@ -2136,9 +2189,11 @@
 public void setForeground (Color color) {
 	checkWidget();
 	if (color == null) {
+		state &= ~FOREGROUND;
 		setForegroundPixel (defaultForeground ());
 	} else {
 		if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+		state |= FOREGROUND;
 		setForegroundPixel (color.handle.pixel);
 	}
 }
@@ -2253,6 +2308,16 @@
 	if (parent.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
 	return false;
 }
+void setParentBackground () {
+	setParentBackground (handle);
+}
+void setParentBackground (int widget) {
+	int xDisplay = OS.XtDisplay (widget);
+	if (xDisplay == 0) return;
+	int xWindow = OS.XtWindow (widget);
+	if (xWindow == 0) return;
+	OS.XSetWindowBackgroundPixmap (xDisplay, xWindow, OS.ParentRelative);
+}
 void setParentTraversal () {
 	/*
 	* When the parent was created with NO_FOCUS, XmNtraversalOn was
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Group.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Group.java
index 766b078..73cdb23 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Group.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Group.java
@@ -245,8 +245,8 @@
 	super.propagateWidget (enabled);
 	propagateHandle (enabled, labelHandle, OS.None);
 }
-void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren) {
-	super.redrawWidget (x, y, width, height, redrawAll, allChildren);
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
 	short [] root_x = new short [1], root_y = new short [1];
 	OS.XtTranslateCoords (handle, (short) x, (short) y, root_x, root_y);
 	short [] label_x = new short [1], label_y = new short [1];
@@ -273,6 +273,10 @@
 	OS.XtSetValues (labelHandle, argList, argList.length / 2);
 	super.setForegroundPixel (pixel);
 }
+void setParentBackground () {
+	super.setParentBackground ();
+	if (labelHandle != 0) setParentBackground (labelHandle);
+}
 /**
  * Sets the receiver's text, which is the string that will
  * be displayed as the receiver's <em>title</em>, to the argument,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Label.java
index b1b9ff2..70e7d5a 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Label.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Label.java
@@ -403,6 +403,14 @@
 	super.realizeChildren ();
 	setBitGravity ();
 }
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
+	short [] root_x = new short [1], root_y = new short [1];
+	OS.XtTranslateCoords (handle, (short) x, (short) y, root_x, root_y);
+	short [] label_x = new short [1], label_y = new short [1];
+	OS.XtTranslateCoords (formHandle, (short) 0, (short) 0, label_x, label_y);
+	redrawHandle (root_x [0] - label_x [0], root_y [0] - label_y [0], width, height, redrawAll, formHandle);
+}
 void register () {
 	super.register ();
 	if (formHandle != 0) display.addWidget (formHandle, this);
@@ -570,6 +578,10 @@
 	if ((style & SWT.SEPARATOR) != 0) return;
 	setBitmap (this.image = image);
 }
+void setParentBackground () {
+	super.setParentBackground ();
+	if (formHandle != 0) setParentBackground (formHandle);
+}
 /**
  * Sets the receiver's text.
  * <p>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Sash.java
index 060da91..8763622 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Sash.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Sash.java
@@ -140,9 +140,11 @@
 	if (display == 0) return;
 	int window = OS.XtWindow (parent.handle);
 	if (window == 0) return;
-	int [] argList = {OS.XmNforeground, 0, OS.XmNbackground, 0};
-	OS.XtGetValues (parent.handle, argList, argList.length / 2);
-	int color = argList [1] ^ argList [3];
+	int foreground = parent.getForegroundPixel ();
+	Control control = parent.findBackgroundControl ();
+	if (control == null) control = parent;
+	int background = control.getBackgroundPixel ();
+	int color = foreground ^ background;
 	byte [] bits = {-86, 85, -86, 85, -86, 85, -86, 85};
 	int stipplePixmap = OS.XCreateBitmapFromData (display, window, bits, 8, 8);
 	int gc = OS.XCreateGC (display, window, 0, null);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Scrollable.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Scrollable.java
index 1c8bd26..0e15901 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Scrollable.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Scrollable.java
@@ -268,6 +268,35 @@
 //		if (argList1 [3] != 0) OS.XmChangeColor (argList1 [3], pixel);
 //	}
 }
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
+	if (!trim) return;
+	if (formHandle == 0 && scrolledHandle == 0) return;
+	short [] root_x = new short [1], root_y = new short [1];
+	OS.XtTranslateCoords (handle, (short) x, (short) y, root_x, root_y);
+	if (formHandle != 0) {
+		short [] form_x = new short [1], form_y = new short [1];
+		OS.XtTranslateCoords (formHandle, (short) 0, (short) 0, form_x, form_y);
+		redrawHandle (root_x [0] - form_x [0], root_y [0] - form_y [0], width, height, redrawAll, formHandle);
+	}
+	if (scrolledHandle != 0) {
+		short [] scrolled_x = new short [1], scrolled_y = new short [1];
+		OS.XtTranslateCoords (scrolledHandle, (short) 0, (short) 0, scrolled_x, scrolled_y);
+		redrawHandle (root_x [0] - scrolled_x [0], root_y [0] - scrolled_y [0], width, height, redrawAll, scrolledHandle);
+		if (horizontalBar != null && horizontalBar.getVisible ()) {
+			int horizontalHandle = horizontalBar.handle;
+			short [] hscroll_x = new short [1], hscroll_y = new short [1];
+			OS.XtTranslateCoords (horizontalHandle, (short) 0, (short) 0, hscroll_x, hscroll_y);
+			redrawHandle (root_x [0] - hscroll_x [0], root_y [0] - hscroll_y [0], width, height, redrawAll, horizontalHandle);
+		}
+		if (verticalBar != null && verticalBar.getVisible ()) {
+			int verticalHandle = verticalBar.handle;
+			short [] vscroll_x = new short [1], vscroll_y = new short [1];
+			OS.XtTranslateCoords (verticalHandle, (short) 0, (short) 0, vscroll_x, vscroll_y);
+			redrawHandle (root_x [0] - vscroll_x [0], root_y [0] - vscroll_y [0], width, height, redrawAll, verticalHandle);
+		}
+	}
+}
 boolean setScrollBarVisible (ScrollBar bar, boolean visible) {
 	if (scrolledHandle == 0) return false;
 	int barHandle = bar.handle;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Shell.java
index b0cfd98..2656438 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Shell.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Shell.java
@@ -757,6 +757,9 @@
 	super.enableWidget (enabled);
 	enableHandle (enabled, shellHandle);
 }
+Control findBackgroundControl () {
+	return (state & BACKGROUND) != 0 || backgroundImage != null ? this : null;
+}
 Composite findDeferredControl () {
 	return layoutCount > 0 ? this : null;
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolBar.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolBar.java
index 0708a85..481ad7a 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolBar.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolBar.java
@@ -406,6 +406,28 @@
 		items [i].propagateWidget (enabled);
 	}
 }
+void realizeChildren () {
+	super.realizeChildren ();
+	if (items != null) {
+		for (int i=0; i<itemCount; i++) {
+			ToolItem item = items [i];
+			if (item != null && !item.isDisposed ()) {
+				item.realizeChildren ();
+			}
+		}
+	}
+}
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
+	if (items != null) {
+		for (int i=0; i<itemCount; i++) {
+			ToolItem item = items [i];
+			if (item != null && !item.isDisposed ()) {
+				item.redrawWidget (x, y, width, height, redrawAll, allChildren, true);
+			}
+		}
+	}
+}
 void relayout () {
 	if (drawCount > 0) return;
 	Rectangle rect = getClientArea ();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolItem.java
index 7c731da..00210de 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/ToolItem.java
@@ -193,8 +193,9 @@
 	};
 	handle = OS.XmCreateDrawnButton (parentHandle, null, argList, argList.length / 2);
 	if (handle == 0) error (SWT.ERROR_NO_HANDLES);
-	int pixel = parent.getBackgroundPixel ();
-	setBackgroundPixel (pixel);
+	Control control = parent.findBackgroundControl ();
+	if (control == null) control = parent;
+	setBackgroundPixel (parent.getBackgroundPixel ());
 }
 
 void click (boolean dropDown, int state) {
@@ -285,6 +286,18 @@
 	}
 	return new Point (width, height);
 }
+void createWidget (int index) {
+	super.createWidget (index);
+	int topHandle = topHandle ();
+	if (OS.XtIsRealized (topHandle)) {
+		/*
+		* Make sure that the widget has been properly realized
+		* because the widget was created after the parent
+		* has been realized.
+		*/
+		realizeChildren ();
+	}
+}
 void destroyWidget () {
 	parent.destroyItem (this);
 	super.destroyWidget ();
@@ -504,6 +517,11 @@
 void manageChildren () {
 	OS.XtManageChild (handle);
 }
+void realizeChildren () {
+	if ((parent.state & PARENT_BACKGROUND) != 0) {
+		setParentBackground ();
+	}
+}
 void redraw () {
 	int display = OS.XtDisplay (handle);
 	if (display == 0) return;
@@ -511,6 +529,9 @@
 	if (window == 0) return;
 	OS.XClearArea (display, window, 0, 0, 0, 0, true);
 }
+void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
+	redrawHandle (x, y, width, height, redrawAll, handle);
+}
 void releaseHandle () {
 	super.releaseHandle ();
 	parent = null;
@@ -716,6 +737,9 @@
 	parent.relayout();
 	redraw ();
 }
+void setParentBackground () {
+	parent.setParentBackground (handle);
+}
 boolean setRadioSelection (boolean value) {
 	if ((style & SWT.RADIO) == 0) return false;
 	if (getSelection () != value) {
@@ -1073,7 +1097,7 @@
 		textX -= 6;  imageX -=6;
 	}
 	if (textWidth > 0) {
-		int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC;
+		int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB | SWT.DRAW_MNEMONIC | SWT.DRAW_TRANSPARENT;
 		gc.drawText(text, textX, textY, flags);
 	}
 	if (imageWidth > 0) gc.drawImage(currentImage, imageX, imageY);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java
index ad244a8..b7a4b70 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java
@@ -296,9 +296,11 @@
 	if (parent != null) {
 		xWindow = OS.XtWindow (parent.handle);
 		if (xWindow == 0) return;
-		int [] argList = {OS.XmNforeground, 0, OS.XmNbackground, 0};
-		OS.XtGetValues (parent.handle, argList, argList.length / 2);
-		color = argList [1] ^ argList [3];
+		int foreground = parent.getForegroundPixel ();
+		Control control = parent.findBackgroundControl ();
+		if (control == null) control = parent;
+		int background = control.getBackgroundPixel ();
+		color = foreground ^ background;
 	}
 	int gc = OS.XCreateGC (xDisplay, xWindow, 0, null);
 	OS.XSetForeground (xDisplay, gc, color);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java
index b52f622..54db1ae 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java
@@ -58,19 +58,22 @@
 	static final int CANVAS = 1<<1;
 	static final int KEYED_DATA = 1<<2;
 	static final int FOCUS_FORCED = 1<<3;
+	static final int BACKGROUND = 1<<4;
+	static final int FOREGROUND = 1<<5;
+	static final int PARENT_BACKGROUND = 1<<6;
 	
 	/* A layout was requested on this widget */
-	static final int LAYOUT_NEEDED	= 1<<4;
+	static final int LAYOUT_NEEDED	= 1<<7;
 	
 	/* The preferred size of a child has changed */
-	static final int LAYOUT_CHANGED = 1<<5;
+	static final int LAYOUT_CHANGED = 1<<8;
 	
 	/* A layout was requested in this widget hierachy */
-	static final int LAYOUT_CHILD = 1<<6;
+	static final int LAYOUT_CHILD = 1<<9;
 
 	/* More global state flags */
-	static final int RELEASED = 1<<7;
-	static final int DISPOSE_SENT = 1<<8;
+	static final int RELEASED = 1<<10;
+	static final int DISPOSE_SENT = 1<<11;
 	
 	/* Default size for widgets */
 	static final int DEFAULT_WIDTH	= 64;