Merge branch 'master' into AERO_WORK
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
index 8001a64..edb5b6a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
@@ -5281,7 +5281,7 @@
 	int[] offsets = layout.getLineOffsets();
 	if (lineIndex != 0 && offsetInLine == offsets[lineIndex]) {
 		int lineY = layout.getLineBounds(lineIndex).y;
-		int caretY = getCaret().getLocation().y - topMargin - getLinePixel(getCaretLine());
+		int caretY = getCaret().getLocation().y - getLinePixel(getCaretLine());
 		if (lineY > caretY) lineIndex--;
 		caretAlignment = OFFSET_LEADING;
  	}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
index 3874254..b9d52f6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/DragSource.java
@@ -299,7 +299,7 @@
 	Image image = event.image; 
 	int /*long*/ context = OS.gtk_drag_begin(control.handle, targetList, actions, 1, 0);
 	if (context != 0 && image != null) {
-		int /*long*/ pixbuf = createPixbuf(image);
+		int /*long*/ pixbuf = ImageList.createPixbuf(image);
 		OS.gtk_drag_set_icon_pixbuf(context, pixbuf, 0, 0);
 		OS.g_object_unref(pixbuf);
 	}
@@ -574,60 +574,4 @@
 		OS.g_free(targets[i].target);
 	}
 }
-
-static int /*long*/ createPixbuf(Image image) {
-	int [] w = new int [1], h = new int [1];
- 	OS.gdk_drawable_get_size (image.pixmap, w, h);
-	int /*long*/ colormap = OS.gdk_colormap_get_system ();
-	int /*long*/ pixbuf;
-	boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1;
-	if (hasMask) {
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]);
-		if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]);
-		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
-		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
-		byte[] line = new byte[stride];
-		int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
-		int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
-		byte[] maskLine = new byte[maskStride];
-		for (int y=0; y<h[0]; y++) {
-			int /*long*/ offset = pixels + (y * stride);
-			OS.memmove(line, offset, stride);
-			int /*long*/ maskOffset = maskPixels + (y * maskStride);
-			OS.memmove(maskLine, maskOffset, maskStride);
-			for (int x=0; x<w[0]; x++) {
-				if (maskLine[x * 3] == 0) {
-					line[x * 4 + 3] = 0;
-				}
-			}
-			OS.memmove(offset, line, stride);
-		}
-		OS.g_object_unref(maskPixbuf);
-	} else {
-		ImageData data = image.getImageData ();
-		boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA;
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		if (hasAlpha) {
-			byte [] alpha = data.alphaData;
-			int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
-			int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
-			byte [] line = new byte [stride];
-			for (int y = 0; y < h [0]; y++) {
-				int /*long*/ offset = pixels + (y * stride);
-				OS.memmove (line, offset, stride);
-				for (int x = 0; x < w [0]; x++) {
-					line [x*4+3] = alpha [y*w [0]+x];
-				}
-				OS.memmove (offset, line, stride);
-			}
-		}
-	}
-	return pixbuf;
-}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java
index c4875c1..fb8d700 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/ImageTransfer.java
@@ -12,7 +12,7 @@
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.*;
-import org.eclipse.swt.internal.Converter;
+import org.eclipse.swt.internal.*;
 import org.eclipse.swt.internal.gtk.*;
 import org.eclipse.swt.widgets.*;
 
@@ -89,37 +89,32 @@
 	ImageData imgData = (ImageData)object;
 	if (imgData == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	Image image = new Image(Display.getCurrent(), imgData);	
-	int /*long*/ pixmap = image.pixmap; 
- 	int width = imgData.width;
- 	int height = imgData.height;  	
- 	int /*long*/ pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, true, 8, width, height);
-	if (pixbuf == 0) SWT.error(SWT.ERROR_NO_HANDLES);
-	int /*long*/ colormap = OS.gdk_colormap_get_system();
-	OS.gdk_pixbuf_get_from_drawable(pixbuf, pixmap, colormap, 0, 0, 0, 0, width, height);	
-	
-	String typeStr = "";
-	if (transferData.type ==  JPEG_ID) typeStr = "jpeg";
-	if (transferData.type ==  PNG_ID) typeStr = "png";
-	if (transferData.type ==  BMP_ID) typeStr = "bmp";
-	if (transferData.type ==  EPS_ID) typeStr = "eps";
-	if (transferData.type ==  PCX_ID) typeStr = "pcx";
-	if (transferData.type ==  PPM_ID) typeStr = "ppm";
-	if (transferData.type ==  RGB_ID) typeStr = "rgb";
-	if (transferData.type ==  TGA_ID) typeStr = "tga";
-	if (transferData.type ==  XBM_ID) typeStr = "xbm";
-	if (transferData.type ==  XPM_ID) typeStr = "xpm";
-	if (transferData.type ==  XV_ID) typeStr = "xv";
-	byte[] type = Converter.wcsToMbcs(null, typeStr , true);
-	int /*long*/ [] buffer = new int /*long*/ [1];
-	int /*long*/ [] len = new int /*long*/ [1];
-	if (type == null) return;
-	OS.gdk_pixbuf_save_to_bufferv(pixbuf, buffer, len, type, null, null, null);
-	OS.g_object_unref(pixbuf);
+ 	int /*long*/ pixbuf = ImageList.createPixbuf(image);
+	if (pixbuf != 0) {
+		String typeStr = "";
+		if (transferData.type ==  JPEG_ID) typeStr = "jpeg";
+		else if (transferData.type ==  PNG_ID) typeStr = "png";
+		else if (transferData.type ==  BMP_ID) typeStr = "bmp";
+		else if (transferData.type ==  EPS_ID) typeStr = "eps";
+		else if (transferData.type ==  PCX_ID) typeStr = "pcx";
+		else if (transferData.type ==  PPM_ID) typeStr = "ppm";
+		else if (transferData.type ==  RGB_ID) typeStr = "rgb";
+		else if (transferData.type ==  TGA_ID) typeStr = "tga";
+		else if (transferData.type ==  XBM_ID) typeStr = "xbm";
+		else if (transferData.type ==  XPM_ID) typeStr = "xpm";
+		else if (transferData.type ==  XV_ID) typeStr = "xv";
+		byte[] type = Converter.wcsToMbcs(null, typeStr , true);
+		int /*long*/ [] buffer = new int /*long*/ [1];
+		int /*long*/ [] len = new int /*long*/ [1];
+		if (type == null) return;
+		OS.gdk_pixbuf_save_to_bufferv(pixbuf, buffer, len, type, null, null, null);
+		OS.g_object_unref(pixbuf);
+		transferData.pValue = buffer[0];
+		transferData.length = (int)(len[0] + 3) / 4 * 4;
+		transferData.result = 1;
+		transferData.format = 32;
+	}
 	image.dispose();
-	transferData.pValue = buffer[0];
-	transferData.length = (int)(len[0] + 3) / 4 * 4;
-	transferData.result = 1;
-	transferData.format = 32;
 }
 
 /**
@@ -134,22 +129,20 @@
  */
 public Object nativeToJava(TransferData transferData) {
 	ImageData imgData = null;
-	if (transferData.length > 0)
-	{
+	if (transferData.length > 0) {
 		int /*long*/ loader = OS.gdk_pixbuf_loader_new();
-		OS.gdk_pixbuf_loader_write(loader, transferData.pValue, transferData.length, null);
-		OS.gdk_pixbuf_loader_close(loader, null);
-		int /*long*/ pixbuf = OS.gdk_pixbuf_loader_get_pixbuf(loader);
-		if (pixbuf != 0) {
-			int /*long*/ [] pixmap_return = new int /*long*/ [1];
-			OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, null, 0);
-			int /*long*/ handle = pixmap_return[0];
-			if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		try {
+			OS.gdk_pixbuf_loader_write(loader, transferData.pValue, transferData.length, null);
+			OS.gdk_pixbuf_loader_close(loader, null);
+			int /*long*/ pixbuf = OS.gdk_pixbuf_loader_get_pixbuf(loader);
+			if (pixbuf != 0) {
+				Image img = Image.gtk_new_from_pixbuf(Display.getCurrent(), SWT.BITMAP, pixbuf);
+				imgData = img.getImageData();
+				img.dispose();
+			}		
+		} finally {
 			OS.g_object_unref(loader);
-			Image img = Image.gtk_new(Display.getCurrent(), SWT.BITMAP, handle, 0);		
-			imgData = img.getImageData();
-			img.dispose();
-		}		
+		}
 	}
 	return imgData;
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java
index dc77be2..5eeddf3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TableDragSourceEffect.java
@@ -81,6 +81,8 @@
 		
 		Table table = (Table) control;
 		if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) return null;
+		//TODO: Use Cairo
+		if (OS.USE_CAIRO) return null;
 		//TEMPORARY CODE
 		if (table.isListening(SWT.EraseItem) || table.isListening (SWT.PaintItem)) return null;
 		/*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java
index 586fb56..fa475d2 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/TreeDragSourceEffect.java
@@ -80,6 +80,8 @@
 		
 		Tree tree = (Tree) control;
 		if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) return null;
+		//TODO: Use Cairo
+		if (OS.USE_CAIRO) return null;
 		//TEMPORARY CODE
 		if (tree.isListening(SWT.EraseItem) || tree.isListening (SWT.PaintItem)) return null;
 		/*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo.c b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo.c
index a7e45be..dc65b24 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo.c
@@ -15,7 +15,7 @@
  *
  * IBM
  * -  Binding to permit interfacing between Cairo and SWT
- * -  Copyright (C) 2005, 2011 IBM Corp.  All Rights Reserved.
+ * -  Copyright (C) 2005, 2012 IBM Corp.  All Rights Reserved.
  *
  * ***** END LICENSE BLOCK ***** */
 
@@ -298,6 +298,26 @@
 }
 #endif
 
+#ifndef NO__1cairo_1format_1stride_1for_1width
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1format_1stride_1for_1width)
+	(JNIEnv *env, jclass that, jint arg0, jint arg1)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1format_1stride_1for_1width_FUNC);
+/*
+	rc = (jint)cairo_format_stride_for_width(arg0, arg1);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_format_stride_for_width)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(jint, jint))fp)(arg0, arg1);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1format_1stride_1for_1width_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1cairo_1get_1antialias
 JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1get_1antialias)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -539,6 +559,46 @@
 }
 #endif
 
+#ifndef NO__1cairo_1image_1surface_1get_1data
+JNIEXPORT jintLong JNICALL Cairo_NATIVE(_1cairo_1image_1surface_1get_1data)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jintLong rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1image_1surface_1get_1data_FUNC);
+/*
+	rc = (jintLong)cairo_image_surface_get_data((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_image_surface_get_data)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1image_1surface_1get_1data_FUNC);
+	return rc;
+}
+#endif
+
+#ifndef NO__1cairo_1image_1surface_1get_1format
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1image_1surface_1get_1format)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1image_1surface_1get_1format_FUNC);
+/*
+	rc = (jint)cairo_image_surface_get_format((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_image_surface_get_format)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1image_1surface_1get_1format_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1cairo_1image_1surface_1get_1height
 JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1image_1surface_1get_1height)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -551,6 +611,26 @@
 }
 #endif
 
+#ifndef NO__1cairo_1image_1surface_1get_1stride
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1image_1surface_1get_1stride)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1image_1surface_1get_1stride_FUNC);
+/*
+	rc = (jint)cairo_image_surface_get_stride((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_image_surface_get_stride)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1image_1surface_1get_1stride_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1cairo_1image_1surface_1get_1width
 JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1image_1surface_1get_1width)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -1021,6 +1101,24 @@
 }
 #endif
 
+#ifndef NO__1cairo_1pop_1group_1to_1source
+JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1pop_1group_1to_1source)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1pop_1group_1to_1source_FUNC);
+/*
+	cairo_pop_group_to_source((cairo_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_pop_group_to_source)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(cairo_t *))fp)((cairo_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1pop_1group_1to_1source_FUNC);
+}
+#endif
+
 #ifndef NO__1cairo_1ps_1surface_1set_1size
 JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1ps_1surface_1set_1size)
 	(JNIEnv *env, jclass that, jintLong arg0, jdouble arg1, jdouble arg2)
@@ -1039,6 +1137,24 @@
 }
 #endif
 
+#ifndef NO__1cairo_1push_1group
+JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1push_1group)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1push_1group_FUNC);
+/*
+	cairo_push_group((cairo_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_push_group)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(cairo_t *))fp)((cairo_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1push_1group_FUNC);
+}
+#endif
+
 #ifndef NO__1cairo_1rectangle
 JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1rectangle)
 	(JNIEnv *env, jclass that, jintLong arg0, jdouble arg1, jdouble arg2, jdouble arg3, jdouble arg4)
@@ -1480,6 +1596,36 @@
 }
 #endif
 
+#ifndef NO__1cairo_1surface_1flush
+JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1surface_1flush)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1surface_1flush_FUNC);
+	cairo_surface_flush((cairo_surface_t *)arg0);
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1surface_1flush_FUNC);
+}
+#endif
+
+#ifndef NO__1cairo_1surface_1get_1content
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1surface_1get_1content)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1surface_1get_1content_FUNC);
+/*
+	rc = (jint)cairo_surface_get_content((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_surface_get_content)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1surface_1get_1content_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1cairo_1surface_1get_1type
 JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1surface_1get_1type)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -1512,6 +1658,16 @@
 }
 #endif
 
+#ifndef NO__1cairo_1surface_1mark_1dirty
+JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1surface_1mark_1dirty)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1surface_1mark_1dirty_FUNC);
+	cairo_surface_mark_dirty((cairo_surface_t *)arg0);
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1surface_1mark_1dirty_FUNC);
+}
+#endif
+
 #ifndef NO__1cairo_1surface_1reference
 JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1surface_1reference)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -1675,6 +1831,66 @@
 }
 #endif
 
+#ifndef NO__1cairo_1xlib_1surface_1get_1drawable
+JNIEXPORT jintLong JNICALL Cairo_NATIVE(_1cairo_1xlib_1surface_1get_1drawable)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jintLong rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1xlib_1surface_1get_1drawable_FUNC);
+/*
+	rc = (jintLong)cairo_xlib_surface_get_drawable((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_xlib_surface_get_drawable)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1xlib_1surface_1get_1drawable_FUNC);
+	return rc;
+}
+#endif
+
+#ifndef NO__1cairo_1xlib_1surface_1get_1height
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1xlib_1surface_1get_1height)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1xlib_1surface_1get_1height_FUNC);
+/*
+	rc = (jint)cairo_xlib_surface_get_height((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_xlib_surface_get_height)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1xlib_1surface_1get_1height_FUNC);
+	return rc;
+}
+#endif
+
+#ifndef NO__1cairo_1xlib_1surface_1get_1width
+JNIEXPORT jint JNICALL Cairo_NATIVE(_1cairo_1xlib_1surface_1get_1width)
+	(JNIEnv *env, jclass that, jintLong arg0)
+{
+	jint rc = 0;
+	Cairo_NATIVE_ENTER(env, that, _1cairo_1xlib_1surface_1get_1width_FUNC);
+/*
+	rc = (jint)cairo_xlib_surface_get_width((cairo_surface_t *)arg0);
+*/
+	{
+		Cairo_LOAD_FUNCTION(fp, cairo_xlib_surface_get_width)
+		if (fp) {
+			rc = (jint)((jint (CALLING_CONVENTION*)(cairo_surface_t *))fp)((cairo_surface_t *)arg0);
+		}
+	}
+	Cairo_NATIVE_EXIT(env, that, _1cairo_1xlib_1surface_1get_1width_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1cairo_1xlib_1surface_1set_1size
 JNIEXPORT void JNICALL Cairo_NATIVE(_1cairo_1xlib_1surface_1set_1size)
 	(JNIEnv *env, jclass that, jintLong arg0, jint arg1, jint arg2)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_custom.h
index 0eb3d23..1655d4b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_custom.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_custom.h
@@ -28,7 +28,17 @@
 #define LIB_CAIRO "libcairo.so.2"
 #endif
 
+#define cairo_format_stride_for_width_LIB LIB_CAIRO
 #define cairo_pdf_surface_set_size_LIB LIB_CAIRO
 #define cairo_ps_surface_set_size_LIB LIB_CAIRO
 #define cairo_surface_set_fallback_resolution_LIB LIB_CAIRO
 #define cairo_surface_get_type_LIB LIB_CAIRO
+#define cairo_image_surface_get_data_LIB LIB_CAIRO
+#define cairo_image_surface_get_format_LIB LIB_CAIRO
+#define cairo_image_surface_get_stride_LIB LIB_CAIRO
+#define cairo_xlib_surface_get_drawable_LIB LIB_CAIRO
+#define cairo_xlib_surface_get_height_LIB LIB_CAIRO
+#define cairo_xlib_surface_get_width_LIB LIB_CAIRO
+#define cairo_surface_get_content_LIB LIB_CAIRO
+#define cairo_push_group_LIB LIB_CAIRO
+#define cairo_pop_group_to_source_LIB LIB_CAIRO
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.c
index b387ce3..67b21fe 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.c
@@ -15,7 +15,7 @@
  *
  * IBM
  * -  Binding to permit interfacing between Cairo and SWT
- * -  Copyright (C) 2005, 2009 IBM Corp.  All Rights Reserved.
+ * -  Copyright (C) 2005, 2012 IBM Corp.  All Rights Reserved.
  *
  * ***** END LICENSE BLOCK ***** */
 
@@ -24,8 +24,8 @@
 
 #ifdef NATIVE_STATS
 
-int Cairo_nativeFunctionCount = 145;
-int Cairo_nativeFunctionCallCount[145];
+int Cairo_nativeFunctionCount = 157;
+int Cairo_nativeFunctionCallCount[157];
 char * Cairo_nativeFunctionNames[] = {
 	"CAIRO_1VERSION_1ENCODE",
 	"_1cairo_1append_1path",
@@ -50,6 +50,7 @@
 	"_1cairo_1font_1options_1destroy",
 	"_1cairo_1font_1options_1get_1antialias",
 	"_1cairo_1font_1options_1set_1antialias",
+	"_1cairo_1format_1stride_1for_1width",
 	"_1cairo_1get_1antialias",
 	"_1cairo_1get_1current_1point",
 	"_1cairo_1get_1fill_1rule",
@@ -70,7 +71,10 @@
 	"_1cairo_1identity_1matrix",
 	"_1cairo_1image_1surface_1create",
 	"_1cairo_1image_1surface_1create_1for_1data",
+	"_1cairo_1image_1surface_1get_1data",
+	"_1cairo_1image_1surface_1get_1format",
 	"_1cairo_1image_1surface_1get_1height",
+	"_1cairo_1image_1surface_1get_1stride",
 	"_1cairo_1image_1surface_1get_1width",
 	"_1cairo_1in_1fill",
 	"_1cairo_1in_1stroke",
@@ -108,7 +112,9 @@
 	"_1cairo_1pattern_1set_1filter",
 	"_1cairo_1pattern_1set_1matrix",
 	"_1cairo_1pdf_1surface_1set_1size",
+	"_1cairo_1pop_1group_1to_1source",
 	"_1cairo_1ps_1surface_1set_1size",
+	"_1cairo_1push_1group",
 	"_1cairo_1rectangle",
 	"_1cairo_1reference",
 	"_1cairo_1rel_1curve_1to",
@@ -149,8 +155,11 @@
 	"_1cairo_1surface_1create_1similar",
 	"_1cairo_1surface_1destroy",
 	"_1cairo_1surface_1finish",
+	"_1cairo_1surface_1flush",
+	"_1cairo_1surface_1get_1content",
 	"_1cairo_1surface_1get_1type",
 	"_1cairo_1surface_1get_1user_1data",
+	"_1cairo_1surface_1mark_1dirty",
 	"_1cairo_1surface_1reference",
 	"_1cairo_1surface_1set_1device_1offset",
 	"_1cairo_1surface_1set_1fallback_1resolution",
@@ -163,6 +172,9 @@
 	"_1cairo_1user_1to_1device_1distance",
 	"_1cairo_1xlib_1surface_1create",
 	"_1cairo_1xlib_1surface_1create_1for_1bitmap",
+	"_1cairo_1xlib_1surface_1get_1drawable",
+	"_1cairo_1xlib_1surface_1get_1height",
+	"_1cairo_1xlib_1surface_1get_1width",
 	"_1cairo_1xlib_1surface_1set_1size",
 	"cairo_1font_1extents_1t_1sizeof",
 	"cairo_1path_1data_1t_1sizeof",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.h
index f5f3bbf..62206dc 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/library/cairo_stats.h
@@ -15,7 +15,7 @@
  *
  * IBM
  * -  Binding to permit interfacing between Cairo and SWT
- * -  Copyright (C) 2005, 2009 IBM Corp.  All Rights Reserved.
+ * -  Copyright (C) 2005, 2012 IBM Corp.  All Rights Reserved.
  *
  * ***** END LICENSE BLOCK ***** */
 
@@ -58,6 +58,7 @@
 	_1cairo_1font_1options_1destroy_FUNC,
 	_1cairo_1font_1options_1get_1antialias_FUNC,
 	_1cairo_1font_1options_1set_1antialias_FUNC,
+	_1cairo_1format_1stride_1for_1width_FUNC,
 	_1cairo_1get_1antialias_FUNC,
 	_1cairo_1get_1current_1point_FUNC,
 	_1cairo_1get_1fill_1rule_FUNC,
@@ -78,7 +79,10 @@
 	_1cairo_1identity_1matrix_FUNC,
 	_1cairo_1image_1surface_1create_FUNC,
 	_1cairo_1image_1surface_1create_1for_1data_FUNC,
+	_1cairo_1image_1surface_1get_1data_FUNC,
+	_1cairo_1image_1surface_1get_1format_FUNC,
 	_1cairo_1image_1surface_1get_1height_FUNC,
+	_1cairo_1image_1surface_1get_1stride_FUNC,
 	_1cairo_1image_1surface_1get_1width_FUNC,
 	_1cairo_1in_1fill_FUNC,
 	_1cairo_1in_1stroke_FUNC,
@@ -116,7 +120,9 @@
 	_1cairo_1pattern_1set_1filter_FUNC,
 	_1cairo_1pattern_1set_1matrix_FUNC,
 	_1cairo_1pdf_1surface_1set_1size_FUNC,
+	_1cairo_1pop_1group_1to_1source_FUNC,
 	_1cairo_1ps_1surface_1set_1size_FUNC,
+	_1cairo_1push_1group_FUNC,
 	_1cairo_1rectangle_FUNC,
 	_1cairo_1reference_FUNC,
 	_1cairo_1rel_1curve_1to_FUNC,
@@ -157,8 +163,11 @@
 	_1cairo_1surface_1create_1similar_FUNC,
 	_1cairo_1surface_1destroy_FUNC,
 	_1cairo_1surface_1finish_FUNC,
+	_1cairo_1surface_1flush_FUNC,
+	_1cairo_1surface_1get_1content_FUNC,
 	_1cairo_1surface_1get_1type_FUNC,
 	_1cairo_1surface_1get_1user_1data_FUNC,
+	_1cairo_1surface_1mark_1dirty_FUNC,
 	_1cairo_1surface_1reference_FUNC,
 	_1cairo_1surface_1set_1device_1offset_FUNC,
 	_1cairo_1surface_1set_1fallback_1resolution_FUNC,
@@ -171,6 +180,9 @@
 	_1cairo_1user_1to_1device_1distance_FUNC,
 	_1cairo_1xlib_1surface_1create_FUNC,
 	_1cairo_1xlib_1surface_1create_1for_1bitmap_FUNC,
+	_1cairo_1xlib_1surface_1get_1drawable_FUNC,
+	_1cairo_1xlib_1surface_1get_1height_FUNC,
+	_1cairo_1xlib_1surface_1get_1width_FUNC,
 	_1cairo_1xlib_1surface_1set_1size_FUNC,
 	cairo_1font_1extents_1t_1sizeof_FUNC,
 	cairo_1path_1data_1t_1sizeof_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/org/eclipse/swt/internal/cairo/Cairo.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/org/eclipse/swt/internal/cairo/Cairo.java
index 8836edd..1314128 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/org/eclipse/swt/internal/cairo/Cairo.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cairo/org/eclipse/swt/internal/cairo/Cairo.java
@@ -31,25 +31,17 @@
 	public static final int CAIRO_ANTIALIAS_DEFAULT = 0;
 	public static final int CAIRO_ANTIALIAS_NONE = 1;
 	public static final int CAIRO_ANTIALIAS_GRAY = 2;
-	public static final int CAIRO_ANTIALIAS_SUBPIXEL = 3;
+	public static final int CAIRO_ANTIALIAS_SUBPIXEL = 3;   
+	public static final int CAIRO_CONTENT_COLOR = 0x1000;
+	public static final int CAIRO_CONTENT_ALPHA = 0x2000;
+	public static final int CAIRO_CONTENT_COLOR_ALPHA = 0x3000;
 	public static final int CAIRO_FORMAT_ARGB32 = 0;
 	public static final int CAIRO_FORMAT_RGB24 = 1;
 	public static final int CAIRO_FORMAT_A8 = 2;
 	public static final int CAIRO_FORMAT_A1 = 3;
-	public static final int CAIRO_OPERATOR_CLEAR = 0;
-	public static final int CAIRO_OPERATOR_SRC = 1;
-	public static final int CAIRO_OPERATOR_DST = 2;
-	public static final int CAIRO_OPERATOR_OVER = 3;
-	public static final int CAIRO_OPERATOR_OVER_REVERSE = 4;
-	public static final int CAIRO_OPERATOR_IN = 5;
-	public static final int CAIRO_OPERATOR_IN_REVERSE = 6;
-	public static final int CAIRO_OPERATOR_OUT = 7;
-	public static final int CAIRO_OPERATOR_OUT_REVERSE = 8;
-	public static final int CAIRO_OPERATOR_ATOP = 9;
-	public static final int CAIRO_OPERATOR_ATOP_REVERSE = 10;
-	public static final int CAIRO_OPERATOR_XOR = 11;
-	public static final int CAIRO_OPERATOR_ADD = 12;
-	public static final int CAIRO_OPERATOR_SATURATE = 13;
+	public static final int CAIRO_OPERATOR_SOURCE = 1;
+	public static final int CAIRO_OPERATOR_OVER = 2;
+	public static final int CAIRO_OPERATOR_DIFFERENCE = 23;
 	public static final int CAIRO_FILL_RULE_WINDING = 0;
 	public static final int CAIRO_FILL_RULE_EVEN_ODD = 1;
 	public static final int CAIRO_LINE_CAP_BUTT = 0;
@@ -327,6 +319,16 @@
 		lock.unlock();
 	}
 }
+/** @method flags=dynamic */
+public static final native int _cairo_format_stride_for_width(int format, int width);
+public static final int cairo_format_stride_for_width(int format, int width) {
+	lock.lock();
+	try {
+		return _cairo_format_stride_for_width(format, width);
+	} finally {
+		lock.unlock();
+	}
+}
 /** @param cr cast=(cairo_t *) */
 public static final native int _cairo_get_antialias(int /*long*/ cr);
 public static final int cairo_get_antialias(int /*long*/ cr) {
@@ -542,6 +544,32 @@
 		lock.unlock();
 	}
 }
+/**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int /*long*/ _cairo_image_surface_get_data(int /*long*/ surface);
+public static final int /*long*/ cairo_image_surface_get_data(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_image_surface_get_data(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int _cairo_image_surface_get_format(int /*long*/ surface);
+public static final int cairo_image_surface_get_format(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_image_surface_get_format(surface);
+	} finally {
+		lock.unlock();
+	}
+}
 /** @param surface cast=(cairo_surface_t *) */
 public static final native int _cairo_image_surface_get_height(int /*long*/ surface);
 public static final int cairo_image_surface_get_height(int /*long*/ surface) {
@@ -562,6 +590,19 @@
 		lock.unlock();
 	}
 }
+/**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int _cairo_image_surface_get_stride(int /*long*/ surface);
+public static final int cairo_image_surface_get_stride(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_image_surface_get_stride(surface);
+	} finally {
+		lock.unlock();
+	}
+}
 /** @param cr cast=(cairo_t *) */
 public static final native int _cairo_in_fill(int /*long*/ cr, double x, double y);
 public static final int cairo_in_fill(int /*long*/ cr, double x, double y) {
@@ -941,6 +982,32 @@
 }
 /**
  * @method flags=dynamic
+ * @param cairo cast=(cairo_t *)
+ */
+public static final native void _cairo_push_group(int /*long*/ cairo);
+public static final void cairo_push_group(int /*long*/ cairo) {
+	lock.lock();
+	try {
+		_cairo_push_group(cairo);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
+ * @method flags=dynamic
+ * @param cairo cast=(cairo_t *)
+ */
+public static final native void _cairo_pop_group_to_source(int /*long*/ cairo);
+public static final void cairo_pop_group_to_source(int /*long*/ cairo) {
+	lock.lock();
+	try {
+		_cairo_pop_group_to_source(cairo);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
+ * @method flags=dynamic
  * @param surface cast=(cairo_surface_t *)
  */
 public static final native void _cairo_ps_surface_set_size(int /*long*/ surface, double width_in_points, double height_in_points);
@@ -1369,6 +1436,16 @@
 	}
 }
 /** @param surface cast=(cairo_surface_t *) */
+public static final native void _cairo_surface_flush(int /*long*/ surface);
+public static final void cairo_surface_flush(int /*long*/ surface) {
+	lock.lock();
+	try {
+		_cairo_surface_flush(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/** @param surface cast=(cairo_surface_t *) */
 public static final native void _cairo_surface_finish(int /*long*/ surface);
 public static final void cairo_surface_finish(int /*long*/ surface) {
 	lock.lock();
@@ -1392,6 +1469,19 @@
 	}
 }
 /**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int _cairo_surface_get_content(int /*long*/ surface);
+public static final int cairo_surface_get_content(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_surface_get_content(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
  * @param surface cast=(cairo_surface_t *)
  * @param key cast=(cairo_user_data_key_t *)
  */
@@ -1405,6 +1495,16 @@
 	}
 }
 /** @param surface cast=(cairo_surface_t *) */
+public static final native void _cairo_surface_mark_dirty(int /*long*/ surface);
+public static final void cairo_surface_mark_dirty(int /*long*/ surface) {
+	lock.lock();
+	try {
+		_cairo_surface_mark_dirty(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/** @param surface cast=(cairo_surface_t *) */
 public static final native void _cairo_surface_reference(int /*long*/ surface);
 public static final void cairo_surface_reference(int /*long*/ surface) {
 	lock.lock();
@@ -1559,6 +1659,45 @@
 	}
 }
 /**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int /*long*/ _cairo_xlib_surface_get_drawable(int /*long*/ surface);
+public static final int /*long*/ cairo_xlib_surface_get_drawable(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_xlib_surface_get_drawable(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int _cairo_xlib_surface_get_height(int /*long*/ surface);
+public static final int cairo_xlib_surface_get_height(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_xlib_surface_get_height(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
+ * @method flags=dynamic
+ * @param surface cast=(cairo_surface_t *)
+ */
+public static final native int _cairo_xlib_surface_get_width(int /*long*/ surface);
+public static final int cairo_xlib_surface_get_width(int /*long*/ surface) {
+	lock.lock();
+	try {
+		return _cairo_xlib_surface_get_width(surface);
+	} finally {
+		lock.unlock();
+	}
+}
+/**
  * @param dest cast=(void *)
  * @param src cast=(const void *)
  * @param size cast=(size_t)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras
index c56f7e0..3d248b2 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/AppKitFull.bridgesupport.extras
@@ -4751,6 +4751,17 @@
 	<enum name="NSFileHandlingPanelOKButton" swt_gen="true"></enum>
 	<enum name="NSFlagsChanged" swt_gen="true"></enum>
 	<enum name="NSFocusRingTypeNone" swt_gen="true"></enum>
+	<enum name="NSFontPanelAllEffectsModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelAllModesMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelCollectionModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelDocumentColorEffectModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelFaceModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelShadowEffectModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelSizeModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelStandardModesMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelStrikethroughEffectModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelTextColorEffectModeMask" swt_gen="true"></enum>
+	<enum name="NSFontPanelUnderlineEffectModeMask" swt_gen="true"></enum>
 	<enum name="NSHelpFunctionKey" swt_gen="true"></enum>
 	<enum name="NSHelpKeyMask" swt_gen="true"></enum>
 	<enum name="NSHourMinuteDatePickerElementFlag" swt_gen="true"></enum>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/FoundationFull.bridgesupport.extras b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/FoundationFull.bridgesupport.extras
index ef51c74..8947ccd 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/FoundationFull.bridgesupport.extras
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/FoundationFull.bridgesupport.extras
@@ -50,6 +50,12 @@
 		</method>
 	</class>
 	<class name="NSAttributedString" swt_gen="mixed">
+		<method selector="attribute:atIndex:effectiveRange:" swt_gen="true">
+			<arg swt_gen="true"></arg>
+			<arg swt_gen="true"></arg>
+			<arg swt_gen="true"></arg>
+			<retval swt_gen="true"></retval>
+		</method>
 		<method selector="attributedSubstringFromRange:" swt_gen="true">
 			<arg swt_gen="true"></arg>
 			<retval swt_gen="true"></retval>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSAttributedString.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSAttributedString.java
index 7d26d52..336244f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSAttributedString.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSAttributedString.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -69,6 +69,11 @@
 	return result;
 }
 
+public id attribute(NSString attrName, int /*long*/ location, int /*long*/ range) {
+	int /*long*/ result = OS.objc_msgSend(this.id, OS.sel_attribute_atIndex_effectiveRange_, attrName != null ? attrName.id : 0, location, range);
+	return result != 0 ? new id(result) : null;
+}
+
 public NSAttributedString attributedSubstringFromRange(NSRange range) {
 	int /*long*/ result = OS.objc_msgSend(this.id, OS.sel_attributedSubstringFromRange_, range);
 	return result == this.id ? this : (result != 0 ? new NSAttributedString(result) : null);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java
index 01d3f53..979688a 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/OS.java
@@ -960,6 +960,7 @@
 public static final int /*long*/ sel_arrayWithObject_ = sel_registerName("arrayWithObject:");
 public static final int /*long*/ sel_arrowCursor = sel_registerName("arrowCursor");
 public static final int /*long*/ sel_ascender = sel_registerName("ascender");
+public static final int /*long*/ sel_attribute_atIndex_effectiveRange_ = sel_registerName("attribute:atIndex:effectiveRange:");
 public static final int /*long*/ sel_attributedStringValue = sel_registerName("attributedStringValue");
 public static final int /*long*/ sel_attributedStringWithAttachment_ = sel_registerName("attributedStringWithAttachment:");
 public static final int /*long*/ sel_attributedSubstringFromRange_ = sel_registerName("attributedSubstringFromRange:");
@@ -2281,17 +2282,17 @@
 public static final int NSFileHandlingPanelOKButton = 1;
 public static final int NSFlagsChanged = 12;
 public static final int NSFocusRingTypeNone = 1;
-public static final int NSFontPanelFaceModeMask = 1 << 0;
-public static final int NSFontPanelSizeModeMask = 1 << 1;
-public static final int NSFontPanelCollectionModeMask = 1 << 2;
-public static final int NSFontPanelUnderlineEffectModeMask = 1<<8;
-public static final int NSFontPanelStrikethroughEffectModeMask = 1<<9;
-public static final int NSFontPanelTextColorEffectModeMask = 1<< 10;
-public static final int NSFontPanelDocumentColorEffectModeMask = 1<<11;
-public static final int NSFontPanelShadowEffectModeMask = 1<<12;
-public static final int NSFontPanelAllEffectsModeMask = 0XFFF00;
-public static final int NSFontPanelStandardModesMask = 0xFFFF;
-public static final int NSFontPanelAllModesMask = 0xFFFFFFFF;
+public static final int NSFontPanelAllEffectsModeMask = 1048320;
+public static final int NSFontPanelAllModesMask = -1;
+public static final int NSFontPanelCollectionModeMask = 4;
+public static final int NSFontPanelDocumentColorEffectModeMask = 2048;
+public static final int NSFontPanelFaceModeMask = 1;
+public static final int NSFontPanelShadowEffectModeMask = 4096;
+public static final int NSFontPanelSizeModeMask = 2;
+public static final int NSFontPanelStandardModesMask = 65535;
+public static final int NSFontPanelStrikethroughEffectModeMask = 512;
+public static final int NSFontPanelTextColorEffectModeMask = 1024;
+public static final int NSFontPanelUnderlineEffectModeMask = 256;
 public static final int NSHelpFunctionKey = 63302;
 public static final int NSHelpKeyMask = 4194304;
 public static final int NSHourMinuteDatePickerElementFlag = 12;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2me/org/eclipse/swt/internal/Library.java b/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2me/org/eclipse/swt/internal/Library.java
index 6e473b3..8a5eaf4 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2me/org/eclipse/swt/internal/Library.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2me/org/eclipse/swt/internal/Library.java
@@ -22,7 +22,7 @@
 	/**
 	 * SWT Minor version number (must be in the range 0..999)
 	 */
-    static int MINOR_VERSION = 817;
+    static int MINOR_VERSION = 820;
 	
 	/**
 	 * SWT revision number (must be >= 0)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2se/org/eclipse/swt/internal/Library.java b/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2se/org/eclipse/swt/internal/Library.java
index af2aaf7..f287a34 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2se/org/eclipse/swt/internal/Library.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/common_j2se/org/eclipse/swt/internal/Library.java
@@ -24,7 +24,7 @@
 	/**
 	 * SWT Minor version number (must be in the range 0..999)
 	 */
-    static int MINOR_VERSION = 817;
+    static int MINOR_VERSION = 820;
 	
 	/**
 	 * SWT revision number (must be >= 0)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk_structs.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk_structs.c
index cf07ec8..92fd430 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk_structs.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/atk_structs.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved.
  * The contents of this file are made available under the terms
  * of the GNU Lesser General Public License (LGPL) Version 2.1 that
  * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
@@ -43,9 +43,9 @@
 	if (!AtkActionIfaceFc.cached) cacheAtkActionIfaceFields(env, lpObject);
 	lpStruct->do_action = (gboolean (*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.do_action);
 	lpStruct->get_n_actions = (gint (*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_n_actions);
-	lpStruct->get_description = (G_CONST_RETURN gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_description);
-	lpStruct->get_name = (G_CONST_RETURN gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_name);
-	lpStruct->get_keybinding = (G_CONST_RETURN gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_keybinding);
+	lpStruct->get_description = (const gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_description);
+	lpStruct->get_name = (const gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_name);
+	lpStruct->get_keybinding = (const gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.get_keybinding);
 	lpStruct->set_description = (gboolean (*)())(*env)->GetIntLongField(env, lpObject, AtkActionIfaceFc.set_description);
 	return lpStruct;
 }
@@ -292,8 +292,8 @@
 AtkObjectClass *getAtkObjectClassFields(JNIEnv *env, jobject lpObject, AtkObjectClass *lpStruct)
 {
 	if (!AtkObjectClassFc.cached) cacheAtkObjectClassFields(env, lpObject);
-	lpStruct->get_name = (G_CONST_RETURN gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_name);
-	lpStruct->get_description = (G_CONST_RETURN gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_description);
+	lpStruct->get_name = (const gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_name);
+	lpStruct->get_description = (const gchar *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_description);
 	lpStruct->get_parent = (AtkObject *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_parent);
 	lpStruct->get_n_children = (gint (*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.get_n_children);
 	lpStruct->ref_child = (AtkObject *(*)())(*env)->GetIntLongField(env, lpObject, AtkObjectClassFc.ref_child);
@@ -502,9 +502,9 @@
 	lpStruct->get_column_extent_at = (gint (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_column_extent_at);
 	lpStruct->get_row_extent_at = (gint (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_row_extent_at);
 	lpStruct->get_caption = (AtkObject* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_caption);
-	lpStruct->get_column_description = (G_CONST_RETURN gchar* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_column_description);
+	lpStruct->get_column_description = (const gchar* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_column_description);
 	lpStruct->get_column_header = (AtkObject* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_column_header);
-	lpStruct->get_row_description = (G_CONST_RETURN gchar* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_row_description);
+	lpStruct->get_row_description = (const gchar* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_row_description);
 	lpStruct->get_row_header = (AtkObject* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_row_header);
 	lpStruct->get_summary = (AtkObject* (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.get_summary);
 	lpStruct->set_caption = (void (*)())(*env)->GetIntLongField(env, lpObject, AtkTableIfaceFc.set_caption);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak
index 3976fe4..ad5b1ca 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak
@@ -122,7 +122,7 @@
 	LFLAGS := $(LFLAGS) -s
 endif
 
-all: make_swt make_atk make_glx
+all: make_swt make_atk make_glx make_webkit
 
 #
 # SWT libs
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
index b3f719d..b7aca3f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved.
  * The contents of this file are made available under the terms
  * of the GNU Lesser General Public License (LGPL) Version 2.1 that
  * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
@@ -5026,6 +5026,24 @@
 }
 #endif
 
+#ifndef NO__1gdk_1cairo_1set_1source_1window
+JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1cairo_1set_1source_1window)
+	(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jint arg2, jint arg3)
+{
+	OS_NATIVE_ENTER(env, that, _1gdk_1cairo_1set_1source_1window_FUNC);
+/*
+	gdk_cairo_set_source_window(arg0, (GdkWindow *)arg1, arg2, arg3);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gdk_cairo_set_source_window)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(jintLong, GdkWindow *, jint, jint))fp)(arg0, (GdkWindow *)arg1, arg2, arg3);
+		}
+	}
+	OS_NATIVE_EXIT(env, that, _1gdk_1cairo_1set_1source_1window_FUNC);
+}
+#endif
+
 #ifndef NO__1gdk_1color_1free
 JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1color_1free)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -5632,16 +5650,6 @@
 }
 #endif
 
-#ifndef NO__1gdk_1free_1text_1list
-JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1free_1text_1list)
-	(JNIEnv *env, jclass that, jintLong arg0)
-{
-	OS_NATIVE_ENTER(env, that, _1gdk_1free_1text_1list_FUNC);
-	gdk_free_text_list((gchar **)arg0);
-	OS_NATIVE_EXIT(env, that, _1gdk_1free_1text_1list_FUNC);
-}
-#endif
-
 #ifndef NO__1gdk_1gc_1get_1values
 JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1gc_1get_1values)
 	(JNIEnv *env, jclass that, jintLong arg0, jobject arg1)
@@ -6175,16 +6183,6 @@
 }
 #endif
 
-#ifndef NO__1gdk_1pixbuf_1render_1to_1drawable_1alpha
-JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1pixbuf_1render_1to_1drawable_1alpha)
-	(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jint arg2, jint arg3, jint arg4, jint arg5, jint arg6, jint arg7, jint arg8, jint arg9, jint arg10, jint arg11, jint arg12)
-{
-	OS_NATIVE_ENTER(env, that, _1gdk_1pixbuf_1render_1to_1drawable_1alpha_FUNC);
-	gdk_pixbuf_render_to_drawable_alpha((GdkPixbuf *)arg0, (GdkDrawable *)arg1, arg2, arg3, arg4, arg5, arg6, arg7, (GdkPixbufAlphaMode)arg8, arg9, (GdkRgbDither)arg10, arg11, arg12);
-	OS_NATIVE_EXIT(env, that, _1gdk_1pixbuf_1render_1to_1drawable_1alpha_FUNC);
-}
-#endif
-
 #ifndef NO__1gdk_1pixbuf_1save_1to_1bufferv
 JNIEXPORT jboolean JNICALL OS_NATIVE(_1gdk_1pixbuf_1save_1to_1bufferv)
 	(JNIEnv *env, jclass that, jintLong arg0, jintLongArray arg1, jintLongArray arg2, jbyteArray arg3, jintLongArray arg4, jintLongArray arg5, jintLongArray arg6)
@@ -6505,16 +6503,6 @@
 }
 #endif
 
-#ifndef NO__1gdk_1rgb_1init
-JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1rgb_1init)
-	(JNIEnv *env, jclass that)
-{
-	OS_NATIVE_ENTER(env, that, _1gdk_1rgb_1init_FUNC);
-	gdk_rgb_init();
-	OS_NATIVE_EXIT(env, that, _1gdk_1rgb_1init_FUNC);
-}
-#endif
-
 #ifndef NO__1gdk_1screen_1get_1default
 JNIEXPORT jintLong JNICALL OS_NATIVE(_1gdk_1screen_1get_1default)
 	(JNIEnv *env, jclass that)
@@ -6823,6 +6811,26 @@
 }
 #endif
 
+#ifndef NO__1gdk_1window_1create_1similar_1surface
+JNIEXPORT jintLong JNICALL OS_NATIVE(_1gdk_1window_1create_1similar_1surface)
+	(JNIEnv *env, jclass that, jintLong arg0, jint arg1, jint arg2, jint arg3)
+{
+	jintLong rc = 0;
+	OS_NATIVE_ENTER(env, that, _1gdk_1window_1create_1similar_1surface_FUNC);
+/*
+	rc = (jintLong)gdk_window_create_similar_surface((GdkWindow *)arg0, arg1, arg2, arg3);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gdk_window_create_similar_surface)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)(GdkWindow *, jint, jint, jint))fp)((GdkWindow *)arg0, arg1, arg2, arg3);
+		}
+	}
+	OS_NATIVE_EXIT(env, that, _1gdk_1window_1create_1similar_1surface_FUNC);
+	return rc;
+}
+#endif
+
 #ifndef NO__1gdk_1window_1destroy
 JNIEXPORT void JNICALL OS_NATIVE(_1gdk_1window_1destroy)
 	(JNIEnv *env, jclass that, jintLong arg0)
@@ -13005,7 +13013,15 @@
 {
 	jintLong rc = 0;
 	OS_NATIVE_ENTER(env, that, _1gtk_1set_1locale_FUNC);
+/*
 	rc = (jintLong)gtk_set_locale();
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gtk_set_locale)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)())fp)();
+		}
+	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1set_1locale_FUNC);
 	return rc;
 }
@@ -14269,7 +14285,15 @@
 {
 	jintLong rc = 0;
 	OS_NATIVE_ENTER(env, that, _1gtk_1tooltips_1data_1get_FUNC);
-	rc = (jintLong)gtk_tooltips_data_get((GtkWidget *)arg0);
+/*
+	rc = (jintLong)gtk_tooltips_data_get(arg0);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gtk_tooltips_data_get)
+		if (fp) {
+			rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0);
+		}
+	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1tooltips_1data_1get_FUNC);
 	return rc;
 }
@@ -14280,7 +14304,15 @@
 	(JNIEnv *env, jclass that, jintLong arg0)
 {
 	OS_NATIVE_ENTER(env, that, _1gtk_1tooltips_1disable_FUNC);
-	gtk_tooltips_disable((GtkTooltips *)arg0);
+/*
+	gtk_tooltips_disable(arg0);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gtk_tooltips_disable)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(jintLong))fp)(arg0);
+		}
+	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1tooltips_1disable_FUNC);
 }
 #endif
@@ -14290,7 +14322,15 @@
 	(JNIEnv *env, jclass that, jintLong arg0)
 {
 	OS_NATIVE_ENTER(env, that, _1gtk_1tooltips_1enable_FUNC);
-	gtk_tooltips_enable((GtkTooltips *)arg0);
+/*
+	gtk_tooltips_enable(arg0);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gtk_tooltips_enable)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(jintLong))fp)(arg0);
+		}
+	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1tooltips_1enable_FUNC);
 }
 #endif
@@ -14300,7 +14340,15 @@
 	(JNIEnv *env, jclass that, jintLong arg0)
 {
 	OS_NATIVE_ENTER(env, that, _1gtk_1tooltips_1force_1window_FUNC);
-	gtk_tooltips_force_window((GtkTooltips *)arg0);
+/*
+	gtk_tooltips_force_window(arg0);
+*/
+	{
+		OS_LOAD_FUNCTION(fp, gtk_tooltips_force_window)
+		if (fp) {
+			((void (CALLING_CONVENTION*)(jintLong))fp)(arg0);
+		}
+	}
 	OS_NATIVE_EXIT(env, that, _1gtk_1tooltips_1force_1window_FUNC);
 }
 #endif
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
index 7f996d5..f52d929 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_custom.h
@@ -126,9 +126,14 @@
 #define gtk_menu_item_remove_submenu_LIB LIB_GTK
 #define gtk_menu_shell_set_take_focus_LIB LIB_GTK
 #define gtk_window_set_keep_below_LIB LIB_GTK
+#define gtk_set_locale_LIB LIB_GTK
 #define gtk_toolbar_set_orientation_LIB LIB_GTK
 #define gtk_tooltip_trigger_tooltip_query_LIB LIB_GTK
 #define gtk_tooltips_set_tip_LIB LIB_GTK
+#define gtk_tooltips_enable_LIB LIB_GTK
+#define gtk_tooltips_disable_LIB LIB_GTK
+#define gtk_tooltips_data_get_LIB LIB_GTK
+#define gtk_tooltips_force_window_LIB LIB_GTK
 #define gtk_tree_selection_count_selected_rows_LIB LIB_GTK
 #define gtk_tree_selection_get_selected_rows_LIB LIB_GTK
 #define gtk_tree_view_column_get_cell_renderers_LIB LIB_GTK
@@ -159,6 +164,7 @@
 #define gtk_status_icon_position_menu_LIB LIB_GTK
 #define gtk_window_get_group_LIB LIB_GTK
 #define gtk_window_get_opacity_LIB LIB_GTK
+#define gdk_window_create_similar_surface_LIB LIB_GDK
 #define gdk_window_restack_LIB LIB_GDK
 #define gdk_window_set_keep_above_LIB LIB_GDK
 #define gdk_window_set_accept_focus_LIB LIB_GDK
@@ -191,6 +197,7 @@
 #define pango_cairo_font_map_set_resolution_LIB LIB_PANGOCAIRO
 #define gdk_cairo_reset_clip_LIB LIB_GDK
 #define gdk_cairo_set_source_color_LIB LIB_GDK
+#define gdk_cairo_set_source_window_LIB LIB_GDK
 #define gdk_cairo_region_LIB LIB_GDK
 #define gdk_cairo_create_LIB LIB_GDK
 #define gtk_enumerate_printers_LIB LIB_GTK
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
index f68a0a8..e3e9a7d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.c
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved.
  * The contents of this file are made available under the terms
  * of the GNU Lesser General Public License (LGPL) Version 2.1 that
  * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
@@ -18,8 +18,8 @@
 
 #ifdef NATIVE_STATS
 
-int OS_nativeFunctionCount = 1381;
-int OS_nativeFunctionCallCount[1381];
+int OS_nativeFunctionCount = 1380;
+int OS_nativeFunctionCallCount[1380];
 char * OS_nativeFunctionNames[] = {
 #ifndef JNI64
 	"Call__IIII",
@@ -430,6 +430,7 @@
 	"_1gdk_1cairo_1region",
 	"_1gdk_1cairo_1reset_1clip",
 	"_1gdk_1cairo_1set_1source_1color",
+	"_1gdk_1cairo_1set_1source_1window",
 	"_1gdk_1color_1free",
 	"_1gdk_1color_1white",
 	"_1gdk_1colormap_1alloc_1color",
@@ -473,7 +474,6 @@
 	"_1gdk_1event_1peek",
 	"_1gdk_1event_1put",
 	"_1gdk_1flush",
-	"_1gdk_1free_1text_1list",
 	"_1gdk_1gc_1get_1values",
 	"_1gdk_1gc_1new",
 	"_1gdk_1gc_1set_1background",
@@ -516,7 +516,6 @@
 	"_1gdk_1pixbuf_1new_1from_1file",
 	"_1gdk_1pixbuf_1render_1pixmap_1and_1mask",
 	"_1gdk_1pixbuf_1render_1to_1drawable",
-	"_1gdk_1pixbuf_1render_1to_1drawable_1alpha",
 	"_1gdk_1pixbuf_1save_1to_1bufferv",
 	"_1gdk_1pixbuf_1scale",
 	"_1gdk_1pixbuf_1scale_1simple",
@@ -540,7 +539,6 @@
 	"_1gdk_1region_1subtract",
 	"_1gdk_1region_1union",
 	"_1gdk_1region_1union_1with_1rect",
-	"_1gdk_1rgb_1init",
 	"_1gdk_1screen_1get_1default",
 	"_1gdk_1screen_1get_1monitor_1at_1point",
 	"_1gdk_1screen_1get_1monitor_1at_1window",
@@ -560,6 +558,7 @@
 	"_1gdk_1window_1at_1pointer",
 	"_1gdk_1window_1begin_1paint_1rect",
 	"_1gdk_1window_1clear_1area",
+	"_1gdk_1window_1create_1similar_1surface",
 	"_1gdk_1window_1destroy",
 	"_1gdk_1window_1end_1paint",
 	"_1gdk_1window_1focus",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
index 53b3ebd..494ac90 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved.
  * The contents of this file are made available under the terms
  * of the GNU Lesser General Public License (LGPL) Version 2.1 that
  * accompanies this distribution (lgpl-v21.txt).  The LGPL is also
@@ -438,6 +438,7 @@
 	_1gdk_1cairo_1region_FUNC,
 	_1gdk_1cairo_1reset_1clip_FUNC,
 	_1gdk_1cairo_1set_1source_1color_FUNC,
+	_1gdk_1cairo_1set_1source_1window_FUNC,
 	_1gdk_1color_1free_FUNC,
 	_1gdk_1color_1white_FUNC,
 	_1gdk_1colormap_1alloc_1color_FUNC,
@@ -481,7 +482,6 @@
 	_1gdk_1event_1peek_FUNC,
 	_1gdk_1event_1put_FUNC,
 	_1gdk_1flush_FUNC,
-	_1gdk_1free_1text_1list_FUNC,
 	_1gdk_1gc_1get_1values_FUNC,
 	_1gdk_1gc_1new_FUNC,
 	_1gdk_1gc_1set_1background_FUNC,
@@ -524,7 +524,6 @@
 	_1gdk_1pixbuf_1new_1from_1file_FUNC,
 	_1gdk_1pixbuf_1render_1pixmap_1and_1mask_FUNC,
 	_1gdk_1pixbuf_1render_1to_1drawable_FUNC,
-	_1gdk_1pixbuf_1render_1to_1drawable_1alpha_FUNC,
 	_1gdk_1pixbuf_1save_1to_1bufferv_FUNC,
 	_1gdk_1pixbuf_1scale_FUNC,
 	_1gdk_1pixbuf_1scale_1simple_FUNC,
@@ -548,7 +547,6 @@
 	_1gdk_1region_1subtract_FUNC,
 	_1gdk_1region_1union_FUNC,
 	_1gdk_1region_1union_1with_1rect_FUNC,
-	_1gdk_1rgb_1init_FUNC,
 	_1gdk_1screen_1get_1default_FUNC,
 	_1gdk_1screen_1get_1monitor_1at_1point_FUNC,
 	_1gdk_1screen_1get_1monitor_1at_1window_FUNC,
@@ -568,6 +566,7 @@
 	_1gdk_1window_1at_1pointer_FUNC,
 	_1gdk_1window_1begin_1paint_1rect_FUNC,
 	_1gdk_1window_1clear_1area_FUNC,
+	_1gdk_1window_1create_1similar_1surface_FUNC,
 	_1gdk_1window_1destroy_FUNC,
 	_1gdk_1window_1end_1paint_FUNC,
 	_1gdk_1window_1focus_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkActionIface.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkActionIface.java
index 94409fc..c40efa1 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkActionIface.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkActionIface.java
@@ -21,11 +21,11 @@
 	public int /*long*/ do_action;
 	/** @field cast=(gint (*)()) */
 	public int /*long*/ get_n_actions;
-	/** @field cast=(G_CONST_RETURN gchar *(*)()) */
+	/** @field cast=(const gchar *(*)()) */
 	public int /*long*/ get_description;
-	/** @field cast=(G_CONST_RETURN gchar *(*)()) */
+	/** @field cast=(const gchar *(*)()) */
 	public int /*long*/ get_name;
-	/** @field cast=(G_CONST_RETURN gchar *(*)()) */
+	/** @field cast=(const gchar *(*)()) */
 	public int /*long*/ get_keybinding;
 	/** @field cast=(gboolean (*)()) */
 	public int /*long*/ set_description;	
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkObjectClass.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkObjectClass.java
index c631c29..934e5b2 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkObjectClass.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkObjectClass.java
@@ -16,9 +16,9 @@
 
 
 public class AtkObjectClass {
-	/** @field cast=(G_CONST_RETURN gchar *(*)()) */
+	/** @field cast=(const gchar *(*)()) */
 	public int /*long*/ get_name;
-	/** @field cast=(G_CONST_RETURN gchar *(*)()) */
+	/** @field cast=(const gchar *(*)()) */
 	public int /*long*/ get_description;
 	/** @field cast=(AtkObject *(*)()) */
 	public int /*long*/ get_parent;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkTableIface.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkTableIface.java
index 9cbc506..2c1d3c8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkTableIface.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/accessibility/gtk/AtkTableIface.java
@@ -34,11 +34,11 @@
 	public int /*long*/ get_row_extent_at;
 	/** @field cast=(AtkObject* (*)()) */
 	public int /*long*/ get_caption;
-	/** @field cast=(G_CONST_RETURN gchar* (*)()) */
+	/** @field cast=(const gchar* (*)()) */
 	public int /*long*/ get_column_description;
 	/** @field cast=(AtkObject* (*)()) */
 	public int /*long*/ get_column_header;
-	/** @field cast=(G_CONST_RETURN gchar* (*)()) */
+	/** @field cast=(const gchar* (*)()) */
 	public int /*long*/ get_row_description;
 	/** @field cast=(AtkObject* (*)()) */
 	public int /*long*/ get_row_header;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index 4cf512b..c43f396 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -23,7 +23,7 @@
 	}
 	
 	/** OS Constants */
-	public static final boolean IsAIX, IsSunOS, IsLinux, IsHPUX;
+	public static final boolean IsAIX, IsSunOS, IsLinux, IsHPUX, BIG_ENDIAN;
 	static {
 		
 		/* Initialize the OS flags and locale constants */
@@ -35,6 +35,13 @@
 		if (osName.equals ("SunOS")) isSunOS = true;
 		if (osName.equals ("HP-UX")) isHPUX = true;
 		IsAIX = isAIX;  IsSunOS = isSunOS;  IsLinux = isLinux;  IsHPUX = isHPUX;
+		
+		byte[] buffer = new byte[4];
+		int /*long*/ ptr = OS.malloc(4);
+		OS.memmove(ptr, new int[]{1}, 4);
+		OS.memmove(buffer, ptr, 1);
+		OS.free(ptr);
+		BIG_ENDIAN = buffer[0] == 0;
 	}
 
 	/** Constants */
@@ -559,6 +566,19 @@
 	public static final byte[] GTK_STOCK_CLEAR = ascii("gtk-clear");
 	
 	public static final int GTK_VERSION = VERSION(gtk_major_version(), gtk_minor_version(), gtk_micro_version()); 
+	public static final boolean USE_CAIRO, INIT_CAIRO;
+	static {
+		boolean useCairo = false;
+		if ("true".equals(System.getProperty("org.eclipse.swt.internal.gtk.cairoGraphics"))) {
+			useCairo  = GTK_VERSION >= VERSION(2, 24, 0);
+		}
+		USE_CAIRO = useCairo;
+		boolean initCairo = false;
+		if (!"false".equals(System.getProperty("org.eclipse.swt.internal.gtk.useCairo"))) {
+			initCairo  = GTK_VERSION >= VERSION(2, 17, 0);
+		}
+		INIT_CAIRO = initCairo;
+	}
 	
 protected static byte [] ascii (String name) {
 	int length = name.length ();
@@ -3651,6 +3671,20 @@
 	}
 }
 /**
+ * @method flags=dynamic
+ * @param window cast=(GdkWindow *)
+ */
+public static final native void _gdk_cairo_set_source_window(int /*long*/ cairo, int /*long*/ window, int x, int y);
+public static final void gdk_cairo_set_source_window(int /*long*/ cairo, int /*long*/ window, int x, int y) {
+        lock.lock();
+        try {
+                _gdk_cairo_set_source_window(cairo, window, x, y);
+        }
+        finally {
+                lock.unlock();
+        }
+}
+/**
  * @param colormap cast=(GdkColormap *)
  * @param color cast=(GdkColor *),flags=no_in
  */
@@ -4197,16 +4231,6 @@
 		lock.unlock();
 	}
 }
-/** @param list cast=(gchar **) */
-public static final native void _gdk_free_text_list(int /*long*/ list);
-public static final void gdk_free_text_list(int /*long*/ list) {
-	lock.lock();
-	try {
-		_gdk_free_text_list(list);
-	} finally {
-		lock.unlock();
-	}
-}
 /**
  * @param gc cast=(GdkGC *)
  * @param values cast=(GdkGCValues *),flags=no_in
@@ -4703,21 +4727,6 @@
 }
 /**
  * @param pixbuf cast=(GdkPixbuf *)
- * @param drawable cast=(GdkDrawable *)
- * @param alpha_mode cast=(GdkPixbufAlphaMode)
- * @param dither cast=(GdkRgbDither)
- */
-public static final native void _gdk_pixbuf_render_to_drawable_alpha(int /*long*/ pixbuf, int /*long*/ drawable, int src_x, int src_y, int dest_x, int dest_y, int width, int height, int alpha_mode, int alpha_threshold, int dither, int x_dither, int y_dither);
-public static final void gdk_pixbuf_render_to_drawable_alpha(int /*long*/ pixbuf, int /*long*/ drawable, int src_x, int src_y, int dest_x, int dest_y, int width, int height, int alpha_mode, int alpha_threshold, int dither, int x_dither, int y_dither) {
-	lock.lock();
-	try {
-		_gdk_pixbuf_render_to_drawable_alpha(pixbuf, drawable, src_x, src_y, dest_x, dest_y, width, height, alpha_mode, alpha_threshold, dither, x_dither, y_dither);
-	} finally {
-		lock.unlock();
-	}
-}
-/**
- * @param pixbuf cast=(GdkPixbuf *)
  * @param pixmap_return cast=(GdkDrawable **)
  * @param mask_return cast=(GdkBitmap **)
  */
@@ -5020,15 +5029,6 @@
 		lock.unlock();
 	}
 }
-public static final native void _gdk_rgb_init();
-public static final void gdk_rgb_init() {
-	lock.lock();
-	try {
-		_gdk_rgb_init();
-	} finally {
-		lock.unlock();
-	}
-}
 /** @method flags=dynamic */
 public static final native int /*long*/ _gdk_screen_get_default();
 public static final int /*long*/ gdk_screen_get_default() {
@@ -5260,6 +5260,19 @@
 		lock.unlock();
 	}
 }
+/**
+ * @method flags=dynamic 
+ * @param window cast=(GdkWindow *)
+ */
+public static final native int /*long*/ _gdk_window_create_similar_surface(int /*long*/ window, int content, int width, int height);
+public static final int /*long*/ gdk_window_create_similar_surface(int /*long*/ window, int content, int width, int height) {
+	lock.lock();
+	try {
+		return _gdk_window_create_similar_surface(window, content, width, height);
+	} finally {
+		lock.unlock();
+	}
+}
 /** @param window cast=(GdkWindow *) */
 public static final native void _gdk_window_destroy(int /*long*/ window);
 public static final void gdk_window_destroy(int /*long*/ window) {
@@ -10030,6 +10043,7 @@
 		lock.unlock();
 	}
 }
+/** @method flags=dynamic */
 public static final native int /*long*/ _gtk_set_locale();
 public static final int /*long*/ gtk_set_locale() {
 	lock.lock();
@@ -11123,7 +11137,7 @@
 		lock.unlock();
 	}
 }
-/** @param widget cast=(GtkWidget *) */
+/** @method flags=dynamic */
 public static final native int /*long*/ _gtk_tooltips_data_get(int /*long*/ widget);
 public static final int /*long*/ gtk_tooltips_data_get(int /*long*/ widget) {
 	lock.lock();
@@ -11133,7 +11147,7 @@
 		lock.unlock();
 	}
 }
-/** @param tooltips cast=(GtkTooltips *) */
+/** @method flags=dynamic */
 public static final native void _gtk_tooltips_disable(int /*long*/ tooltips);
 public static final void gtk_tooltips_disable(int /*long*/ tooltips) {
 	lock.lock();
@@ -11143,7 +11157,7 @@
 		lock.unlock();
 	}
 }
-/** @param tooltips cast=(GtkTooltips *) */
+/** @method flags=dynamic */
 public static final native void _gtk_tooltips_enable(int /*long*/ tooltips);
 public static final void gtk_tooltips_enable(int /*long*/ tooltips) {
 	lock.lock();
@@ -11162,7 +11176,7 @@
 		lock.unlock();
 	}
 }
-/** @param tooltips cast=(GtkTooltips *) */
+/** @method flags=dynamic */
 public static final native void _gtk_tooltips_force_window(int /*long*/ tooltips);
 public static final void gtk_tooltips_force_window(int /*long*/ tooltips) {
 	lock.lock();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Printing/gtk/org/eclipse/swt/printing/Printer.java b/bundles/org.eclipse.swt/Eclipse SWT Printing/gtk/org/eclipse/swt/printing/Printer.java
index b43afa6..73f0404 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Printing/gtk/org/eclipse/swt/printing/Printer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Printing/gtk/org/eclipse/swt/printing/Printer.java
@@ -73,7 +73,9 @@
 	if (!OS.g_thread_supported ()) {
 		OS.g_thread_init (0);
 	}
-	OS.gtk_set_locale();
+	if (OS.GTK_VERSION < OS.VERSION(2, 24, 0)) {
+	    OS.gtk_set_locale();
+	}
 	if (!OS.gtk_init_check (new int /*long*/ [] {0}, null)) {
 		SWT.error (SWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]");
 	}
@@ -432,11 +434,16 @@
  * @noreference This method is not intended to be referenced by clients.
  */
 public int /*long*/ internal_new_GC(GCData data) {
-	GdkVisual visual = new GdkVisual ();
-	OS.memmove (visual, OS.gdk_visual_get_system());
-	int /*long*/ drawable = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), 1, 1, visual.depth);
-	int /*long*/ gdkGC = OS.gdk_gc_new (drawable);
-	if (gdkGC == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+	int /*long*/ gc, drawable = 0;
+	if (OS.USE_CAIRO) {
+		gc = cairo;
+	} else {
+		GdkVisual visual = new GdkVisual ();
+		OS.memmove (visual, OS.gdk_visual_get_system());
+		drawable = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), 1, 1, visual.depth);
+		gc = OS.gdk_gc_new (drawable);
+	}
+	if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
 	if (data != null) {
 		if (isGCCreated) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
@@ -463,7 +470,7 @@
 		data.cairo = cairo;
 		isGCCreated = true;
 	}
-	return gdkGC;
+	return gc;
 }
 
 /**	 
@@ -481,9 +488,10 @@
  * 
  * @noreference This method is not intended to be referenced by clients.
  */
-public void internal_dispose_GC(int /*long*/ gdkGC, GCData data) {
+public void internal_dispose_GC(int /*long*/ gc, GCData data) {
 	if (data != null) isGCCreated = false;
-	OS.g_object_unref (gdkGC);
+	if (OS.USE_CAIRO) return;
+	OS.g_object_unref (gc);
 	if (data != null) {
 		if (data.drawable != 0) OS.g_object_unref (data.drawable);
 		data.drawable = data.cairo = 0;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/DrawData.java b/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/DrawData.java
index f4492b5..9f52da3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/DrawData.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/DrawData.java
@@ -85,7 +85,7 @@
 	if (state_type == OS.GTK_STATE_NORMAL) {
 		gc.drawImage(image, 0, 0, rect.width, rect.height, bounds.x, bounds.y, bounds.width, bounds.height);
 	} else {
-		int /*long*/ pixbuf = Theme.createPixbuf(image);
+		int /*long*/ pixbuf = ImageList.createPixbuf(image);
 		int /*long*/ source = OS.gtk_icon_source_new();
 		if (source != 0) {
 			OS.gtk_icon_source_set_pixbuf(source, pixbuf);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/Theme.java b/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/Theme.java
index 72d8175..7cca3a9 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/Theme.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Theme/gtk/org/eclipse/swt/internal/theme/Theme.java
@@ -67,63 +67,6 @@
 	OS.gtk_widget_realize (shellHandle);
 }
 
-//TODO - share this code 
-static int /*long*/ createPixbuf(Image image) {
-	int [] w = new int [1], h = new int [1];
- 	OS.gdk_drawable_get_size (image.pixmap, w, h);
-	int /*long*/ colormap = OS.gdk_colormap_get_system ();
-	int /*long*/ pixbuf;
-	boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1;
-	if (hasMask) {
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]);
-		if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]);
-		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
-		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
-		byte[] line = new byte[stride];
-		int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
-		int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
-		byte[] maskLine = new byte[maskStride];
-		for (int y=0; y<h[0]; y++) {
-			int /*long*/ offset = pixels + (y * stride);
-			OS.memmove(line, offset, stride);
-			int /*long*/ maskOffset = maskPixels + (y * maskStride);
-			OS.memmove(maskLine, maskOffset, maskStride);
-			for (int x=0; x<w[0]; x++) {
-				if (maskLine[x * 3] == 0) {
-					line[x * 4 + 3] = 0;
-				}
-			}
-			OS.memmove(offset, line, stride);
-		}
-		OS.g_object_unref(maskPixbuf);
-	} else {
-		ImageData data = image.getImageData ();
-		boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA;
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		if (hasAlpha) {
-			byte [] alpha = data.alphaData;
-			int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
-			int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
-			byte [] line = new byte [stride];
-			for (int y = 0; y < h [0]; y++) {
-				int /*long*/ offset = pixels + (y * stride);
-				OS.memmove (line, offset, stride);
-				for (int x = 0; x < w [0]; x++) {
-					line [x*4+3] = alpha [y*w [0]+x];
-				}
-				OS.memmove (offset, line, stride);
-			}
-		}
-	}
-	return pixbuf;
-}
-
 void checkTheme() {
 	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/GC.java
index ea28083..c7e10d4 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/GC.java
@@ -1678,8 +1678,8 @@
 		NSPoint pt = new NSPoint();
 		pt.x = x;
 		pt.y = y;
+		NSRange range = data.layoutManager.glyphRangeForTextContainer(data.textContainer);
 		if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
-			data.layoutManager.glyphRangeForTextContainer(data.textContainer);
 			NSRect rect = data.layoutManager.usedRectForTextContainer(data.textContainer);
 			rect.x = x;
 			rect.y = y;
@@ -1692,8 +1692,6 @@
 			bg.setFill();
 			NSBezierPath.fillRect(rect);
 		}
-		NSRange range = new NSRange();
-		range.length = data.layoutManager.numberOfGlyphs();
 		data.layoutManager.drawGlyphsForGlyphRange(range, pt);
 		handle.restoreGraphicsState();
 	} finally {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Path.java
index 7a87377..1afd744 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Path.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Path.java
@@ -362,6 +362,7 @@
 		size.width = OS.MAX_TEXT_CONTAINER_SIZE;
 		size.height = OS.MAX_TEXT_CONTAINER_SIZE;
 		textContainer.initWithContainerSize(size);
+		textContainer.setLineFragmentPadding(0);
 		textStorage.addLayoutManager(layoutManager);
 		layoutManager.addTextContainer(textContainer);
 		NSRange range = new NSRange();
@@ -382,18 +383,22 @@
 		attrStr.release();
 		range = layoutManager.glyphRangeForTextContainer(textContainer);
 		if (range.length != 0) {
-			int /*long*/ glyphs = OS.malloc(4 * range.length * 2);
-			layoutManager.getGlyphs(glyphs, range);
+			int /*long*/ glyphs = OS.malloc((range.length + 1) * 4);
+			int /*long*/ count = layoutManager.getGlyphs(glyphs, range);
 			NSBezierPath path = NSBezierPath.bezierPath();
-			NSPoint point = new NSPoint();
-			path.moveToPoint(point);
-			path.appendBezierPathWithGlyphs(glyphs, range.length, font.handle);
+			for (int i = 0; i < count; i++) {
+				NSPoint pt = layoutManager.locationForGlyphAtIndex(i);
+				NSRect lineFragmentRect = layoutManager.lineFragmentUsedRectForGlyphAtIndex(i, 0);
+				NSFont actualFont = new NSFont(textStorage.attribute(OS.NSFontAttributeName, layoutManager.characterIndexForGlyphAtIndex(i), 0));
+				pt.x = pt.x + x + lineFragmentRect.x;
+				pt.y =  - pt.y - y - lineFragmentRect.y;
+				path.moveToPoint(pt);
+				path.appendBezierPathWithGlyphs(glyphs + (i * 4), 1, actualFont);
+			}
+			OS.free(glyphs);
 			NSAffineTransform transform = NSAffineTransform.transform();
 			transform.scaleXBy(1, -1);
-			float /*double*/ baseline = layoutManager.defaultBaselineOffsetForFont(font.handle);
-			transform.translateXBy(x, -(y + baseline));
 			path.transformUsingAffineTransform(transform);
-			OS.free(glyphs);
 			handle.appendBezierPath(path);
 		}
 		textContainer.release();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak b/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak
index c24cf44..4bcac5f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/library/make_common.mak
@@ -10,5 +10,5 @@
 #*******************************************************************************
 
 maj_ver=3
-min_ver=817
-comma_ver=3,8,1,7
+min_ver=820
+comma_ver=3,8,2,0
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt b/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt
index 86c09d6..4db30ce 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/version.txt
@@ -1 +1 @@
-version 3.817
\ No newline at end of file
+version 3.820
\ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
index 5a0ea64..37a95bf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java
@@ -85,7 +85,6 @@
 	int /*long*/ emptyTab;
 
 	boolean useXRender;
-	boolean useCairo;
 	static boolean CAIRO_LOADED;
 
 	/*
@@ -580,7 +579,7 @@
 protected void init () {
 	this.dpi = getDPI();
 	
-	if (xDisplay != 0) {
+	if (xDisplay != 0 && !OS.USE_CAIRO) {
 		int[] event_basep = new int[1], error_basep = new int [1];
 		if (OS.XRenderQueryExtension (xDisplay, event_basep, error_basep)) {
 			int[] major_versionp = new int[1], minor_versionp = new int [1];
@@ -588,13 +587,7 @@
 			useXRender = major_versionp[0] > 0 || (major_versionp[0] == 0 && minor_versionp[0] >= 8);
 		}
 	}
-	
-	if (OS.GTK_VERSION > OS.VERSION (2, 17, 0)) {
-		useCairo = !"false".equals(System.getProperty("org.eclipse.swt.internal.gtk.useCairo")); 
-	}
-	
-	
-	
+
 	//TODO: Remove; temporary code only
 	boolean fixAIX = OS.IsAIX && OS.PTR_SIZEOF == 8;
 	
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
index 08e999a..bf75352 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
@@ -448,6 +448,33 @@
 	if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
 	if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+	if (OS.USE_CAIRO) {
+		int /*long*/ cairo = Cairo.cairo_create(image.surface);
+		if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		Cairo.cairo_translate(cairo, -x, -y);
+		if (data.image != null) {
+			Cairo.cairo_set_source_surface(cairo, data.image.surface, 0, 0);
+		} else if (data.drawable != 0) {
+			if (OS.GTK_VERSION >= OS.VERSION(2, 24, 0)) {
+				OS.gdk_cairo_set_source_window(cairo, data.drawable, 0, 0);
+			} else {
+				int[] w = new int[1], h = new int[1];
+				OS.gdk_drawable_get_size(data.drawable, w, h);
+				int width = w[0], height = h[0];
+				int /*long*/ xDisplay = OS.GDK_DISPLAY();
+				int /*long*/ xDrawable = OS.gdk_x11_drawable_get_xid(data.drawable);
+				int /*long*/ xVisual = OS.gdk_x11_visual_get_xvisual(OS.gdk_visual_get_system());
+				int /*long*/ srcSurface = Cairo.cairo_xlib_surface_create(xDisplay, xDrawable, xVisual, width, height);
+				Cairo.cairo_set_source_surface(cairo, srcSurface, 0, 0);
+			}
+		} else {
+			return;
+		}
+		Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE);
+		Cairo.cairo_paint(cairo);
+		Cairo.cairo_destroy(cairo);
+        return;
+	}
 	Rectangle rect = image.getBounds();
 	int /*long*/ gdkGC = OS.gdk_gc_new(image.pixmap);
 	if (gdkGC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
@@ -498,10 +525,50 @@
 	int deltaX = destX - srcX, deltaY = destY - srcY;
 	if (deltaX == 0 && deltaY == 0) return;
 	int /*long*/ drawable = data.drawable;
-	if (data.image == null && paint) OS.gdk_gc_set_exposures(handle, true);
-	OS.gdk_draw_drawable(drawable, handle, drawable, srcX, srcY, destX, destY, width, height);
+	if (OS.USE_CAIRO) {
+		if (data.image != null) {
+			Cairo.cairo_set_source_surface(handle, data.image.surface, deltaX, deltaY);
+			Cairo.cairo_rectangle(handle, destX, destY, width, height);
+			Cairo.cairo_set_operator(handle, Cairo.CAIRO_OPERATOR_SOURCE);
+			Cairo.cairo_fill(handle);
+		} else if (drawable != 0) {
+			Cairo.cairo_save(handle);
+			Cairo.cairo_rectangle(handle, destX, destY, width, height);
+			Cairo.cairo_clip(handle);
+			Cairo.cairo_translate(handle, deltaX, deltaY);
+			Cairo.cairo_set_operator(handle, Cairo.CAIRO_OPERATOR_SOURCE);
+			Cairo.cairo_push_group(handle);
+			OS.gdk_cairo_set_source_window(handle, drawable, 0, 0);
+			Cairo.cairo_paint(handle);
+			Cairo.cairo_pop_group_to_source(handle);
+			Cairo.cairo_rectangle(handle, destX - deltaX, destY - deltaY, width, height);
+			Cairo.cairo_clip(handle);
+			Cairo.cairo_paint(handle);
+			Cairo.cairo_restore(handle);
+			if (paint) {
+				int /*long*/ visibleRegion = OS.gdk_drawable_get_visible_region (drawable);
+				GdkRectangle srcRect = new GdkRectangle ();
+				srcRect.x = srcX;
+				srcRect.y = srcY;
+				srcRect.width = width;
+				srcRect.height = height;
+				int /*long*/ copyRegion = OS.gdk_region_rectangle (srcRect);
+				OS.gdk_region_intersect(copyRegion, visibleRegion);
+				int /*long*/ invalidateRegion = OS.gdk_region_rectangle (srcRect);	
+				OS.gdk_region_subtract (invalidateRegion, visibleRegion);
+				OS.gdk_region_offset (invalidateRegion, deltaX, deltaY);
+				OS.gdk_window_invalidate_region(drawable, invalidateRegion, false);
+				OS.gdk_region_destroy (visibleRegion);
+				OS.gdk_region_destroy (copyRegion);
+				OS.gdk_region_destroy (invalidateRegion);
+			}
+		}
+	} else {
+		if (data.image == null && paint) OS.gdk_gc_set_exposures(handle, true);
+		OS.gdk_draw_drawable(drawable, handle, drawable, srcX, srcY, destX, destY, width, height);
+	}
 	if (data.image == null & paint) {
-		OS.gdk_gc_set_exposures(handle, false);
+		if (!OS.USE_CAIRO) OS.gdk_gc_set_exposures(handle, false);
 		boolean disjoint = (destX + width < srcX) || (srcX + width < destX) || (destY + height < srcY) || (srcY + height < destY);
 		GdkRectangle rect = new GdkRectangle ();
 		if (disjoint) {
@@ -562,8 +629,8 @@
 	if (data.disposeCairo) {
 		int /*long*/ cairo = data.cairo;
 		if (cairo != 0) Cairo.cairo_destroy(cairo);
-		data.cairo = 0;
 	}
+	data.cairo = 0;
 
 	/* Free resources */
 	int /*long*/ clipRgn = data.clipRgn;
@@ -770,11 +837,17 @@
 }
 
 void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
-	int[] width = new int[1];
-	int[] height = new int[1];
- 	OS.gdk_drawable_get_size(srcImage.pixmap, width, height);
- 	int imgWidth = width[0];
- 	int imgHeight = height[0];
+	int imgWidth, imgHeight;
+	if (OS.USE_CAIRO){
+	 	imgWidth = srcImage.width;
+	 	imgHeight = srcImage.height;
+	} else {
+		int[] width = new int[1];
+		int[] height = new int[1];
+	 	OS.gdk_drawable_get_size(srcImage.pixmap, width, height);
+	 	imgWidth = width[0];
+	 	imgHeight = height[0];
+	}
  	if (simple) {
  		srcWidth = destWidth = imgWidth;
  		srcHeight = destHeight = imgHeight;
@@ -812,8 +885,8 @@
 			if (pattern == 0) SWT.error(SWT.ERROR_NO_HANDLES);
 			if (srcWidth != destWidth || srcHeight != destHeight) {
 				/*
-				* Bug in Cairo.  When drawing the image streched with an interpolation
-				* alghorithm, the edges of the image are faded.  This is not a bug, but
+				* Bug in Cairo.  When drawing the image stretched with an interpolation
+				* algorithm, the edges of the image are faded.  This is not a bug, but
 				* it is not desired.  To avoid the faded edges, it should be possible to
 				* use cairo_pattern_set_extend() to set the pattern extend to either
 				* CAIRO_EXTEND_REFLECT or CAIRO_EXTEND_PAD, but these are not implemented
@@ -823,10 +896,13 @@
 				* the original image in every quadrant (with an appropriate transform) and
 				* use this image as the pattern.
 				* 
-				* NOTE: For some reaons, it is necessary to use CAIRO_EXTEND_PAD with
+				* NOTE: For some reason, it is necessary to use CAIRO_EXTEND_PAD with
 				* the image that was created or the edges are still faded.
+				* 
+				* NOTE: Cairo.CAIRO_EXTEND_PAD works on Cairo 1.8.x and greater.
 				*/
-				if (Cairo.cairo_version () >= Cairo.CAIRO_VERSION_ENCODE(1, 4, 0)) {
+				int version = Cairo.cairo_version ();
+				if (version >= Cairo.CAIRO_VERSION_ENCODE(1, 4, 0) && version < Cairo.CAIRO_VERSION_ENCODE(1, 8, 0)) {
 					int /*long*/ surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, imgWidth * 3, imgHeight * 3);
 					int /*long*/ cr = Cairo.cairo_create(surface);
 					Cairo.cairo_set_source_surface(cr, srcImage.surface, imgWidth, imgHeight);
@@ -860,8 +936,9 @@
 					double[] matrix = new double[6]; 
 					Cairo.cairo_matrix_init_translate(matrix, imgWidth, imgHeight);
 					Cairo.cairo_pattern_set_matrix(pattern, matrix);
+				} else if (version >= Cairo.CAIRO_VERSION_ENCODE(1, 8, 0)) {
+					Cairo.cairo_pattern_set_extend(pattern, Cairo.CAIRO_EXTEND_PAD);
 				}
-//				Cairo.cairo_pattern_set_extend(pattern, Cairo.CAIRO_EXTEND_REFLECT);
 			}
 			Cairo.cairo_pattern_set_filter(pattern, filter);
 			Cairo.cairo_set_source(cairo, pattern);
@@ -931,15 +1008,7 @@
 		if (scaledPixbuf == 0) return;
 		pixbuf = scaledPixbuf;
 	}
-	/*
-	* Feature in GTK.  gdk_draw_pixbuf was introduced in GTK+ 2.2.0 and
-	* supports clipping.
-	*/
-	if (OS.GTK_VERSION >= OS.VERSION (2, 2, 0)) {
-		OS.gdk_draw_pixbuf(data.drawable, handle, pixbuf, 0, 0, destX, destY, destWidth, destHeight, OS.GDK_RGB_DITHER_NORMAL, 0, 0);
-	} else {
-		OS.gdk_pixbuf_render_to_drawable_alpha(pixbuf, data.drawable, 0, 0, destX, destY, destWidth, destHeight, OS.GDK_PIXBUF_ALPHA_BILEVEL, 128, OS.GDK_RGB_DITHER_NORMAL, 0, 0);
-	}
+	OS.gdk_draw_pixbuf(data.drawable, handle, pixbuf, 0, 0, destX, destY, destWidth, destHeight, OS.GDK_RGB_DITHER_NORMAL, 0, 0);
 	OS.g_object_unref(pixbuf);
 }
 void drawImageMask(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight) {
@@ -2286,15 +2355,10 @@
 	if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
 	/* Calculate visible bounds in device space */
 	int x = 0, y = 0, width = 0, height = 0;
-	if (data.width != -1 && data.height != -1) {
-		width = data.width;
-		height = data.height;
-	} else {
-		int[] w = new int[1], h = new int[1];
-		OS.gdk_drawable_get_size(data.drawable, w, h);
-		width = w[0];
-		height = h[0];
-	}
+	int[] w = new int[1], h = new int[1];
+	getSize(w, h);
+	width = w[0];
+	height = h[0];
 	/* Intersect visible bounds with clipping in device space and then convert then to user space */
 	int /*long*/ cairo = data.cairo;
 	int /*long*/ clipRgn = data.clipRgn;
@@ -2362,15 +2426,10 @@
 	int /*long*/ clipRgn = data.clipRgn;
 	if (clipRgn == 0) {
 		GdkRectangle rect = new GdkRectangle();
-		if (data.width != -1 && data.height != -1) {
-			rect.width = data.width;
-			rect.height = data.height;
-		} else {
-			int[] width = new int[1], height = new int[1];
-			OS.gdk_drawable_get_size(data.drawable, width, height);
-			rect.width = width[0];
-			rect.height = height[0];
-		}
+		int[] width = new int[1], height = new int[1];
+		getSize(width, height);
+		rect.width = width[0];
+		rect.height = height[0];
 		OS.gdk_region_union_with_rect(clipping, rect);
 	} else {
 		/* Convert clipping to device space if needed */
@@ -2673,6 +2732,31 @@
 	return data.style;
 }
 
+void getSize(int[] width, int[] height) {
+	if (data.width != -1 && data.height != -1) {
+		width[0] = data.width;
+		height[0] = data.height;
+		return;
+	}
+	if (data.drawable != 0) {
+		OS.gdk_drawable_get_size(data.drawable, width, height);
+		return;
+	}
+	if (OS.USE_CAIRO) {
+		int /*long*/ surface = Cairo.cairo_get_target(handle);
+		switch (Cairo.cairo_surface_get_type(surface)) {
+			case Cairo.CAIRO_SURFACE_TYPE_IMAGE:
+				width[0] = Cairo.cairo_image_surface_get_width(surface);
+				height[0] = Cairo.cairo_image_surface_get_height(surface);
+				break;
+			case Cairo.CAIRO_SURFACE_TYPE_XLIB: 
+				width[0] = Cairo.cairo_xlib_surface_get_width(surface);
+				height[0] = Cairo.cairo_xlib_surface_get_height(surface);
+				break;
+		}
+	}
+}
+
 /**
  * Returns the receiver's text drawing anti-aliasing setting value,
  * which will be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
@@ -2787,7 +2871,7 @@
 	double[] identity = new double[6];
 	if ((data.style & SWT.MIRRORED) != 0) {
 		int[] w = new int[1], h = new int[1];
-		OS.gdk_drawable_get_size(data.drawable, w, h);
+		getSize(w, h);
 		Cairo.cairo_matrix_init(identity, -1, 0, 0, 1, w[0], 0);
 	} else {
 		Cairo.cairo_matrix_init_identity(identity);
@@ -2816,9 +2900,14 @@
 	this.drawable = drawable;
 	this.data = data;
 	handle = gdkGC;
-	if (device.useCairo) {
-		initCairo();
+	if (OS.USE_CAIRO) {
+		int /*long*/ cairo = data.cairo = handle;
+		Cairo.cairo_set_fill_rule(cairo, Cairo.CAIRO_FILL_RULE_EVEN_ODD);
+		data.state &= ~(BACKGROUND | FOREGROUND | FONT | LINE_WIDTH | LINE_CAP | LINE_JOIN | LINE_STYLE | DRAW_OFFSET);
+	} else if (OS.INIT_CAIRO) {
+		 initCairo();
 	}
+	setClipping(data.clipRgn);
 	if ((data.style & SWT.MIRRORED) != 0) {
 	  initCairo();
 	  int /*long*/ cairo = data.cairo;
@@ -2955,7 +3044,7 @@
  */
 public void setAdvanced(boolean advanced) {
 	if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
-	if ((data.style & SWT.MIRRORED) != 0 || device.useCairo) {
+	if ((data.style & SWT.MIRRORED) != 0 || OS.USE_CAIRO || OS.INIT_CAIRO) {
 		if (!advanced) {
 			setAlpha(0xFF);
 			setAntialias(SWT.DEFAULT);
@@ -3166,10 +3255,10 @@
 
 void setCairoClip(int /*long*/ damageRgn, int /*long*/ clipRgn) {
 	int /*long*/ cairo = data.cairo;
-	if (OS.GTK_VERSION < OS.VERSION(2,18,0)) {
-		Cairo.cairo_reset_clip(cairo);
-	} else {
+	if (OS.GTK_VERSION >= OS.VERSION(2,18,0) && data.drawable != 0) {
 		OS.gdk_cairo_reset_clip(cairo, data.drawable);
+	} else {
+		Cairo.cairo_reset_clip(cairo);
 	}
 	if (damageRgn != 0) {
 		double[] matrix = new double[6];
@@ -3934,7 +4023,15 @@
  */
 public void setXORMode(boolean xor) {
 	if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
-	OS.gdk_gc_set_function(handle, xor ? OS.GDK_XOR : OS.GDK_COPY);
+	int /*long*/ cairo = data.cairo;
+	if (cairo != 0) {
+		if (Cairo.cairo_version() >= Cairo.CAIRO_VERSION_ENCODE(1, 10, 0)) {
+			Cairo.cairo_set_operator(handle, xor ? Cairo.CAIRO_OPERATOR_DIFFERENCE : Cairo.CAIRO_OPERATOR_OVER);
+		}
+	}
+	if (!OS.USE_CAIRO) {
+		OS.gdk_gc_set_function(handle, xor ? OS.GDK_XOR : OS.GDK_COPY);
+	}
 	data.xorMode = xor;
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
index c70a42a..ec42448 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java
@@ -112,7 +112,19 @@
 	 */
 	public int /*long*/ mask;
 
-	int /*long*/ surface, surfaceData;
+	/**
+	 * The handle to the OS cairo surface resource.
+	 * (Warning: This field is platform dependent)
+	 * <p>
+	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
+	 * public API. It is marked public only so that it can be shared
+	 * within the packages provided by SWT. It is not available on all
+	 * platforms and should never be accessed from application code.
+	 * </p>
+	 * 
+	 * @noreference This field is not intended to be referenced by clients.
+	 */
+	public int /*long*/ surface;
 	
 	/**
 	 * specifies the transparent pixel
@@ -234,6 +246,120 @@
 	}
 	device = this.device;
 	this.type = srcImage.type;
+	
+	if (OS.USE_CAIRO) {
+		if (flag != SWT.IMAGE_DISABLE) transparentPixel = srcImage.transparentPixel;
+		alpha = srcImage.alpha;
+		if (srcImage.alphaData != null) {
+			alphaData = new byte[srcImage.alphaData.length];
+			System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+		}
+	
+		int /*long*/ imageSurface = srcImage.surface;
+		int width = this.width = srcImage.width;
+		int height = this.height = srcImage.height;
+		int format = Cairo.cairo_surface_get_content(imageSurface) == Cairo.CAIRO_CONTENT_COLOR ? Cairo.CAIRO_FORMAT_RGB24 : Cairo.CAIRO_FORMAT_ARGB32;
+		boolean hasAlpha = format == Cairo.CAIRO_FORMAT_ARGB32;
+		surface = Cairo.cairo_image_surface_create(format, width, height);
+		if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		int /*long*/ cairo = Cairo.cairo_create(surface);
+		if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE);
+		Cairo.cairo_set_source_surface (cairo, imageSurface, 0, 0);
+		Cairo.cairo_paint (cairo);
+		Cairo.cairo_destroy(cairo);
+		if (flag != SWT.IMAGE_COPY) {
+			int stride = Cairo.cairo_image_surface_get_stride(surface);
+			int /*long*/ data = Cairo.cairo_image_surface_get_data(surface);
+			int oa, or, og, ob;
+			if (OS.BIG_ENDIAN) {
+				oa = 0; or = 1; og = 2; ob = 3;
+			} else {
+				oa = 3; or = 2; og = 1; ob = 0;
+			}
+			switch (flag) {
+				case SWT.IMAGE_DISABLE: {
+					Color zeroColor = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+					RGB zeroRGB = zeroColor.getRGB();
+					int zeroRed = zeroRGB.red;
+					int zeroGreen = zeroRGB.green;
+					int zeroBlue = zeroRGB.blue;
+					Color oneColor = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+					RGB oneRGB = oneColor.getRGB();
+					int oneRed = oneRGB.red;
+					int oneGreen = oneRGB.green;
+					int oneBlue = oneRGB.blue;
+					byte[] line = new byte[stride];
+					for (int y=0; y<height; y++) {
+						OS.memmove(line, data + (y * stride), stride);
+						for (int x=0, offset=0; x<width; x++, offset += 4) {
+							int a = line[offset + oa] & 0xFF;
+							int r = line[offset + or] & 0xFF;
+							int g = line[offset + og] & 0xFF;
+							int b = line[offset + ob] & 0xFF;
+							if (hasAlpha && a != 0) {
+								r = ((r * 0xFF) + a / 2) / a;
+								g = ((g * 0xFF) + a / 2) / a;
+								b = ((b * 0xFF) + a / 2) / a;
+							}
+							int intensity = r * r + g * g + b * b;
+							if (intensity < 98304) {
+								r = zeroRed;
+								g = zeroGreen;
+								b = zeroBlue;
+							} else {
+								r = oneRed;
+								g = oneGreen;
+								b = oneBlue;
+							}
+							if (hasAlpha) {
+								/* pre-multiplied alpha */
+								r = (r * a) + 128;
+								r = (r + (r >> 8)) >> 8;
+								g = (g * a) + 128;
+								g = (g + (g >> 8)) >> 8;
+								b = (b * a) + 128;
+								b = (b + (b >> 8)) >> 8;
+							}
+							line[offset + or] = (byte)r;
+							line[offset + og] = (byte)g;
+							line[offset + ob] = (byte)b;
+						}
+						OS.memmove(data + (y * stride), line, stride);
+					}
+					break;
+				}
+				case SWT.IMAGE_GRAY: {			
+					byte[] line = new byte[stride];
+					for (int y=0; y<height; y++) {
+						OS.memmove(line, data + (y * stride), stride);
+						for (int x=0, offset = 0; x<width; x++, offset += 4) {
+							int a = line[offset + oa] & 0xFF;
+							int r = line[offset + or] & 0xFF;
+							int g = line[offset + og] & 0xFF;
+							int b = line[offset + ob] & 0xFF;
+							if (hasAlpha && a != 0) {
+								r = ((r * 0xFF) + a / 2) / a;
+								g = ((g * 0xFF) + a / 2) / a;
+								b = ((b * 0xFF) + a / 2) / a;
+							}
+							int intensity = (r+r+g+g+g+g+g+b) >> 3;
+							if (hasAlpha) {
+								/* pre-multiplied alpha */
+								intensity = (intensity * a) + 128;
+								intensity = (intensity + (intensity >> 8)) >> 8;
+							}
+							line[offset+or] = line[offset+og] = line[offset+ob] = (byte)intensity;
+						}
+						OS.memmove(data + (y * stride), line, stride);
+					}
+					break;
+				}
+			}
+		}
+		init();
+		return;
+	}
 
 	/* Get source image size */
 	int[] w = new int[1], h = new int[1];
@@ -535,7 +661,7 @@
 	super(device);
 	if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	initNative(filename);
-	if (this.pixmap == 0) init(new ImageData(filename));
+	if (this.pixmap == 0 && this.surface == 0) init(new ImageData(filename));
 	init();
 }
 
@@ -547,37 +673,11 @@
 		byte [] buffer = Converter.wcsToMbcs(null, chars, true);
 		int /*long*/ pixbuf = OS.gdk_pixbuf_new_from_file(buffer, null);
 		if (pixbuf != 0) {
-			boolean hasAlpha = OS.gdk_pixbuf_get_has_alpha(pixbuf);
-			if (hasAlpha) {
-				/*
-				* Bug in GTK. Depending on the image (seems to affect images that have
-				* some degree of transparency all over the image), gdk_pixbuff_render_pixmap_and_mask()
-				* will return a corrupt pixmap. To avoid this, read in and store the alpha channel data
-				* for the image and then set it to 0xFF to prevent any possible corruption from 
-				* gdk_pixbuff_render_pixmap_and_mask(). 
-				*/
-				int width = OS.gdk_pixbuf_get_width(pixbuf);
-				int height = OS.gdk_pixbuf_get_height(pixbuf);
-				int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
-				int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
-				byte[] line = new byte[stride];
-				alphaData = new byte[width * height];
-				for (int y = 0; y < height; y++) {
-					OS.memmove(line, pixels + (y * stride), stride);
-					for (int x = 0; x < width; x++) {
-						alphaData[y*width+x] = line[x*4 + 3];
-						line[x*4 + 3] = (byte) 0xFF;
-					}
-					OS.memmove(pixels + (y * stride), line, stride);
-				}
-				createAlphaMask(width, height);
+			try {
+				createFromPixbuf (SWT.BITMAP, pixbuf);
+			} finally {
+				if (pixbuf != 0) OS.g_object_unref (pixbuf);
 			}
-			int /*long*/ [] pixmap_return = new int /*long*/ [1];
-			OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, null, 0);
-			this.type = SWT.BITMAP;
-			this.pixmap = pixmap_return[0];
-			if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
-			OS.g_object_unref (pixbuf);
 		}
 	} catch (SWTException e) {}
 }
@@ -613,10 +713,138 @@
 	}
 }
 
+void createFromPixbuf(int type, int /*long*/ pixbuf) {
+	this.type = type;
+	boolean hasAlpha = OS.gdk_pixbuf_get_has_alpha(pixbuf);
+	if (OS.USE_CAIRO) {
+		int width = this.width = OS.gdk_pixbuf_get_width(pixbuf);
+		int height = this.height = OS.gdk_pixbuf_get_height(pixbuf);
+		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
+		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
+		int format = hasAlpha ? Cairo.CAIRO_FORMAT_ARGB32 : Cairo.CAIRO_FORMAT_RGB24;
+		surface = Cairo.cairo_image_surface_create(format, width, height);
+		if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		int /*long*/ data = Cairo.cairo_image_surface_get_data(surface);
+		int cairoStride = Cairo.cairo_image_surface_get_stride(surface);
+		int oa = 0, or = 0, og = 0, ob = 0;
+		if (OS.BIG_ENDIAN) {
+			oa = 0; or = 1; og = 2; ob = 3;
+		} else {
+			oa = 3; or = 2; og = 1; ob = 0;
+		}
+		byte[] line = new byte[stride];
+		if (hasAlpha) {
+			alphaData = new byte[width * height];
+			for (int y = 0, alphaOffset = 0; y < height; y++) {
+				OS.memmove(line, pixels + (y * stride), stride);
+				for (int x = 0, offset = 0; x < width; x++, offset += 4) {
+					int a = line[offset + 3] & 0xFF;
+					int r = ((line[offset + 0] & 0xFF) * a) + 128;
+					r = (r + (r >> 8)) >> 8;
+					int g = ((line[offset + 1] & 0xFF) * a) + 128;
+					g = (g + (g >> 8)) >> 8;
+					int b = ((line[offset + 2] & 0xFF) * a) + 128;
+					b = (b + (b >> 8)) >> 8;
+					line[offset + oa] = (byte)a;
+					line[offset + or] = (byte)r;
+					line[offset + og] = (byte)g;
+					line[offset + ob] = (byte)b;
+					alphaData[alphaOffset++] = (byte)a;
+				}
+				OS.memmove(data + (y * stride), line, stride);
+			}
+		} else {
+			byte[] cairoLine = new byte[cairoStride];
+			for (int y = 0; y < height; y++) {
+				OS.memmove(line, pixels + (y * stride), stride);
+				for (int x = 0, offset = 0, cairoOffset = 0; x < width; x++, offset += 3, cairoOffset += 4) {
+					int r = line[offset + 0] & 0xFF;
+					int g = line[offset + 1] & 0xFF;
+					int b = line[offset + 2] & 0xFF;
+					cairoLine[cairoOffset + or] = (byte)r;
+					cairoLine[cairoOffset + og] = (byte)g;
+					cairoLine[cairoOffset + ob] = (byte)b;
+				}
+				OS.memmove(data + (y * cairoStride), cairoLine, cairoStride);
+			}
+		}
+		Cairo.cairo_surface_mark_dirty(surface);
+	} else {
+		if (hasAlpha) {
+			/*
+			* Bug in GTK. Depending on the image (seems to affect images that have
+			* some degree of transparency all over the image), gdk_pixbuff_render_pixmap_and_mask()
+			* will return a corrupt pixmap. To avoid this, read in and store the alpha channel data
+			* for the image and then set it to 0xFF to prevent any possible corruption from 
+			* gdk_pixbuff_render_pixmap_and_mask(). 
+			*/
+			int width = OS.gdk_pixbuf_get_width(pixbuf);
+			int height = OS.gdk_pixbuf_get_height(pixbuf);
+			int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
+			int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
+			byte[] line = new byte[stride];
+			alphaData = new byte[width * height];
+			for (int y = 0; y < height; y++) {
+				OS.memmove(line, pixels + (y * stride), stride);
+				for (int x = 0; x < width; x++) {
+					alphaData[y*width+x] = line[x*4 + 3];
+					line[x*4 + 3] = (byte) 0xFF;
+				}
+				OS.memmove(pixels + (y * stride), line, stride);
+			}
+			createAlphaMask(width, height);
+		}
+		int /*long*/ [] pixmap_return = new int /*long*/ [1];
+		OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, null, 0);
+		this.pixmap = pixmap_return[0];
+		if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+	}
+}
+
 /**
  * Create the receiver's mask if necessary.
  */
 void createMask() {
+	if (OS.USE_CAIRO) {
+		int width = this.width;
+		int height = this.height;
+		int stride = Cairo.cairo_image_surface_get_stride(surface);
+		int /*long*/ surfaceData = Cairo.cairo_image_surface_get_data(surface);
+		int oa, or, og, ob, tr, tg, tb;
+		if (OS.BIG_ENDIAN) {
+			oa = 0; or = 1; og = 2; ob = 3;
+			tr = (transparentPixel >> 24) & 0xFF;
+			tg = (transparentPixel >> 16) & 0xFF;
+			tb = (transparentPixel >> 8) & 0xFF;
+		} else {
+			oa = 3; or = 2; og = 1; ob = 0;
+			tr = (transparentPixel >> 16) & 0xFF;
+			tg = (transparentPixel >> 8) & 0xFF;
+			tb = (transparentPixel >> 0) & 0xFF;
+		}
+		byte[] srcData = new byte[stride * height];
+		OS.memmove(srcData, surfaceData, srcData.length);
+		int offset = 0;
+		for (int y = 0; y < height; y++) {
+			for (int x = 0; x < width; x++, offset += 4) {
+				int a = srcData[offset + oa] & 0xFF;
+				int r = srcData[offset + or] & 0xFF;
+				int g = srcData[offset + og] & 0xFF;
+				int b = srcData[offset + ob] & 0xFF;
+				if (r == tr && g == tg && b == tb) {
+					a = r = g = b = 0;
+				} else {
+					a = 0xff;
+				}
+				srcData[offset + oa] = (byte)a;
+				srcData[offset + or] = (byte)r;
+				srcData[offset + og] = (byte)g;
+				srcData[offset + ob] = (byte)b;
+			}
+		}
+		OS.memmove(surfaceData, srcData, srcData.length);
+		return;
+	}
 	if (mask != 0) return;
 	mask = createMask(getImageData(), false);
 	if (mask == 0) SWT.error(SWT.ERROR_NO_HANDLES);
@@ -651,13 +879,8 @@
 		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
 		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);		
 		byte[] line = new byte[stride];
-		int /*long*/ ptr = OS.malloc(4);
-		OS.memmove(ptr, new int[]{1}, 4);
-		OS.memmove(line, ptr, 1);
-		OS.free(ptr);
 		int oa, or, og, ob;
-		boolean bigendian = line[0] == 0;
-		if (bigendian) {
+		if (OS.BIG_ENDIAN) {
 			oa = 0; or = 1; og = 2; ob = 3;
 		} else {
 			oa = 3; or = 2; og = 1; ob = 0;
@@ -749,9 +972,10 @@
 				offset += stride;
 			}
 		}
-		surfaceData = OS.g_malloc(stride * height);
-		OS.memmove(surfaceData, pixels, stride * height);
-		surface = Cairo.cairo_image_surface_create_for_data(surfaceData, Cairo.CAIRO_FORMAT_ARGB32, width, height, stride);
+		surface = Cairo.cairo_image_surface_create(Cairo.CAIRO_FORMAT_ARGB32, width, height);
+		int /*long*/ data = Cairo.cairo_image_surface_get_data(surface);
+		OS.memmove(data, pixels, stride * height);
+		Cairo.cairo_surface_mark_dirty(surface);
 		OS.g_object_unref(pixbuf);
 	} else {
 		int /*long*/ xDisplay = OS.GDK_DISPLAY();
@@ -777,8 +1001,7 @@
 	if (pixmap != 0) OS.g_object_unref(pixmap);
 	if (mask != 0) OS.g_object_unref(mask);
 	if (surface != 0) Cairo.cairo_surface_destroy(surface);
-	if (surfaceData != 0) OS.g_free(surfaceData);
-	surfaceData = surface = pixmap = mask = 0;
+	surface = pixmap = mask = 0;
 	memGC = null;
 }
 
@@ -796,7 +1019,11 @@
 	if (object == this) return true;
 	if (!(object instanceof Image)) return false;
 	Image image = (Image)object;
-	return device == image.device && pixmap == image.pixmap;
+	if (OS.USE_CAIRO) {
+		return device == image.device && surface == image.surface;
+	} else {
+		return device == image.device && pixmap == image.pixmap;
+	}
 }
 
 /**
@@ -863,6 +1090,57 @@
 public ImageData getImageData() {
 	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
 
+	if (OS.USE_CAIRO) {
+		int /*long*/ surface = ImageList.convertSurface(this);
+		int format = Cairo.cairo_image_surface_get_format(surface);
+		int width = Cairo.cairo_image_surface_get_width(surface);
+		int height = Cairo.cairo_image_surface_get_height(surface);
+		int stride = Cairo.cairo_image_surface_get_stride(surface);
+		int /*long*/ surfaceData = Cairo.cairo_image_surface_get_data(surface);
+		boolean hasAlpha = format == Cairo.CAIRO_FORMAT_ARGB32;
+		int oa, or, og, ob;
+		if (OS.BIG_ENDIAN) {
+			oa = 0; or = 1; og = 2; ob = 3;
+		} else {
+			oa = 3; or = 2; og = 1; ob = 0;
+		}
+		byte[] srcData = new byte[stride * height];
+		OS.memmove(srcData, surfaceData, srcData.length);
+		PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
+		ImageData data = new ImageData(width, height, 32, palette, 4, srcData);
+		if (hasAlpha) {
+			byte[] alphaData = data.alphaData = new byte[width * height];
+			for (int y = 0, offset = 0, alphaOffset = 0; y < height; y++) {
+				for (int x = 0; x < width; x++, offset += 4) {
+					int a = srcData[offset + oa] & 0xFF;
+					int r = srcData[offset + or] & 0xFF;
+					int g = srcData[offset + og] & 0xFF;
+					int b = srcData[offset + ob] & 0xFF;
+					srcData[offset + 0] = 0;
+					alphaData[alphaOffset++] = (byte)a;
+					if (a != 0) {
+						srcData[offset + 1] = (byte)(((r * 0xFF) + a / 2) / a);
+						srcData[offset + 2] = (byte)(((g * 0xFF) + a / 2) / a);
+						srcData[offset + 3] = (byte)(((b * 0xFF) + a / 2) / a);
+					}
+				}
+			}
+		} else {
+			for (int y = 0, offset = 0; y < height; y++) {
+				for (int x = 0; x < width; x++, offset += 4) {
+					byte r = srcData[offset + or];
+					byte g = srcData[offset + og];
+					byte b = srcData[offset + ob];
+					srcData[offset + 0] = 0;
+					srcData[offset + 1] = r;
+					srcData[offset + 2] = g;
+					srcData[offset + 3] = b;
+				}
+			}
+		}
+		Cairo.cairo_surface_destroy(surface);
+		return data;
+	}
 	int[] w = new int[1], h = new int[1];
  	OS.gdk_drawable_get_size(pixmap, w, h);
  	int width = w[0], height = h[0]; 	
@@ -942,6 +1220,29 @@
 	return image;
 }
 
+/**	 
+ * Invokes platform specific functionality to allocate a new image.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</code>. It is marked public only so that it
+ * can be shared within the packages provided by SWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param type the type of the image (<code>SWT.BITMAP</code> or <code>SWT.ICON</code>)
+ * @param pixbuf an GdkPixbuf
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+public static Image gtk_new_from_pixbuf(Device device, int type, int /*long*/ pixbuf) {
+	Image image = new Image(device);
+	image.createFromPixbuf(type, pixbuf);
+	image.type = type;
+	return image;
+}
+
 /**
  * Returns an integer hash code for the receiver. Any two 
  * objects that return <code>true</code> when passed to 
@@ -953,7 +1254,11 @@
  * @see #equals
  */
 public int hashCode () {
-	return (int)/*64*/pixmap;
+	if (OS.USE_CAIRO) {
+		return (int)/*64*/surface;
+	} else {
+		return (int)/*64*/pixmap;
+	}
 }
 
 void init(int width, int height) {
@@ -963,6 +1268,29 @@
 	this.type = SWT.BITMAP;
 
 	/* Create the pixmap */
+	if (OS.USE_CAIRO) {
+		if (OS.GTK_VERSION >= OS.VERSION(2, 22, 0)) {
+			surface = OS.gdk_window_create_similar_surface(OS.GDK_ROOT_PARENT(), Cairo.CAIRO_CONTENT_COLOR, width, height);
+		} else {
+			int /*long*/ xDisplay = OS.GDK_DISPLAY();
+			int /*long*/ xDrawable = OS.gdk_x11_drawable_get_xid(OS.GDK_ROOT_PARENT());
+			int /*long*/ xVisual = OS.gdk_x11_visual_get_xvisual(OS.gdk_visual_get_system());
+			int /*long*/ rootSurface = Cairo.cairo_xlib_surface_create(xDisplay, xDrawable, xVisual, 1, 1);
+			if (rootSurface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+			surface = Cairo.cairo_surface_create_similar(rootSurface, Cairo.CAIRO_CONTENT_COLOR, width, height);
+			Cairo.cairo_surface_destroy(rootSurface);
+		}
+		if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		int /*long*/ cairo = Cairo.cairo_create(surface);
+		if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		Cairo.cairo_set_source_rgb(cairo, 1, 1, 1);
+		Cairo.cairo_rectangle(cairo, 0, 0, width, height);
+		Cairo.cairo_fill(cairo);
+		Cairo.cairo_destroy(cairo);
+		this.width = width;
+		this.height = height;
+		return;
+	}
 	this.pixmap = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width, height, -1);
 	if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
 	/* Fill the bitmap with white */
@@ -981,12 +1309,143 @@
 
 void init(ImageData image) {
 	if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
-	int width = image.width;
-	int height = image.height;
+	int width = this.width = image.width;
+	int height = this.height = image.height;
 	PaletteData palette = image.palette;
 	if (!(((image.depth == 1 || image.depth == 2 || image.depth == 4 || image.depth == 8) && !palette.isDirect) ||
 		((image.depth == 8) || (image.depth == 16 || image.depth == 24 || image.depth == 32) && palette.isDirect)))
 			SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+	if (OS.USE_CAIRO) {
+		boolean hasAlpha = image.transparentPixel != -1 || image.alpha != -1 || image.maskData != null || image.alphaData != null;
+		int format = hasAlpha ? Cairo.CAIRO_FORMAT_ARGB32 : Cairo.CAIRO_FORMAT_RGB24;
+		surface = Cairo.cairo_image_surface_create(format, width, height);
+		if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		int stride = Cairo.cairo_image_surface_get_stride(surface);
+		int /*long*/ data = Cairo.cairo_image_surface_get_data(surface);
+		int oa = 0, or = 0, og = 0, ob = 0;
+		int redMask, greenMask, blueMask, destDepth = 32, destOrder;
+		if (OS.BIG_ENDIAN) {
+			oa = 0; or = 1; og = 2; ob = 3;
+			redMask = 0xFF00;
+			greenMask = 0xFF0000;
+			blueMask = 0xFF000000;
+			destOrder = ImageData.MSB_FIRST;
+		} else {
+			oa = 3; or = 2; og = 1; ob = 0;
+			redMask = 0xFF0000;
+			greenMask = 0xFF00;
+			blueMask = 0xFF;
+			destOrder = ImageData.LSB_FIRST;
+		}
+		byte[] buffer = image.data;
+		if (!palette.isDirect || image.depth != destDepth || stride != image.bytesPerLine || palette.redMask != redMask || palette.greenMask != greenMask || palette.blueMask != blueMask || destOrder != image.getByteOrder()) {
+			buffer = new byte[stride * height];
+			if (palette.isDirect) {
+				ImageData.blit(ImageData.BLIT_SRC,
+					image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, palette.redMask, palette.greenMask, palette.blueMask,
+					ImageData.ALPHA_OPAQUE, null, 0, 0, 0, 
+					buffer, destDepth, stride, destOrder, 0, 0, width, height, redMask, greenMask, blueMask,
+					false, false);
+			} else {
+				RGB[] rgbs = palette.getRGBs();
+				int length = rgbs.length;
+				byte[] srcReds = new byte[length];
+				byte[] srcGreens = new byte[length];
+				byte[] srcBlues = new byte[length];
+				for (int i = 0; i < rgbs.length; i++) {
+					RGB rgb = rgbs[i];
+					if (rgb == null) continue;
+					srcReds[i] = (byte)rgb.red;
+					srcGreens[i] = (byte)rgb.green;
+					srcBlues[i] = (byte)rgb.blue;
+				}
+				ImageData.blit(ImageData.BLIT_SRC,
+					image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+					ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+					buffer, destDepth, stride, destOrder, 0, 0, width, height, redMask, greenMask, blueMask,
+					false, false);
+			}
+		}
+		boolean isIcon = image.getTransparencyType() == SWT.TRANSPARENCY_MASK;
+		this.type = isIcon ? SWT.ICON : SWT.BITMAP;
+		if (isIcon || image.transparentPixel != -1) {
+			if (image.transparentPixel != -1) {
+				RGB rgb = null;
+				if (palette.isDirect) {
+					rgb = palette.getRGB(image.transparentPixel);
+				} else {
+					if (image.transparentPixel < palette.colors.length) {
+						rgb = palette.getRGB(image.transparentPixel);
+					}
+				}
+				if (rgb != null) {
+					transparentPixel = rgb.red << 16 | rgb.green << 8 | rgb.blue;
+				}
+			}
+			ImageData mask = image.getTransparencyMask();
+			for (int y = 0, offset = 0; y < height; y++) {
+				for (int x=0; x<width; x++, offset += 4) {
+					int alpha = mask.getPixel(x, y) == 0 ? 0 : 0xff;
+					/* pre-multiplied alpha */
+					int r = ((buffer[offset + or] & 0xFF) * alpha) + 128;
+					r = (r + (r >> 8)) >> 8;
+					int g = ((buffer[offset + og] & 0xFF) * alpha) + 128;
+					g = (g + (g >> 8)) >> 8;
+					int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128;
+					b = (b + (b >> 8)) >> 8;
+					buffer[offset + oa] = (byte)alpha;
+					buffer[offset + or] = (byte)r;
+					buffer[offset + og] = (byte)g;
+					buffer[offset + ob] = (byte)b;
+				}
+			}
+		} else {
+			this.alpha = image.alpha;
+			if (image.alpha == -1 && image.alphaData != null) {
+				this.alphaData = new byte[image.alphaData.length];
+				System.arraycopy(image.alphaData, 0, this.alphaData, 0, alphaData.length);
+			}
+			if (this.alpha != -1) {
+				for (int y = 0, offset = 0; y < height; y++) {
+					for (int x=0; x<width; x++, offset += 4) {
+						int alpha = this.alpha;
+						/* pre-multiplied alpha */
+						int r = ((buffer[offset + or] & 0xFF) * alpha) + 128;
+						r = (r + (r >> 8)) >> 8;
+						int g = ((buffer[offset + og] & 0xFF) * alpha) + 128;
+						g = (g + (g >> 8)) >> 8;
+						int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128;
+						b = (b + (b >> 8)) >> 8;
+						buffer[offset + oa] = (byte)alpha;
+						buffer[offset + or] = (byte)r;
+						buffer[offset + og] = (byte)g;
+						buffer[offset + ob] = (byte)b;
+					}
+				}
+			} else if (this.alphaData != null) {
+				for (int y = 0, offset = 0; y < height; y++) {
+					for (int x=0; x<width; x++, offset += 4) {
+						int alpha = alphaData [y*width+x] & 0xFF;
+						/* pre-multiplied alpha */
+						int r = ((buffer[offset + or] & 0xFF) * alpha) + 128;
+						r = (r + (r >> 8)) >> 8;
+						int g = ((buffer[offset + og] & 0xFF) * alpha) + 128;
+						g = (g + (g >> 8)) >> 8;
+						int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128;
+						b = (b + (b >> 8)) >> 8;
+						buffer[offset + oa] = (byte)alpha;
+						buffer[offset + or] = (byte)r;
+						buffer[offset + og] = (byte)g;
+						buffer[offset + ob] = (byte)b;
+					}
+				}
+			}
+		}
+		OS.memmove(data, buffer, stride * height);
+		Cairo.cairo_surface_mark_dirty(surface);
+		//TODO convert to XLIB surface if opaque for better performance
+		return;
+	}
 	int /*long*/ pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height);
 	if (pixbuf == 0) SWT.error(SWT.ERROR_NO_HANDLES);
 	int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
@@ -1081,11 +1540,16 @@
  * @noreference This method is not intended to be referenced by clients.
  */
 public int /*long*/ internal_new_GC (GCData data) {
-	if (pixmap == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
 	if (type != SWT.BITMAP || memGC != null) {
 		SWT.error(SWT.ERROR_INVALID_ARGUMENT);
 	}
-	int /*long*/ gdkGC = OS.gdk_gc_new(pixmap);
+	int /*long*/ gc;
+	if (OS.USE_CAIRO) {
+		gc = Cairo.cairo_create(surface);
+	} else {
+		gc = OS.gdk_gc_new(pixmap);
+	}
 	if (data != null) {
 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
 		if ((data.style & mask) == 0) {
@@ -1102,7 +1566,7 @@
 		data.font = device.systemFont;
 		data.image = this;
 	}
-	return gdkGC;
+	return gc;
 }
 
 /**	 
@@ -1120,8 +1584,12 @@
  * 
  * @noreference This method is not intended to be referenced by clients.
  */
-public void internal_dispose_GC (int /*long*/ gdkGC, GCData data) {
-	OS.g_object_unref(gdkGC);
+public void internal_dispose_GC (int /*long*/ gc, GCData data) {
+	if (OS.USE_CAIRO) {
+		Cairo.cairo_destroy(gc);
+	} else {
+		OS.g_object_unref(gc);
+	}
 }
 
 /**
@@ -1135,7 +1603,11 @@
  * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
  */
 public boolean isDisposed() {
-	return pixmap == 0;
+	if (OS.USE_CAIRO) {
+		return surface == 0;
+	} else {
+		return pixmap == 0;
+	}
 }
 
 /**
@@ -1188,7 +1660,11 @@
  */
 public String toString () {
 	if (isDisposed()) return "Image {*DISPOSED*}";
-	return "Image {" + pixmap + "}";
+	if (OS.USE_CAIRO) {
+		return "Image {" + surface + "}";
+	} else {
+		return "Image {" + pixmap + "}";
+	}
 }
 
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/ImageList.java
new file mode 100644
index 0000000..c678e49
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/internal/ImageList.java
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal;
+
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.cairo.*;
+import org.eclipse.swt.internal.gtk.*;
+import org.eclipse.swt.graphics.*;
+
+public class ImageList {
+	int /*long*/ [] pixbufs;
+	int width = -1, height = -1;
+	Image [] images;
+	
+public ImageList() {
+	images = new Image [4];
+	pixbufs = new int /*long*/ [4];
+}
+
+public static int /*long*/ convertSurface(Image image) {
+	int /*long*/ newSurface = image.surface;
+	int type = Cairo.cairo_surface_get_type(newSurface);
+	if (type != Cairo.CAIRO_SURFACE_TYPE_IMAGE) {
+		Rectangle bounds = image.getBounds();
+		int format = Cairo.cairo_surface_get_content(newSurface) == Cairo.CAIRO_CONTENT_COLOR ? Cairo.CAIRO_FORMAT_RGB24 : Cairo.CAIRO_FORMAT_ARGB32;
+		newSurface = Cairo.cairo_image_surface_create(format, bounds.width, bounds.height);
+		if (newSurface == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		int /*long*/ cairo = Cairo.cairo_create(newSurface);
+		if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE);
+		Cairo.cairo_set_source_surface (cairo, image.surface, 0, 0);
+		Cairo.cairo_paint (cairo);
+		Cairo.cairo_destroy(cairo);
+	} else {
+		Cairo.cairo_surface_reference(newSurface);
+	}
+	return newSurface;
+}
+
+public static int /*long*/ createPixbuf(Image image) {
+	int /*long*/ pixbuf;
+	if (OS.USE_CAIRO) {
+		int /*long*/ surface = convertSurface(image);
+		int format = Cairo.cairo_image_surface_get_format(surface);
+		int width = Cairo.cairo_image_surface_get_width(surface);
+		int height = Cairo.cairo_image_surface_get_height(surface);
+		boolean hasAlpha = format == Cairo.CAIRO_FORMAT_ARGB32;
+		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, width, height);
+		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+		int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
+		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
+		int oa, or, og, ob;
+		if (OS.BIG_ENDIAN) {
+			oa = 0; or = 1; og = 2; ob = 3;
+		} else {
+			oa = 3; or = 2; og = 1; ob = 0;
+		}
+		byte[] line = new byte[stride];
+		int /*long*/ surfaceData = Cairo.cairo_image_surface_get_data(surface);
+		if (hasAlpha) {
+			for (int y = 0; y < height; y++) {
+				OS.memmove (line, surfaceData + (y * stride), stride);
+				for (int x = 0, offset = 0; x < width; x++, offset += 4) {
+					int a = line[offset + oa] & 0xFF;
+					int r = line[offset + or] & 0xFF;
+					int g = line[offset + og] & 0xFF;
+					int b = line[offset + ob] & 0xFF;
+					line[offset + 3] = (byte)a;
+					if (a != 0) {
+						line[offset + 0] = (byte)(((r * 0xFF) + a / 2) / a);
+						line[offset + 1] = (byte)(((g * 0xFF) + a / 2) / a);
+						line[offset + 2] = (byte)(((b * 0xFF) + a / 2) / a);
+					}
+				}
+				OS.memmove (pixels + (y * stride), line, stride);
+			}
+		} else {
+			int cairoStride = Cairo.cairo_image_surface_get_stride(surface);
+			byte[] cairoLine = new byte[cairoStride];
+			for (int y = 0; y < height; y++) {
+				OS.memmove (cairoLine, surfaceData + (y * cairoStride), cairoStride);
+				for (int x = 0, offset = 0, cairoOffset = 0; x < width; x++, offset += 3, cairoOffset += 4) {
+					byte r = cairoLine[cairoOffset + or];
+					byte g = cairoLine[cairoOffset + og];
+					byte b = cairoLine[cairoOffset + ob];
+					line[offset + 0] = r;
+					line[offset + 1] = g;
+					line[offset + 2] = b;
+				}
+				OS.memmove (pixels + (y * stride), line, stride);
+			}
+		}
+		Cairo.cairo_surface_destroy(surface);
+	} else {
+		int [] w = new int [1], h = new int [1];
+	 	OS.gdk_drawable_get_size (image.pixmap, w, h);
+		int /*long*/ colormap = OS.gdk_colormap_get_system ();
+		boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1;
+		if (hasMask) {
+			pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]);
+			if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+			OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
+			int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]);
+			if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+			OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]);
+			int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
+			int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
+			byte[] line = new byte[stride];
+			int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
+			int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
+			byte[] maskLine = new byte[maskStride];
+			for (int y=0; y<h[0]; y++) {
+				int /*long*/ offset = pixels + (y * stride);
+				OS.memmove(line, offset, stride);
+				int /*long*/ maskOffset = maskPixels + (y * maskStride);
+				OS.memmove(maskLine, maskOffset, maskStride);
+				for (int x=0; x<w[0]; x++) {
+					if (maskLine[x * 3] == 0) {
+						line[x * 4 + 3] = 0;
+					}
+				}
+				OS.memmove(offset, line, stride);
+			}
+			OS.g_object_unref(maskPixbuf);
+		} else {
+			ImageData data = image.getImageData ();
+			boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA;
+			pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]);
+			if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+			OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
+			if (hasAlpha) {
+				byte [] alpha = data.alphaData;
+				int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
+				int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
+				byte [] line = new byte [stride];
+				for (int y = 0; y < h [0]; y++) {
+					int /*long*/ offset = pixels + (y * stride);
+					OS.memmove (line, offset, stride);
+					for (int x = 0; x < w [0]; x++) {
+						line [x*4+3] = alpha [y*w [0]+x];
+					}
+					OS.memmove (offset, line, stride);
+				}
+			}
+		}
+	}
+	return pixbuf;
+}
+
+public int add (Image image) {
+	int index = 0;
+	while (index < images.length) {
+		if (images [index] != null) {
+			if (images [index].isDisposed ()) {
+				OS.g_object_unref (pixbufs [index]);
+				images [index] = null;
+				pixbufs [index] = 0;
+			}
+		}
+		if (images [index] == null) break;
+		index++;
+	}
+	if (index == images.length) {
+		Image [] newImages = new Image [images.length + 4];
+		System.arraycopy (images, 0, newImages, 0, images.length);
+		images = newImages;
+		int /*long*/ [] newPixbufs = new int /*long*/ [pixbufs.length + 4];
+		System.arraycopy (pixbufs, 0, newPixbufs, 0, pixbufs.length);
+		pixbufs = newPixbufs;
+	}
+	set (index, image);
+	return index;
+}
+
+public void dispose () {
+	if (pixbufs == null) return;
+	for (int index=0; index<pixbufs.length; index++) {
+		if (pixbufs [index] != 0) OS.g_object_unref (pixbufs [index]);
+	}
+	images = null;
+	pixbufs = null;
+}
+
+public Image get (int index) {
+	return images [index];
+}
+
+public int /*long*/ getPixbuf (int index) {
+	return pixbufs [index];
+}
+
+public int indexOf (Image image) {
+	if (image == null) return -1;
+	for (int index=0; index<images.length; index++) {
+		if (image == images [index]) return index;
+	}
+	return -1;
+}
+
+public int indexOf (int /*long*/ pixbuf) {
+	if (pixbuf == 0) return -1;
+	for (int index=0; index<images.length; index++) {
+		if (pixbuf == pixbufs [index]) return index;
+	}
+	return -1;
+}
+
+public boolean isDisposed () {
+	return images == null;
+}
+
+public void put (int index, Image image) {
+	int count = images.length;
+	if (!(0 <= index && index < count)) return;
+	if (image != null) {
+		set (index, image);
+	} else {
+		images [index] = null;	
+		if (pixbufs [index] != 0) OS.g_object_unref (pixbufs [index]);
+		pixbufs [index] = 0;
+	}
+}
+
+public void remove (Image image) {
+	if (image == null) return;
+	for (int index=0; index<images.length; index++) {
+		if (image == images [index]){
+			OS.g_object_unref (pixbufs [index]);
+			images [index] = null;
+			pixbufs [index] = 0;
+		}
+	}
+}
+
+void set (int index, Image image) {
+	int /*long*/ pixbuf = createPixbuf (image);
+	int w = OS.gdk_pixbuf_get_width(pixbuf);
+	int h = OS.gdk_pixbuf_get_height(pixbuf);
+	if (width == -1 || height == -1) {
+		width = w;
+		height = h;
+	}
+	if (w != width || h != height) {
+		int /*long*/ scaledPixbuf = OS.gdk_pixbuf_scale_simple(pixbuf, width, height, OS.GDK_INTERP_BILINEAR);
+		OS.g_object_unref (pixbuf);
+		pixbuf = scaledPixbuf;
+	}
+	int /*long*/ oldPixbuf = pixbufs [index];
+	if (oldPixbuf != 0) {
+		if (images [index] == image) {
+			OS.gdk_pixbuf_copy_area (pixbuf, 0, 0, width, height, oldPixbuf, 0, 0);
+			OS.g_object_unref (pixbuf);
+			pixbuf = oldPixbuf;
+		} else {
+			OS.g_object_unref (oldPixbuf);
+		}
+	}
+	pixbufs [index] = pixbuf;
+	images [index] = image;	
+}
+
+public int size () {
+	int result = 0;
+	for (int index=0; index<images.length; index++) {
+		if (images [index] != null) {
+			if (images [index].isDisposed ()) {
+				OS.g_object_unref (pixbufs [index]);
+				images [index] = null;
+				pixbufs [index] = 0;
+			}
+			if (images [index] != null) result++;
+		}
+	}
+	return result;
+}
+
+}
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 3fd382c..1799563 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
@@ -275,6 +275,7 @@
 //		GC gc = new GC (this);
 //		gc.copyArea (x, y, width, height, destX, destY);
 //		gc.dispose ();
+		//TODO: Use Cairo
 		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);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Caret.java
index b5034c6..ddb8b1c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Caret.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Caret.java
@@ -12,6 +12,7 @@
 
 
 import org.eclipse.swt.*;
+import org.eclipse.swt.internal.cairo.*;
 import org.eclipse.swt.internal.gtk.*;
 import org.eclipse.swt.graphics.*;
 
@@ -97,6 +98,38 @@
 	if (parent == null) return false;
 	if (parent.isDisposed ()) return false;
 	int /*long*/ window = parent.paintWindow ();
+	if (OS.USE_CAIRO) {
+		int /*long*/ cairo = OS.gdk_cairo_create(window);
+		if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+		Cairo.cairo_set_source_rgb(cairo, 1, 1, 1);
+		Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_DIFFERENCE);
+		if (image != null && !image.isDisposed() && image.mask == 0) {
+			int /*long*/ surface = Cairo.cairo_get_target(cairo);
+			int nWidth = 0;
+			switch (Cairo.cairo_surface_get_type(surface)) {
+				case Cairo.CAIRO_SURFACE_TYPE_IMAGE:
+					nWidth = Cairo.cairo_image_surface_get_width(surface);
+					break;
+				case Cairo.CAIRO_SURFACE_TYPE_XLIB: 
+					nWidth = Cairo.cairo_xlib_surface_get_width(surface);
+					break;
+			}
+			int nX = x;
+			if ((parent.style & SWT.MIRRORED) != 0) nX = parent.getClientWidth () - nWidth - nX;
+			Cairo.cairo_translate(cairo, nX, y); 
+			Cairo.cairo_set_source_surface(cairo, image.surface, 0, 0);
+			Cairo.cairo_paint(cairo);
+		} else {
+			int nWidth = width, nHeight = height;
+			if (nWidth <= 0) nWidth = DEFAULT_WIDTH;
+			int nX = x;
+			if ((parent.style & SWT.MIRRORED) != 0) nX = parent.getClientWidth () - nWidth - nX;
+			Cairo.cairo_rectangle(cairo, nX, y, nWidth, nHeight);
+		}
+		Cairo.cairo_fill(cairo);
+		Cairo.cairo_destroy(cairo);
+		return true;
+	}
 	int /*long*/ gc = OS.gdk_gc_new (window);
 	GdkColor color = new GdkColor ();
 	color.red = (short) 0xffff;
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 4aaf4d3..29ba309 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
@@ -372,14 +372,19 @@
 				Cairo.cairo_translate (cairo, -pt.x - offsetX, -pt.y - offsetY);
 				x += pt.x + offsetX;
 				y += pt.y + offsetY;
-				int /*long*/ xDisplay = OS.GDK_DISPLAY ();
-				int /*long*/ xVisual = OS.gdk_x11_visual_get_xvisual (OS.gdk_visual_get_system());
-				int /*long*/ drawable = control.backgroundImage.pixmap;
-				int /*long*/ xDrawable = OS.GDK_PIXMAP_XID (drawable);				
-				int [] w = new int [1], h = new int [1];
-				OS.gdk_drawable_get_size (drawable, w, h);
-				int /*long*/ surface = Cairo.cairo_xlib_surface_create (xDisplay, xDrawable, xVisual, w [0], h [0]);
-				if (surface == 0) error (SWT.ERROR_NO_HANDLES);
+				int /*long*/ surface = control.backgroundImage.surface;
+				if (surface == 0) {
+					int /*long*/ xDisplay = OS.GDK_DISPLAY ();
+					int /*long*/ xVisual = OS.gdk_x11_visual_get_xvisual (OS.gdk_visual_get_system());
+					int /*long*/ drawable = control.backgroundImage.pixmap;
+					int /*long*/ xDrawable = OS.GDK_PIXMAP_XID (drawable);				
+					int [] w = new int [1], h = new int [1];
+					OS.gdk_drawable_get_size (drawable, w, h);
+					surface = Cairo.cairo_xlib_surface_create (xDisplay, xDrawable, xVisual, w [0], h [0]);
+					if (surface == 0) error (SWT.ERROR_NO_HANDLES);
+				} else {
+					Cairo.cairo_surface_reference(surface);
+				}
 				int /*long*/ pattern = Cairo.cairo_pattern_create_for_surface (surface);
 				if (pattern == 0) error (SWT.ERROR_NO_HANDLES);
 				Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT);
@@ -720,7 +725,6 @@
 		GCData data = new GCData ();
 		data.damageRgn = damageRgn;
 		GC gc = event.gc = GC.gtk_new (this, data);
-		OS.gdk_gc_set_clip_region (gc.handle, damageRgn);
 		sendEvent (SWT.Paint, event);
 		gc.dispose ();
 		OS.gdk_region_destroy (damageRgn);
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 28047f9..912e78f 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
@@ -109,6 +109,36 @@
 }
 
 void drawBackground (Control control, int /*long*/ window, int /*long*/ region, int x, int y, int width, int height) {
+	if (OS.USE_CAIRO) {
+		int /*long*/ cairo = OS.gdk_cairo_create(window);
+		if (cairo == 0) error (SWT.ERROR_NO_HANDLES);
+		if (region != 0) {
+			OS.gdk_cairo_region(cairo, region);
+			Cairo.cairo_clip(cairo);
+		}
+		if (control.backgroundImage != null) {
+			Point pt = display.map (this, control, 0, 0);
+			Cairo.cairo_translate (cairo, -pt.x, -pt.y);
+			x += pt.x;
+			y += pt.y;
+			int /*long*/ pattern = Cairo.cairo_pattern_create_for_surface (control.backgroundImage.surface);
+			if (pattern == 0) error (SWT.ERROR_NO_HANDLES);
+			Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT);
+			if ((style & SWT.MIRRORED) != 0) {
+				double[] matrix = {-1, 0, 0, 1, 0, 0};
+				Cairo.cairo_pattern_set_matrix(pattern, matrix);
+			}
+			Cairo.cairo_set_source (cairo, pattern);
+			Cairo.cairo_pattern_destroy (pattern);
+		} else {
+			GdkColor color = control.getBackgroundColor ();
+			Cairo.cairo_set_source_rgba (cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF, 1);
+		}
+		Cairo.cairo_rectangle (cairo, x, y, width, height);
+		Cairo.cairo_fill (cairo);
+		Cairo.cairo_destroy(cairo);
+		return;
+	}
 	int /*long*/ gdkGC = OS.gdk_gc_new (window);
 	if (region != 0) OS.gdk_gc_set_clip_region (gdkGC, region);
 	if (control.backgroundImage != null) {
@@ -359,7 +389,9 @@
 	int /*long*/ window = OS.GTK_WIDGET_WINDOW (topHandle);
 	GCData data = gc.getGCData ();
 	OS.gdk_window_process_updates (window, true);
-	printWidget (gc, data.drawable, OS.gdk_drawable_get_depth (data.drawable), 0, 0);
+	int /*long*/ drawable = data.drawable;
+	if (drawable == 0) drawable = OS.GDK_ROOT_PARENT();
+	printWidget (gc, drawable, OS.gdk_drawable_get_depth (drawable), 0, 0);
 	return true;
 }
 
@@ -2959,7 +2991,6 @@
 	GCData data = new GCData ();
 	data.damageRgn = gdkEvent.region;
 	GC gc = event.gc = GC.gtk_new (this, data);
-	OS.gdk_gc_set_clip_region (gc.handle, gdkEvent.region);
 	sendEvent (SWT.Paint, event);
 	gc.dispose ();
 	event.gc = null;
@@ -3105,7 +3136,7 @@
 		OS.gtk_im_context_set_client_window (imHandle, window);
 	}
 	if (backgroundImage != null) {
-		setBackgroundPixmap (backgroundImage.pixmap);
+		setBackgroundPixmap (backgroundImage);
 	}
 	return 0;
 }
@@ -3133,7 +3164,7 @@
 
 int /*long*/ gtk_style_set (int /*long*/ widget, int /*long*/ previousStyle) {
 	if (backgroundImage != null) {
-		setBackgroundPixmap (backgroundImage.pixmap);
+		setBackgroundPixmap (backgroundImage);
 	}
 	return 0;
 }
@@ -3196,8 +3227,13 @@
 	checkWidget ();
 	int /*long*/ window = paintWindow ();
 	if (window == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-	int /*long*/ gdkGC = OS.gdk_gc_new (window);
-	if (gdkGC == 0) error (SWT.ERROR_NO_HANDLES);	
+	int /*long*/ gc;
+	if (OS.USE_CAIRO) {
+		gc = OS.gdk_cairo_create (window);
+	} else {
+		gc = OS.gdk_gc_new (window);
+	}
+	if (gc == 0) error (SWT.ERROR_NO_HANDLES);	
 	if (data != null) {
 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
 		if ((data.style & mask) == 0) {
@@ -3215,7 +3251,7 @@
 		data.background = control.getBackgroundColor ();
 		data.font = font != null ? font : defaultFont (); 
 	}	
-	return gdkGC;
+	return gc;
 }
 
 int /*long*/ imHandle () {
@@ -3237,9 +3273,13 @@
  * 
  * @noreference This method is not intended to be referenced by clients.
  */
-public void internal_dispose_GC (int /*long*/ gdkGC, GCData data) {
+public void internal_dispose_GC (int /*long*/ gc, GCData data) {
 	checkWidget ();
-	OS.g_object_unref (gdkGC);
+	if (OS.USE_CAIRO) {
+		Cairo.cairo_destroy (gc);
+	} else {
+		OS.g_object_unref (gc);
+	}
 }
 
 /**
@@ -3766,7 +3806,7 @@
 	if (image == backgroundImage) return;
 	this.backgroundImage = image;
 	if (backgroundImage != null) {
-		setBackgroundPixmap (backgroundImage.pixmap);
+		setBackgroundPixmap (backgroundImage);
 		redrawWidget (0, 0, 0, 0, true, false, false);
 	} else {
 		setWidgetBackground ();
@@ -3774,9 +3814,30 @@
 	redrawChildren ();
 }
 
-void setBackgroundPixmap (int /*long*/ pixmap) {
+void setBackgroundPixmap (Image image) {
 	int /*long*/ window = OS.GTK_WIDGET_WINDOW (paintHandle ());
-	if (window != 0) OS.gdk_window_set_back_pixmap (window, pixmap, false);
+	if (window != 0) {
+		if (image.pixmap != 0) {
+			OS.gdk_window_set_back_pixmap (window, image.pixmap, false);
+		} else if (image.surface != 0) {
+			/*
+			* TODO This code code is commented because it does not work since the pixmap
+			* created with gdk_pixmap_foreign_new() does not have colormap. Another option
+			* would be to create a pixmap on the fly from the surface.
+			* 
+			* For now draw background in windowProc().
+			*/
+//			int /*long*/ surface = image.surface;
+//			int type = Cairo.cairo_surface_get_type(surface);
+//			switch (type) {
+//				case Cairo.CAIRO_SURFACE_TYPE_XLIB:
+//					int /*long*/ pixmap = OS.gdk_pixmap_foreign_new(Cairo.cairo_xlib_surface_get_drawable(surface));
+//					OS.gdk_window_set_back_pixmap (window, pixmap, false);
+//					OS.g_object_unref(pixmap);
+//					break;
+//			}
+		}
+	}
 }
 
 /**
@@ -4996,7 +5057,19 @@
 int /*long*/ windowProc (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
 	switch ((int)/*64*/user_data) {
 		case EXPOSE_EVENT_INVERSE: {
-			if ((OS.GTK_VERSION <  OS.VERSION (2, 8, 0)) && ((state & OBSCURED) == 0)) {
+			if ((state & OBSCURED) != 0) break;
+			if (OS.USE_CAIRO) {
+				Control control = findBackgroundControl ();
+				if (control != null && control.backgroundImage != null) {
+					GdkEventExpose gdkEvent = new GdkEventExpose ();
+					OS.memmove (gdkEvent, arg0, GdkEventExpose.sizeof);
+					int /*long*/ paintWindow = paintWindow();
+					int /*long*/ window = gdkEvent.window;
+					if (window != paintWindow) break;
+					drawBackground(control, window, gdkEvent.region, gdkEvent.area_y, gdkEvent.area_y, gdkEvent.area_width, gdkEvent.area_height);
+				}
+			}
+			if (OS.GTK_VERSION <  OS.VERSION (2, 8, 0)) {
 				Control control = findBackgroundControl ();
 				if (control != null && control.backgroundImage != null) {
 					GdkEventExpose gdkEvent = new GdkEventExpose ();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Decorations.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Decorations.java
index 97f3422..19fa5cf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Decorations.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Decorations.java
@@ -11,6 +11,7 @@
 package org.eclipse.swt.widgets;
 
 import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
 import org.eclipse.swt.internal.gtk.*;
 import org.eclipse.swt.graphics.*;
 
@@ -175,7 +176,7 @@
 	if (images != null) {
 		for (int i = 0; i < images.length; i++) {
 			Image image = images [i];
-			int /*long*/ pixbuf = Display.createPixbuf (image);
+			int /*long*/ pixbuf = ImageList.createPixbuf (image);
 			pixbufs = OS.g_list_append (pixbufs, pixbuf);			
 		}
 	}
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 69cb570..45a9973 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
@@ -13,6 +13,7 @@
 
 import org.eclipse.swt.*;
 import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.cairo.*;
 import org.eclipse.swt.internal.gtk.*;
 import org.eclipse.swt.graphics.*;
 
@@ -215,10 +216,6 @@
 	boolean idleNeeded;
 	
 	/* GtkTreeView callbacks */
-	int[] treeSelection;
-	int treeSelectionLength;
-	int /*long*/ treeSelectionProc;
-	Callback treeSelectionCallback;
 	int /*long*/ cellDataProc;
 	Callback cellDataCallback;
 	
@@ -904,7 +901,9 @@
 	if (!OS.g_thread_supported ()) {
 		OS.g_thread_init (0);
 	}
-	OS.gtk_set_locale();
+	if (OS.GTK_VERSION < OS.VERSION(2, 24, 0)) {
+	    OS.gtk_set_locale();
+	}
 	if (!OS.gtk_init_check (new int /*long*/ [] {0}, null)) {
 		SWT.error (SWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]"); //$NON-NLS-1$
 	}
@@ -985,7 +984,6 @@
 	}
 	
 	OS.gtk_widget_set_default_direction (OS.GTK_TEXT_DIR_LTR);
-	OS.gdk_rgb_init ();
 	byte [] buffer = Converter.wcsToMbcs (null, APP_NAME, true);
 	OS.g_set_prgname (buffer);
 	OS.gdk_set_program_class (buffer);
@@ -1058,62 +1056,6 @@
 	return new Image (this, imageData);
 }
 
-static int /*long*/ createPixbuf(Image image) {
-	int [] w = new int [1], h = new int [1];
- 	OS.gdk_drawable_get_size (image.pixmap, w, h);
-	int /*long*/ colormap = OS.gdk_colormap_get_system ();
-	int /*long*/ pixbuf;
-	boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1;
-	if (hasMask) {
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]);
-		if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]);
-		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
-		int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
-		byte[] line = new byte[stride];
-		int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
-		int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
-		byte[] maskLine = new byte[maskStride];
-		for (int y=0; y<h[0]; y++) {
-			int /*long*/ offset = pixels + (y * stride);
-			OS.memmove(line, offset, stride);
-			int /*long*/ maskOffset = maskPixels + (y * maskStride);
-			OS.memmove(maskLine, maskOffset, maskStride);
-			for (int x=0; x<w[0]; x++) {
-				if (maskLine[x * 3] == 0) {
-					line[x * 4 + 3] = 0;
-				}
-			}
-			OS.memmove(offset, line, stride);
-		}
-		OS.g_object_unref(maskPixbuf);
-	} else {
-		ImageData data = image.getImageData ();
-		boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA;
-		pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]);
-		if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]);
-		if (hasAlpha) {
-			byte [] alpha = data.alphaData;
-			int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
-			int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
-			byte [] line = new byte [stride];
-			for (int y = 0; y < h [0]; y++) {
-				int /*long*/ offset = pixels + (y * stride);
-				OS.memmove (line, offset, stride);
-				for (int x = 0; x < w [0]; x++) {
-					line [x*4+3] = alpha [y*w [0]+x];
-				}
-				OS.memmove (offset, line, stride);
-			}
-		}
-	}
-	return pixbuf;
-}
-
 static void deregister (Display display) {
 	synchronized (Device.class) {
 		for (int i=0; i<Displays.length; i++) {
@@ -2601,10 +2543,6 @@
 
 	shellMapProcClosure = OS.g_cclosure_new (shellMapProc, 0, 0);
 	OS.g_closure_ref (shellMapProcClosure);
-
-	treeSelectionCallback = new Callback(this, "treeSelectionProc", 4); //$NON-NLS-1$
-	treeSelectionProc = treeSelectionCallback.getAddress();
-	if (treeSelectionProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
 	
 	cellDataCallback = new Callback (this, "cellDataProc", 5); //$NON-NLS-1$
 	cellDataProc = cellDataCallback.getAddress ();
@@ -2702,8 +2640,12 @@
  * 
  * @noreference This method is not intended to be referenced by clients.
  */
-public void internal_dispose_GC (int /*long*/ gdkGC, GCData data) {
-	OS.g_object_unref (gdkGC);
+public void internal_dispose_GC (int /*long*/ gc, GCData data) {
+	if (OS.USE_CAIRO) {
+		Cairo.cairo_destroy (gc);
+	} else {
+		OS.g_object_unref (gc);
+	}
 }
 
 /**	 
@@ -2731,9 +2673,16 @@
 public int /*long*/ internal_new_GC (GCData data) {
 	if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
 	int /*long*/ root = OS.GDK_ROOT_PARENT ();
-	int /*long*/ gdkGC = OS.gdk_gc_new (root);
-	if (gdkGC == 0) SWT.error (SWT.ERROR_NO_HANDLES);
-	OS.gdk_gc_set_subwindow (gdkGC, OS.GDK_INCLUDE_INFERIORS);
+	int /*long*/ gc;
+	if (OS.USE_CAIRO) {
+		gc = OS.gdk_cairo_create (root);
+		if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+		//TODO how gdk_gc_set_subwindow is done in cairo?
+	} else {
+		gc = OS.gdk_gc_new (root);
+		if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
+		OS.gdk_gc_set_subwindow (gc, OS.GDK_INCLUDE_INFERIORS);
+	}
 	if (data != null) {
 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
 		if ((data.style & mask) == 0) {
@@ -2745,7 +2694,7 @@
 		data.foreground = getSystemColor (SWT.COLOR_BLACK).handle;
 		data.font = getSystemFont ();
 	}
-	return gdkGC;
+	return gc;
 }
 
 boolean isValidThread () {
@@ -3316,8 +3265,6 @@
 	idleHandle = 0;
 	
 	/* Dispose GtkTreeView callbacks */
-	treeSelectionCallback.dispose (); treeSelectionCallback = null;
-	treeSelectionProc = 0;
 	cellDataCallback.dispose (); cellDataCallback = null;
 	cellDataProc = 0;
 	
@@ -3432,7 +3379,7 @@
 	thread = null;
 	lastWidget = activeShell = null;
 	flushData = closures = null;
-	indexTable = signalIds = treeSelection = null;
+	indexTable = signalIds = null;
 	widgetTable = modalShells = null;
 	data = null;
 	values = keys = null;
@@ -4184,12 +4131,6 @@
 	return widget.sizeRequestProc (handle, arg0, user_data);
 }
 
-int /*long*/ treeSelectionProc (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int /*long*/ data) {
-	Widget widget = getWidget (data);
-	if (widget == null) return 0;
-	return widget.treeSelectionProc (model, path, iter, treeSelection, treeSelectionLength++);
-}
-
 void saveResources () {
 	int resourceCount = 0;
 	if (resources == null) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandBar.java
index 44c5ffc..2de6346 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandBar.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandBar.java
@@ -114,85 +114,34 @@
 }
 
 public Point computeSize (int wHint, int hHint, boolean changed) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
-		if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
-		Point size = computeNativeSize (handle, wHint, hHint, changed);
-		int border = OS.gtk_container_get_border_width (handle);
-		size.x += 2 * border;
-		size.y += 2 * border;
-		return size;
-	} else {
-		int height = 0, width = 0;
-		if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
-			if (itemCount > 0) {
-				height += spacing;
-				GC gc = new GC (this);
-				for (int i = 0; i < itemCount; i++) {
-					ExpandItem item = items [i];
-					height += item.getHeaderHeight ();
-					if (item.expanded) height += item.height;
-					height += spacing;
-					width = Math.max (width, item.getPreferredWidth (gc));
-				}
-				gc.dispose ();
-			}
-		}
-		if (width == 0) width = DEFAULT_WIDTH;
-		if (height == 0) height = DEFAULT_HEIGHT;
-		if (wHint != SWT.DEFAULT) width = wHint;
-		if (hHint != SWT.DEFAULT) height = hHint;
-		return new Point (width, height);	
-	} 
+	if (wHint != SWT.DEFAULT && wHint < 0) wHint = 0;
+	if (hHint != SWT.DEFAULT && hHint < 0) hHint = 0;
+	Point size = computeNativeSize (handle, wHint, hHint, changed);
+	int border = OS.gtk_container_get_border_width (handle);
+	size.x += 2 * border;
+	size.y += 2 * border;
+	return size;
 }
 
 void createHandle (int index) {
 	state |= HANDLE;
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		fixedHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
-		if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		OS.gtk_fixed_set_has_window (fixedHandle, true);
-		handle = OS.gtk_vbox_new (false, 0);
-		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
-		if ((style & SWT.V_SCROLL) != 0) {
-			scrolledHandle = OS.gtk_scrolled_window_new (0, 0);
-			if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
-			OS.gtk_scrolled_window_set_policy (scrolledHandle, OS.GTK_POLICY_NEVER, OS.GTK_POLICY_AUTOMATIC);
-			OS.gtk_container_add (fixedHandle, scrolledHandle);
-			OS.gtk_scrolled_window_add_with_viewport (scrolledHandle, handle);
-			int /*long*/ viewport = OS.gtk_bin_get_child (scrolledHandle);
-			OS.gtk_viewport_set_shadow_type (viewport, OS.GTK_SHADOW_NONE);
-		} else {
-			OS.gtk_container_add (fixedHandle, handle);
-		}
-		OS.gtk_container_set_border_width (handle, 0);
+	fixedHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
+	if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
+	OS.gtk_fixed_set_has_window (fixedHandle, true);
+	handle = OS.gtk_vbox_new (false, 0);
+	if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+	if ((style & SWT.V_SCROLL) != 0) {
+		scrolledHandle = OS.gtk_scrolled_window_new (0, 0);
+		if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
+		OS.gtk_scrolled_window_set_policy (scrolledHandle, OS.GTK_POLICY_NEVER, OS.GTK_POLICY_AUTOMATIC);
+		OS.gtk_container_add (fixedHandle, scrolledHandle);
+		OS.gtk_scrolled_window_add_with_viewport (scrolledHandle, handle);
+		int /*long*/ viewport = OS.gtk_bin_get_child (scrolledHandle);
+		OS.gtk_viewport_set_shadow_type (viewport, OS.GTK_SHADOW_NONE);
 	} else {
-		int /*long*/ topHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
-		if (topHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		OS.gtk_fixed_set_has_window (topHandle, true);
-		if ((style & SWT.V_SCROLL) != 0) {
-			fixedHandle = topHandle;
-			scrolledHandle = OS.gtk_scrolled_window_new (0, 0);
-			if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
-			handle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
-			if (handle == 0) error (SWT.ERROR_NO_HANDLES);
-			OS.gtk_fixed_set_has_window (handle, true);
-			OS.gtk_container_add (fixedHandle, scrolledHandle);
-				
-			/*
-			* Force the scrolledWindow to have a single child that is
-			* not scrolled automatically.  Calling gtk_container_add()
-			* seems to add the child correctly but cause a warning.
-			*/
-			boolean warnings = display.getWarnings ();
-			display.setWarnings (false);
-			OS.gtk_container_add (scrolledHandle, handle);
-			display.setWarnings (warnings);
-		} else {
-			handle = topHandle;
-		}
-		OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
+		OS.gtk_container_add (fixedHandle, handle);
 	}
+	OS.gtk_container_set_border_width (handle, 0);
 }
 
 void createItem (ExpandItem item, int style, int index) {
@@ -205,9 +154,6 @@
 	System.arraycopy (items, index, items, index + 1, itemCount - index);
 	items [index] = item;
 	itemCount++;
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (lastFocus == null) lastFocus = item;
-	}
 	item.width = Math.max (0, getClientArea ().width - spacing * 2);
 	layoutItems (index, true);
 }
@@ -224,17 +170,6 @@
 		index++;
 	}
 	if (index == itemCount) return;
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (item == lastFocus) {
-			int focusIndex = index > 0 ? index - 1 : 1;
-			if (focusIndex < itemCount) {
-				lastFocus = items [focusIndex];
-				lastFocus.redraw ();
-			} else {
-				lastFocus = null;
-			}
-		}
-	}
 	System.arraycopy (items, index + 1, items, index, --itemCount - index);
 	items [itemCount] = null;
 	item.redraw ();
@@ -242,36 +177,30 @@
 }
 
 int /*long*/ eventHandle () {
-	return OS.GTK_VERSION >= OS.VERSION (2, 4, 0) ? fixedHandle : handle;
+	return fixedHandle;
 }
 
 boolean forceFocus (int /*long*/ focusHandle) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (lastFocus != null && lastFocus.setFocus ()) return true;
-		for (int i = 0; i < itemCount; i++) {
-			ExpandItem item = items [i];
-			if (item.setFocus ()) return true;
-		}
+	if (lastFocus != null && lastFocus.setFocus ()) return true;
+	for (int i = 0; i < itemCount; i++) {
+		ExpandItem item = items [i];
+		if (item.setFocus ()) return true;
 	}
 	return super.forceFocus (focusHandle);
 }
 
 boolean hasFocus () {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		for (int i=0; i<itemCount; i++) {
-			ExpandItem item = items [i];
-			if (item.hasFocus ()) return true;
-		}
+	for (int i=0; i<itemCount; i++) {
+		ExpandItem item = items [i];
+		if (item.hasFocus ()) return true;
 	}
 	return super.hasFocus();
 }
 
 void hookEvents () {
 	super.hookEvents ();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (scrolledHandle != 0) {
-			OS.g_signal_connect_closure (scrolledHandle, OS.size_allocate, display.closures [SIZE_ALLOCATE], true);
-		}
+	if (scrolledHandle != 0) {
+		OS.g_signal_connect_closure (scrolledHandle, OS.size_allocate, display.closures [SIZE_ALLOCATE], true);
 	}
 }
 
@@ -283,15 +212,6 @@
 	return Math.max (ExpandItem.CHEVRON_SIZE, metrics.getHeight ());
 }
 
-GdkColor getForegroundColor () {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if ((state & FOREGROUND) == 0) {
-			return display.getSystemColor (SWT.COLOR_TITLE_FOREGROUND).handle;
-		}
-	}
-	return super.getForegroundColor ();
-}
-
 /**
  * Returns the item at the given, zero-relative index in the
  * receiver. Throws an exception if the index is out of range.
@@ -366,143 +286,31 @@
 	return spacing;
 }
 
-int /*long*/ gtk_button_press_event (int /*long*/ widget, int /*long*/ event) {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		GdkEventButton gdkEvent = new GdkEventButton ();
-		OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
-		int x = (int)gdkEvent.x;
-		int y = (int)gdkEvent.y;
-		for (int i = 0; i < itemCount; i++) {
-			ExpandItem item = items[i];
-			boolean hover = item.x <= x && x < (item.x + item.width) && item.y <= y && y < (item.y + getBandHeight ());
-			if (hover && item != lastFocus) {
-				lastFocus.redraw ();
-				lastFocus = item;
-				lastFocus.redraw ();
-				forceFocus ();
-				break;
-			}
-		}
-	}
-	return super.gtk_button_press_event (widget, event);
-}
-
-int /*long*/ gtk_button_release_event (int /*long*/ widget, int /*long*/ event) {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (lastFocus != null) {
-			GdkEventButton gdkEvent = new GdkEventButton ();
-			OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
-			int x = (int)gdkEvent.x;
-			int y = (int)gdkEvent.y;
-			boolean hover = lastFocus.x <= x && x < (lastFocus.x + lastFocus.width) && lastFocus.y <= y && y < (lastFocus.y + getBandHeight ()); 
-			if (hover) {
-				Event ev = new Event ();
-				ev.item = lastFocus;
-				notifyListeners (lastFocus.expanded ? SWT.Collapse : SWT.Expand, ev);
-				lastFocus.expanded = !lastFocus.expanded;
-				showItem (lastFocus);
-			}
-		}
-	}
-	return super.gtk_button_release_event (widget, event);
-}
-
-int /*long*/ gtk_expose_event (int /*long*/ widget, int /*long*/ eventPtr) {
-	if ((state & OBSCURED) != 0) return 0;
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		GdkEventExpose gdkEvent = new GdkEventExpose ();
-		OS.memmove(gdkEvent, eventPtr, GdkEventExpose.sizeof);
-		GCData data = new GCData ();
-		data.damageRgn = gdkEvent.region;
-		GC gc = GC.gtk_new (this, data);
-		OS.gdk_gc_set_clip_region (gc.handle, gdkEvent.region);
-		boolean hasFocus = isFocusControl ();
-		for (int i = 0; i < itemCount; i++) {
-			ExpandItem item = items [i];
-			item.drawItem (gc, hasFocus && item == lastFocus);
-		}
-		gc.dispose ();
-	}
-	return super.gtk_expose_event (widget, eventPtr);
-}
-
-int /*long*/ gtk_focus_in_event (int /*long*/ widget, int /*long*/ event) {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (lastFocus != null) lastFocus.redraw ();
-	}
-	return super.gtk_focus_in_event(widget, event);
-}
-
-int /*long*/ gtk_focus_out_event (int /*long*/ widget, int /*long*/ event) {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (lastFocus != null) lastFocus.redraw ();
-	}
-	return super.gtk_focus_out_event (widget, event);
-}
-
 int /*long*/ gtk_key_press_event (int /*long*/ widget, int /*long*/ event) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (!hasFocus ()) return 0;
-		int /*long*/ result = super.gtk_key_press_event (widget, event);
-		if (result != 0) return result;
-		int index = 0;
-		while (index < itemCount) {
-			if (items [index].hasFocus ()) break;
-			index++;
-		}
-		GdkEventKey gdkEvent = new GdkEventKey ();
-		OS.memmove (gdkEvent, event, GdkEventKey.sizeof);
-		boolean next = false;
-		switch (gdkEvent.keyval) {
-			case OS.GDK_Up:
-			case OS.GDK_Left: next = false; break;
-			case OS.GDK_Down: 
-			case OS.GDK_Right: next = true; break;
-			default: return result;
-		}
-		int start = index, offset = next ? 1 : -1;
-		while ((index = (index + offset + itemCount) % itemCount) != start) {
-			ExpandItem item = items [index];
-			if (item.setFocus ()) return result;
-		}
-		return result;
-	} else {
-		if (lastFocus != null) {
-			GdkEventKey keyEvent = new GdkEventKey ();
-			OS.memmove (keyEvent, event, GdkEventKey.sizeof);
-			switch (keyEvent.keyval) {
-				case OS.GDK_Return:
-				case OS.GDK_space:
-					Event ev = new Event ();
-					ev.item = lastFocus;
-					sendEvent (lastFocus.expanded ? SWT.Collapse :SWT.Expand, ev);
-					lastFocus.expanded = !lastFocus.expanded;
-					showItem (lastFocus);
-					break;
-				case OS.GDK_Up:
-				case OS.GDK_KP_Up: {
-					int focusIndex = indexOf (lastFocus);
-					if (focusIndex > 0) {
-						lastFocus.redraw ();
-						lastFocus = items [focusIndex - 1];
-						lastFocus.redraw ();
-					}
-					break;
-				}
-				case OS.GDK_Down:
-				case OS.GDK_KP_Down: {
-					int focusIndex = indexOf (lastFocus);
-					if (focusIndex < itemCount - 1) {
-						lastFocus.redraw ();
-						lastFocus = items [focusIndex + 1];
-						lastFocus.redraw ();
-					}
-					break;
-				}
-			}
-		}
+	if (!hasFocus ()) return 0;
+	int /*long*/ result = super.gtk_key_press_event (widget, event);
+	if (result != 0) return result;
+	int index = 0;
+	while (index < itemCount) {
+		if (items [index].hasFocus ()) break;
+		index++;
 	}
-	return super.gtk_key_press_event (widget, event);
+	GdkEventKey gdkEvent = new GdkEventKey ();
+	OS.memmove (gdkEvent, event, GdkEventKey.sizeof);
+	boolean next = false;
+	switch (gdkEvent.keyval) {
+		case OS.GDK_Up:
+		case OS.GDK_Left: next = false; break;
+		case OS.GDK_Down: 
+		case OS.GDK_Right: next = true; break;
+		default: return result;
+	}
+	int start = index, offset = next ? 1 : -1;
+	while ((index = (index + offset + itemCount) % itemCount) != start) {
+		ExpandItem item = items [index];
+		if (item.setFocus ()) return result;
+	}
+	return result;
 }
 
 /**
@@ -533,27 +341,9 @@
 }
 
 void layoutItems (int index, boolean setScrollbar) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		for (int i = 0; i < itemCount; i++) {
-			ExpandItem item = items [i];
-			if (item != null) item.resizeControl (yCurrentScroll);
-		}
-	} else {
-		if (index < itemCount) {
-			int y = spacing - yCurrentScroll;
-			for (int i = 0; i < index; i++) {
-				ExpandItem item = items [i];
-				if (item.expanded) y += item.height;
-				y += item.getHeaderHeight() + spacing;
-			}
-			for (int i = index; i < itemCount; i++) {
-				ExpandItem item = items [i];
-				item.setBounds (spacing, y, 0, 0, true, false);
-				if (item.expanded) y += item.height;
-				y += item.getHeaderHeight() + spacing;
-			}
-		}
-		if (setScrollbar) setScrollbar ();
+	for (int i = 0; i < itemCount; i++) {
+		ExpandItem item = items [i];
+		if (item != null) item.resizeControl (yCurrentScroll);
 	}
 }
 
@@ -564,7 +354,7 @@
 }
 
 int /*long*/ parentingHandle () {
-	return OS.GTK_VERSION >= OS.VERSION (2, 4, 0) ? fixedHandle : handle;
+	return fixedHandle;
 }
 
 void releaseChildren (boolean destroy) {
@@ -612,42 +402,18 @@
 	super.reskinChildren (flags);
 }
 
-int setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
-	int result = super.setBounds (x, y, width, height, move, resize);
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		if (resize) {
-			if ((style & SWT.V_SCROLL) != 0) {
-				setScrollbar ();
-			} else {
-				for (int i = 0; i < itemCount; i++) {
-					ExpandItem item = items [i];
-					int newWidth = Math.max (0, getClientArea ().width - spacing * 2);
-					if (item.width != newWidth) {
-						item.setBounds (0, 0, newWidth, item.height, false, true);
-					}
-				}
-			}
-		}
-	}
-	return result;
-}
-
 void setFontDescription (int /*long*/ font) {
 	super.setFontDescription (font);
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		for (int i = 0; i < itemCount; i++) {
-			items[i].setFontDescription (font);
-		}
-		layoutItems (0, true);
+	for (int i = 0; i < itemCount; i++) {
+		items[i].setFontDescription (font);
 	}
+	layoutItems (0, true);
 }
 
 void setForegroundColor (GdkColor color) {
 	super.setForegroundColor (color);
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		for (int i = 0; i < itemCount; i++) {
-			items[i].setForegroundColor (color);
-		}
+	for (int i = 0; i < itemCount; i++) {
+		items[i].setForegroundColor (color);
 	}
 }
 
@@ -715,20 +481,8 @@
 	if (spacing < 0) return;
 	if (spacing == this.spacing) return;
 	this.spacing = spacing;
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		OS.gtk_box_set_spacing (handle, spacing);
-		OS.gtk_container_set_border_width (handle, spacing);
-	} else {
-		if ((style & SWT.V_SCROLL) == 0) {
-			int width = Math.max (0, getClientArea ().width - spacing * 2);
-			for (int i = 0; i < itemCount; i++) {
-				ExpandItem item = items [i];
-				if (item.width != width) item.setBounds (0, 0, width, item.height, false, true);
-			}
-		}
-		layoutItems (0, true);
-		redraw ();
-	}
+	OS.gtk_box_set_spacing (handle, spacing);
+	OS.gtk_container_set_border_width (handle, spacing);
 }
 
 void showItem (ExpandItem item) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
index 4ac69e4..f1c27e4 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ExpandItem.java
@@ -121,24 +121,22 @@
 }
 
 void createHandle (int index) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		state |= HANDLE;
-		handle = OS.gtk_expander_new (null);
-		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
-		clientHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
-		if (clientHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		OS.gtk_container_add (handle, clientHandle);	
-		boxHandle = OS.gtk_hbox_new (false, 4);
-		if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		labelHandle = OS.gtk_label_new (null);
-		if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		imageHandle = OS.gtk_image_new ();
-		if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
-		OS.gtk_container_add (boxHandle, imageHandle);
-		OS.gtk_container_add (boxHandle, labelHandle);
-		OS.gtk_expander_set_label_widget (handle, boxHandle);
-		OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
-	}
+	state |= HANDLE;
+	handle = OS.gtk_expander_new (null);
+	if (handle == 0) error (SWT.ERROR_NO_HANDLES);
+	clientHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
+	if (clientHandle == 0) error (SWT.ERROR_NO_HANDLES);
+	OS.gtk_container_add (handle, clientHandle);	
+	boxHandle = OS.gtk_hbox_new (false, 4);
+	if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
+	labelHandle = OS.gtk_label_new (null);
+	if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
+	imageHandle = OS.gtk_image_new ();
+	if (imageHandle == 0) error (SWT.ERROR_NO_HANDLES);
+	OS.gtk_container_add (boxHandle, imageHandle);
+	OS.gtk_container_add (boxHandle, labelHandle);
+	OS.gtk_expander_set_label_widget (handle, boxHandle);
+	OS.GTK_WIDGET_SET_FLAGS (handle, OS.GTK_CAN_FOCUS);
 }
 
 void createWidget (int index) {
@@ -149,12 +147,10 @@
 
 void deregister() {
 	super.deregister();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		display.removeWidget (clientHandle);
-		display.removeWidget (boxHandle);
-		display.removeWidget (labelHandle);
-		display.removeWidget (imageHandle);
-	}
+	display.removeWidget (clientHandle);
+	display.removeWidget (boxHandle);
+	display.removeWidget (labelHandle);
+	display.removeWidget (imageHandle);
 }
 
 void destroyWidget () {
@@ -269,10 +265,7 @@
  */
 public int getHeaderHeight () {
 	checkWidget ();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		return OS.GTK_WIDGET_HEIGHT (handle) - (expanded ? height : 0);
-	}
-	return Math.max (parent.getBandHeight (), imageHeight);
+	return OS.GTK_WIDGET_HEIGHT (handle) - (expanded ? height : 0);
 }
 
 /**
@@ -351,34 +344,23 @@
 
 void hookEvents () {
 	super.hookEvents ();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		OS.g_signal_connect_closure (handle, OS.activate, display.closures [ACTIVATE], false);
-		OS.g_signal_connect_closure (handle, OS.activate, display.closures [ACTIVATE_INVERSE], true);
-		OS.g_signal_connect_closure_by_id (handle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false);
-		OS.g_signal_connect_closure_by_id (handle, display.signalIds [FOCUS_OUT_EVENT], 0, display.closures [FOCUS_OUT_EVENT], false);
-		OS.g_signal_connect_closure (clientHandle, OS.size_allocate, display.closures [SIZE_ALLOCATE], true);
-		OS.g_signal_connect_closure_by_id (handle, display.signalIds [ENTER_NOTIFY_EVENT], 0, display.closures [ENTER_NOTIFY_EVENT], false);
-	}
+	OS.g_signal_connect_closure (handle, OS.activate, display.closures [ACTIVATE], false);
+	OS.g_signal_connect_closure (handle, OS.activate, display.closures [ACTIVATE_INVERSE], true);
+	OS.g_signal_connect_closure_by_id (handle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false);
+	OS.g_signal_connect_closure_by_id (handle, display.signalIds [FOCUS_OUT_EVENT], 0, display.closures [FOCUS_OUT_EVENT], false);
+	OS.g_signal_connect_closure (clientHandle, OS.size_allocate, display.closures [SIZE_ALLOCATE], true);
+	OS.g_signal_connect_closure_by_id (handle, display.signalIds [ENTER_NOTIFY_EVENT], 0, display.closures [ENTER_NOTIFY_EVENT], false);
 }
 
 void redraw () {
-	if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-		int headerHeight = parent.getBandHeight ();
-		if (imageHeight > headerHeight) {
-			parent.redraw (x + ExpandItem.TEXT_INSET, y + headerHeight - imageHeight, imageWidth, imageHeight, false);
-		}
-		parent.redraw (x, y, width, headerHeight + height, false);
-	}
 }
 
 void register () {
 	super.register ();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		display.addWidget (clientHandle, this);
-		display.addWidget (boxHandle, this);
-		display.addWidget (labelHandle, this);
-		display.addWidget (imageHandle, this);
-	}
+	display.addWidget (clientHandle, this);
+	display.addWidget (boxHandle, this);
+	display.addWidget (labelHandle, this);
+	display.addWidget (imageHandle, this);
 }
 
 void releaseHandle () {
@@ -390,9 +372,7 @@
 void releaseWidget () {
 	super.releaseWidget ();
 	if (imageList != null) imageList.dispose ();
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (parent.lastFocus == this) parent.lastFocus = null;
-	}
+	if (parent.lastFocus == this) parent.lastFocus = null;
 	imageList = null;
 	control = null;
 }
@@ -478,14 +458,8 @@
 	this.control = control;
 	if (control != null) {
 		control.setVisible (expanded);
-		if (OS.GTK_VERSION < OS.VERSION (2, 4, 0)) {
-			int headerHeight = parent.getBandHeight ();
-			control.setBounds (x + BORDER, y + headerHeight, Math.max (0, width - 2 * BORDER), Math.max (0, height - BORDER));
-		}
 	}
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		parent.layoutItems (0, true);
-	}
+	parent.layoutItems (0, true);
 }
 
 /**
@@ -501,12 +475,8 @@
 public void setExpanded (boolean expanded) {
 	checkWidget ();
 	this.expanded = expanded;
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		OS.gtk_expander_set_expanded (handle, expanded);
-		parent.layoutItems (0, true);
-	} else {
-		parent.showItem (this);
-	}
+	OS.gtk_expander_set_expanded (handle, expanded);
+	parent.layoutItems (0, true);
 }
 
 boolean setFocus () {
@@ -546,48 +516,27 @@
 public void setHeight (int height) {
 	checkWidget ();
 	if (height < 0) return;
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		this.height = height;
-		OS.gtk_widget_set_size_request (clientHandle, -1, height);
-		parent.layoutItems (0, false);
-	} else {
-		setBounds (0, 0, width, height, false, true);
-		if (expanded) parent.layoutItems (parent.indexOf (this) + 1, true);
-	}
+	this.height = height;
+	OS.gtk_widget_set_size_request (clientHandle, -1, height);
+	parent.layoutItems (0, false);
 }
 
 public void setImage (Image image) {
 	super.setImage (image);
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		if (imageList != null) imageList.dispose ();
-		imageList = null;
-		if (image != null) {
-			if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
-			imageList = new ImageList ();
-			int imageIndex = imageList.add (image);
-			int /*long*/ pixbuf = imageList.getPixbuf (imageIndex);
-			OS.gtk_image_set_from_pixbuf (imageHandle, pixbuf);
-			if (text.length () == 0) OS.gtk_widget_hide (labelHandle);
-			OS.gtk_widget_show (imageHandle);
-		} else {
-			OS.gtk_image_set_from_pixbuf (imageHandle, 0);
-			OS.gtk_widget_show (labelHandle);
-			OS.gtk_widget_hide (imageHandle);
-		}
+	if (imageList != null) imageList.dispose ();
+	imageList = null;
+	if (image != null) {
+		if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+		imageList = new ImageList ();
+		int imageIndex = imageList.add (image);
+		int /*long*/ pixbuf = imageList.getPixbuf (imageIndex);
+		OS.gtk_image_set_from_pixbuf (imageHandle, pixbuf);
+		if (text.length () == 0) OS.gtk_widget_hide (labelHandle);
+		OS.gtk_widget_show (imageHandle);
 	} else {
-		int oldImageHeight = imageHeight;
-		if (image != null) {
-			Rectangle bounds = image.getBounds ();
-			imageHeight = bounds.height;
-			imageWidth = bounds.width;
-		} else {
-			imageHeight = imageWidth = 0;
-		}
-		if (oldImageHeight != imageHeight) {
-			parent.layoutItems (parent.indexOf (this), true);
-		} else {
-			redraw ();
-		}
+		OS.gtk_image_set_from_pixbuf (imageHandle, 0);
+		OS.gtk_widget_show (labelHandle);
+		OS.gtk_widget_hide (imageHandle);
 	}
 }
 
@@ -602,23 +551,17 @@
 	
 public void setText (String string) {
 	super.setText (string);
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		byte [] buffer = Converter.wcsToMbcs (null, string, true);
-		OS.gtk_label_set_text (labelHandle, buffer);
-	} else {
-		redraw ();
-	}
+	byte [] buffer = Converter.wcsToMbcs (null, string, true);
+	OS.gtk_label_set_text (labelHandle, buffer);
 }
 
 void showWidget (int index) {
-	if (OS.GTK_VERSION >= OS.VERSION (2, 4, 0)) {
-		OS.gtk_widget_show (handle);
-		OS.gtk_widget_show (clientHandle);
-		OS.gtk_container_add (parent.handle, handle);
-		OS.gtk_box_set_child_packing (parent.handle, handle, false, false, 0, OS.GTK_PACK_START);
-		if (boxHandle != 0) OS.gtk_widget_show (boxHandle);
-		if (labelHandle != 0) OS.gtk_widget_show (labelHandle);
-	}
+	OS.gtk_widget_show (handle);
+	OS.gtk_widget_show (clientHandle);
+	OS.gtk_container_add (parent.handle, handle);
+	OS.gtk_box_set_child_packing (parent.handle, handle, false, false, 0, OS.GTK_PACK_START);
+	if (boxHandle != 0) OS.gtk_widget_show (boxHandle);
+	if (labelHandle != 0) OS.gtk_widget_show (labelHandle);
 }
 
 int /*long*/ windowProc (int /*long*/ handle, int /*long*/ user_data) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java
deleted file mode 100644
index cab405e..0000000
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.swt.widgets;
-
-
-import org.eclipse.swt.internal.gtk.*;
-import org.eclipse.swt.graphics.*;
-
-class ImageList {
-	int /*long*/ [] pixbufs;
-	int width = -1, height = -1;
-	Image [] images;
-	
-public ImageList() {
-	images = new Image [4];
-	pixbufs = new int /*long*/ [4];
-}
-
-public int add (Image image) {
-	int index = 0;
-	while (index < images.length) {
-		if (images [index] != null) {
-			if (images [index].isDisposed ()) {
-				OS.g_object_unref (pixbufs [index]);
-				images [index] = null;
-				pixbufs [index] = 0;
-			}
-		}
-		if (images [index] == null) break;
-		index++;
-	}
-	if (index == images.length) {
-		Image [] newImages = new Image [images.length + 4];
-		System.arraycopy (images, 0, newImages, 0, images.length);
-		images = newImages;
-		int /*long*/ [] newPixbufs = new int /*long*/ [pixbufs.length + 4];
-		System.arraycopy (pixbufs, 0, newPixbufs, 0, pixbufs.length);
-		pixbufs = newPixbufs;
-	}
-	set (index, image);
-	return index;
-}
-
-public void dispose () {
-	if (pixbufs == null) return;
-	for (int index=0; index<pixbufs.length; index++) {
-		if (pixbufs [index] != 0) OS.g_object_unref (pixbufs [index]);
-	}
-	images = null;
-	pixbufs = null;
-}
-
-public Image get (int index) {
-	return images [index];
-}
-
-int /*long*/ getPixbuf (int index) {
-	return pixbufs [index];
-}
-
-public int indexOf (Image image) {
-	if (image == null) return -1;
-	for (int index=0; index<images.length; index++) {
-		if (image == images [index]) return index;
-	}
-	return -1;
-}
-
-int indexOf (int /*long*/ pixbuf) {
-	if (pixbuf == 0) return -1;
-	for (int index=0; index<images.length; index++) {
-		if (pixbuf == pixbufs [index]) return index;
-	}
-	return -1;
-}
-
-public boolean isDisposed () {
-	return images == null;
-}
-
-public void put (int index, Image image) {
-	int count = images.length;
-	if (!(0 <= index && index < count)) return;
-	if (image != null) {
-		set (index, image);
-	} else {
-		images [index] = null;	
-		if (pixbufs [index] != 0) OS.g_object_unref (pixbufs [index]);
-		pixbufs [index] = 0;
-	}
-}
-
-public void remove (Image image) {
-	if (image == null) return;
-	for (int index=0; index<images.length; index++) {
-		if (image == images [index]){
-			OS.g_object_unref (pixbufs [index]);
-			images [index] = null;
-			pixbufs [index] = 0;
-		}
-	}
-}
-
-void set (int index, Image image) {
-	int [] w = new int [1], h = new int [1];
- 	OS.gdk_drawable_get_size (image.pixmap, w, h);
-	int /*long*/ pixbuf = Display.createPixbuf (image);
-	if (width == -1 || height == -1) {
-		width = w [0];
-		height = h [0];
-	}
-	if (w [0] != width || h [0] != height) {
-		int /*long*/ scaledPixbuf = OS.gdk_pixbuf_scale_simple(pixbuf, width, height, OS.GDK_INTERP_BILINEAR);
-		OS.g_object_unref (pixbuf);
-		pixbuf = scaledPixbuf;
-	}
-	int /*long*/ oldPixbuf = pixbufs [index];
-	if (oldPixbuf != 0) {
-		if (images [index] == image) {
-			OS.gdk_pixbuf_copy_area (pixbuf, 0, 0, width, height, oldPixbuf, 0, 0);
-			OS.g_object_unref (pixbuf);
-			pixbuf = oldPixbuf;
-		} else {
-			OS.g_object_unref (oldPixbuf);
-		}
-	}
-	pixbufs [index] = pixbuf;
-	images [index] = image;	
-}
-
-public int size () {
-	int result = 0;
-	for (int index=0; index<images.length; index++) {
-		if (images [index] != null) {
-			if (images [index].isDisposed ()) {
-				OS.g_object_unref (pixbufs [index]);
-				images [index] = null;
-				pixbufs [index] = 0;
-			}
-			if (images [index] != null) result++;
-		}
-	}
-	return result;
-}
-
-}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
index e9321cc..8810331 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Link.java
@@ -363,7 +363,6 @@
 	GCData data = new GCData ();
 	data.damageRgn = gdkEvent.region;
 	GC gc = GC.gtk_new (this, data);
-	OS.gdk_gc_set_clip_region (gc.handle, gdkEvent.region);
 	int selStart = selection.x;
 	int selEnd = selection.y;
 	if (selStart > selEnd) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/List.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/List.java
index 5edfc18..5ea80a8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/List.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/List.java
@@ -577,12 +577,6 @@
 public int getSelectionCount () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength = 0;
-		display.treeSelection = null;
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		return display.treeSelectionLength;
-	}
 	return OS.gtk_tree_selection_count_selected_rows (selection);
 }
 
@@ -600,21 +594,7 @@
 public int getSelectionIndex () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		int itemCount = OS.gtk_tree_model_iter_n_children (modelHandle, 0);
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [itemCount];
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		if (display.treeSelectionLength == 0) return -1;
-		return display.treeSelection [0];
-	}
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		int [] index = new int [1];
@@ -656,23 +636,7 @@
 public int [] getSelectionIndices () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		int itemCount = OS.gtk_tree_model_iter_n_children (modelHandle, 0);
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [itemCount];
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		if (display.treeSelectionLength == display.treeSelection.length) return display.treeSelection;
-		int [] result = new int [display.treeSelectionLength];
-		System.arraycopy (display.treeSelection, 0, result, 0, display.treeSelectionLength);
-		return result;
-	}
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		int [] treeSelection = new int [count];
@@ -801,29 +765,6 @@
 	return result;
 }
 
-int /*long*/ gtk_key_press_event (int /*long*/ widget, int /*long*/ event) {
-	int /*long*/ result = super.gtk_key_press_event (widget, event);
-	if (result != 0) return result;
-	if (OS.GTK_VERSION < OS.VERSION (2, 2 ,0)) {
-		/*
-		* Feature in GTK 2.0.x.  When an item is default selected using
-		* the return key, GTK does not issue notification. The fix is
-		* to issue this notification when the return key is pressed.
-		*/
-		GdkEventKey keyEvent = new GdkEventKey ();
-		OS.memmove (keyEvent, event, GdkEventKey.sizeof);
-		int key = keyEvent.keyval;
-		switch (key) {
-			case OS.GDK_Return:
-			case OS.GDK_KP_Enter: {
-				sendSelectionEvent (SWT.DefaultSelection);
-				break;
-			}
-		}
-	}
-	return result;
-}
-
 int /*long*/ gtk_popup_menu (int /*long*/ widget) {
 	int /*long*/ result = super.gtk_popup_menu (widget);
 	/*
@@ -1609,16 +1550,4 @@
 	OS.g_free (iter);
 }
 
-int /*long*/ treeSelectionProc (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int[] selection, int length) {
-	if (selection != null) { 
-		int /*long*/ indices = OS.gtk_tree_path_get_indices (path);
-		if (indices != 0) {
-			int [] index = new int [1];
-			OS.memmove (index, indices, 4);
-			selection [length] = index [0];
-		}
-	}
-	return 0;
-}
-
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Sash.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Sash.java
index 3b2fe88..f6cd115 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Sash.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Sash.java
@@ -144,6 +144,7 @@
 
 void drawBand (int x, int y, int width, int height) {
 	if ((style & SWT.SMOOTH) != 0) return;
+	//TODO: Use Cairo
 	int /*long*/ window = OS.GTK_WIDGET_WINDOW (parent.paintHandle());
 	if (window == 0) return;
 	byte [] bits = {-86, 85, -86, 85, -86, 85, -86, 85};
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 af3cc3e..1ace883 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
@@ -725,7 +725,9 @@
 					case OS.NotifyNonlinear:
 					case OS.NotifyNonlinearVirtual:
 					case OS.NotifyAncestor:
-						if (tooltipsHandle != 0) OS.gtk_tooltips_enable (tooltipsHandle);
+						if (tooltipsHandle != 0 && OS.GTK_VERSION < OS.VERSION (2, 12, 0)) {
+						    OS.gtk_tooltips_enable (tooltipsHandle);
+						}
 						display.activeShell = this;
 						display.activePending = false;
 						sendEvent (SWT.Activate);
@@ -743,7 +745,9 @@
 					case OS.NotifyNonlinear:
 					case OS.NotifyNonlinearVirtual:
 					case OS.NotifyVirtual:
-						if (tooltipsHandle != 0) OS.gtk_tooltips_disable (tooltipsHandle);
+						if (tooltipsHandle != 0 && OS.GTK_VERSION < OS.VERSION (2, 12, 0)) {
+							OS.gtk_tooltips_disable (tooltipsHandle);
+						}
 						Display display = this.display;
 						sendEvent (SWT.Deactivate);
 						setActiveControl (null);
@@ -2470,6 +2474,8 @@
 		* Bug in Solaris-GTK.  Invoking gtk_tooltips_force_window()
 		* can cause a crash in older versions of GTK.  The fix is
 		* to avoid this call if the GTK version is older than 2.2.x.
+		* The call is to be avoided on GTK versions newer than 2.12.0
+		* where it's deprecated.
 		*/
 		if (OS.GTK_VERSION >= OS.VERSION (2, 2, 1)) {
 			OS.gtk_tooltips_force_window (tooltipsHandle);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
index e09761c..7302454 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabFolder.java
@@ -12,6 +12,7 @@
 
 
 import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
 import org.eclipse.swt.internal.gtk.*;
 import org.eclipse.swt.graphics.*;
 import org.eclipse.swt.events.*;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
index 6ce0782..222d6e6 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java
@@ -195,29 +195,6 @@
 	if (modelIndex == -1) return 0;
 	boolean setData = false;
 	if ((style & SWT.VIRTUAL) != 0) {
-		/*
-		* Feature in GTK.  On GTK before 2.4, fixed_height_mode is not
-		* supported, and the tree asks for the data of all items.  The
-		* fix is to only provide the data if the row is visible.
-		*/
-		if (OS.GTK_VERSION < OS.VERSION (2, 3, 2)) {
-			OS.gtk_widget_realize (handle);
-			GdkRectangle visible = new GdkRectangle ();
-			OS.gtk_tree_view_get_visible_rect (handle, visible);
-			GdkRectangle area = new GdkRectangle ();
-			path = OS.gtk_tree_model_get_path (tree_model, iter);
-			OS.gtk_tree_view_get_cell_area (handle, path, tree_column, area);
-			OS.gtk_tree_path_free (path);
-			if (area.y + area.height < 0 || area.y + visible.y > visible.y + visible.height) {
-				/* Give an image from the image list to make sure the row has
-				* the correct height.
-				*/
-				if (imageList != null && imageList.pixbufs.length > 0) {
-					if (isPixbuf) OS.g_object_set (cell, OS.pixbuf, imageList.pixbufs [0], 0);
-				}
-				return 0;
-			}
-		}
 		if (!item.cached) {
 			lastIndexOf = index[0];
 			setData = checkData (item);
@@ -229,7 +206,7 @@
 		if (isPixbuf) {
 			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1);
 			OS.g_object_set (cell, OS.pixbuf, ptr [0], 0);
-			OS.g_object_unref (ptr [0]);
+			if (ptr [0] != 0) OS.g_object_unref (ptr [0]);
 		} else {
 			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_TEXT, ptr, -1); 
 			if (ptr [0] != 0) {
@@ -239,18 +216,12 @@
 		}
 	}
 	if (customDraw) {
-		/*
-		* Bug on GTK. Gtk renders the background on top of the checkbox and pixbuf.
-		* This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-		*/
-		if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-			if (!ownerDraw) {
-				ptr [0] = 0;
-				OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_BACKGROUND, ptr, -1);
-				if (ptr [0] != 0) {
-					OS.g_object_set (cell, OS.cell_background_gdk, ptr [0], 0);
-					OS.gdk_color_free (ptr [0]);
-				}
+		if (!ownerDraw) {
+			ptr [0] = 0;
+			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_BACKGROUND, ptr, -1);
+			if (ptr [0] != 0) {
+				OS.g_object_set (cell, OS.cell_background_gdk, ptr [0], 0);
+				OS.gdk_color_free (ptr [0]);
 			}
 		}
 		if (!isPixbuf) {
@@ -579,12 +550,7 @@
 		createRenderers (checkColumn.handle, checkColumn.modelIndex, false, checkColumn.style);
 	}
 	createRenderers (columnHandle, modelIndex, index == 0, column == null ? 0 : column.style);
-	/*
-	* Use GTK_TREE_VIEW_COLUMN_GROW_ONLY on GTK versions < 2.3.2
-	* because fixed_height_mode is not supported.
-	*/
-	boolean useVirtual = (style & SWT.VIRTUAL) != 0 && OS.GTK_VERSION >= OS.VERSION (2, 3, 2);
-	if (!useVirtual && columnCount == 0) {
+	if ((style & SWT.VIRTUAL) == 0 && columnCount == 0) {
 		OS.gtk_tree_view_column_set_sizing (columnHandle, OS.GTK_TREE_VIEW_COLUMN_GROW_ONLY);
 	} else {
 		OS.gtk_tree_view_column_set_sizing (columnHandle, OS.GTK_TREE_VIEW_COLUMN_FIXED);
@@ -651,10 +617,7 @@
 	OS.gtk_scrolled_window_set_policy (scrolledHandle, hsp, vsp);
 	if ((style & SWT.BORDER) != 0) OS.gtk_scrolled_window_set_shadow_type (scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
 	if ((style & SWT.VIRTUAL) != 0) {
-		/* The fixed_height_mode property only exists in GTK 2.3.2 and greater */
-		if (OS.GTK_VERSION >= OS.VERSION (2, 3, 2)) {
-			OS.g_object_set (handle, OS.fixed_height_mode, true, 0);
-		}
+		OS.g_object_set (handle, OS.fixed_height_mode, true, 0);
 	}
 	if (!searchEnabled ()) {
 		/*
@@ -772,19 +735,8 @@
 	if ((style & SWT.CHECK) != 0 && check) {
 		OS.gtk_tree_view_column_pack_start (columnHandle, checkRenderer, false);
 		OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.active, CHECKED_COLUMN);
-		/*
-		* Feature in GTK. The inconsistent property only exists in GTK 2.2.x.
-		*/
-		if (OS.GTK_VERSION >= OS.VERSION (2, 2, 0)) {
-			OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.inconsistent, GRAYED_COLUMN);
-		}
-		/*
-		* Bug in GTK. GTK renders the background on top of the checkbox.
-		* This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-		*/
-		if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-			if (!ownerDraw) OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-		}
+		OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.inconsistent, GRAYED_COLUMN);
+		if (!ownerDraw) OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
 		if (ownerDraw) {
 			OS.gtk_tree_view_column_set_cell_data_func (columnHandle, checkRenderer, display.cellDataProc, handle, 0);
 			OS.g_object_set_qdata (checkRenderer, Display.SWT_OBJECT_INDEX1, columnHandle);
@@ -829,15 +781,9 @@
 
 	/* Add attributes */
 	OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF);
-	/*
-	 * Bug on GTK. Gtk renders the background on top of the pixbuf.
-	 * This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-	 */
-	if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-		if (!ownerDraw) {
-			OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-			OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-		}
+	if (!ownerDraw) {
+		OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
+		OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
 	}
 	OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.text, modelIndex + CELL_TEXT);
 	OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.foreground_gdk, FOREGROUND_COLUMN);
@@ -1649,21 +1595,7 @@
 public TableItem [] getSelection () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [itemCount];
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		TableItem [] result = new TableItem [display.treeSelectionLength];
-		for (int i=0; i<result.length; i++) result [i] = _getItem (display.treeSelection [i]);
-		return result;
-	}
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		int [] treeSelection = new int [count];
@@ -1700,12 +1632,6 @@
 public int getSelectionCount () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength = 0;
-		display.treeSelection = null;
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		return display.treeSelectionLength;
-	}
 	return OS.gtk_tree_selection_count_selected_rows (selection);
 }
 
@@ -1722,22 +1648,8 @@
  */
 public int getSelectionIndex () {
 	checkWidget();
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [itemCount];
-		int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		if (display.treeSelectionLength == 0) return -1;
-		return display.treeSelection [0];
-	}
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		int [] index = new int [1];
@@ -1779,22 +1691,7 @@
 public int [] getSelectionIndices () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [itemCount];
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		if (display.treeSelectionLength == display.treeSelection.length) return display.treeSelection;
-		int [] result = new int [display.treeSelectionLength];
-		System.arraycopy (display.treeSelection, 0, result, 0, display.treeSelectionLength);
-		return result;
-	}
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		int [] treeSelection = new int [count];
@@ -2031,31 +1928,6 @@
 	return super.gtk_expose_event (widget, eventPtr);
 }
 
-int /*long*/ gtk_key_press_event (int /*long*/ widget, int /*long*/ eventPtr) {
-	int /*long*/ result = super.gtk_key_press_event (widget, eventPtr);
-	if (result != 0) return result;
-	if (OS.GTK_VERSION < OS.VERSION (2, 2 ,0)) {
-		/*
-		* Feature in GTK 2.0.x.  When an item is default selected using
-		* the return key, GTK does not issue notification. The fix is
-		* to issue this notification when the return key is pressed.
-		*/
-		GdkEventKey keyEvent = new GdkEventKey ();
-		OS.memmove (keyEvent, eventPtr, GdkEventKey.sizeof);
-		int key = keyEvent.keyval;
-		switch (key) {
-			case OS.GDK_Return:
-			case OS.GDK_KP_Enter: {
-				Event event = new Event ();
-				event.item = getFocusItem (); 
-				sendSelectionEvent (SWT.DefaultSelection, event, false);
-				break;
-			}
-		}
-	}
-	return result;
-}
-
 int /*long*/ gtk_popup_menu (int /*long*/ widget) {
 	int /*long*/ result = super.gtk_popup_menu (widget);
 	/*
@@ -3036,7 +2908,7 @@
 	OS.gtk_widget_modify_base (handle, 0, color);
 }
 
-void setBackgroundPixmap (int /*long*/ pixmap) {
+void setBackgroundPixmap (Image image) {
 	ownerDraw = true;
 	recreateRenderers ();
 }
@@ -3245,11 +3117,6 @@
 
 void setScrollWidth (int /*long*/ column, TableItem item) {
 	if (columnCount != 0 || currentItem == item) return;
-	/*
-	* Use GTK_TREE_VIEW_COLUMN_GROW_ONLY on GTK versions < 2.3.2
-	* because fixed_height_mode is not supported.
-	*/
-	if (((style & SWT.VIRTUAL) != 0) && OS.GTK_VERSION < OS.VERSION (2, 3, 2)) return;
 	int width = OS.gtk_tree_view_column_get_fixed_width (column);
 	int itemWidth = calculateWidth (column, item.handle);
 	if (width < itemWidth) {
@@ -3666,18 +3533,6 @@
 	showItem (item.handle);
 }
 
-int /*long*/ treeSelectionProc (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int[] selection, int length) {
-	if (selection != null) { 
-		int /*long*/ indices = OS.gtk_tree_path_get_indices (path);
-		if (indices != 0) {
-			int [] index = new int [1];
-			OS.memmove (index, indices, 4);
-			selection [(int)/*64*/length] = index [0];
-		}
-	}
-	return 0;
-}
-
 void updateScrollBarValue (ScrollBar bar) {
 	super.updateScrollBarValue (bar);
 	/*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Text.java
index 25c926a..a969c2b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Text.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Text.java
@@ -1398,6 +1398,7 @@
 				case SWT.CENTER: x = (width - rect.width) / 2; break;
 				case SWT.RIGHT: x = rtl ? innerBorder.left : width - rect.width; break;
 			}
+			//TODO: Use Cairo
 			int /*long*/ gc = OS.gdk_gc_new	(window);
 			int /*long*/ style = OS.gtk_widget_get_style (handle);	
 			GdkColor textColor = new GdkColor ();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolTip.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolTip.java
index 4d58088..bd0ac23 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolTip.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolTip.java
@@ -270,6 +270,8 @@
 		* Bug in Solaris-GTK.  Invoking gtk_tooltips_force_window()
 		* can cause a crash in older versions of GTK.  The fix is
 		* to avoid this call if the GTK version is older than 2.2.x.
+		* The call is to be avoided on GTK versions newer than 2.12.0
+		* where it's deprecated.
 		*/
 		if (OS.GTK_VERSION >= OS.VERSION (2, 2, 1)) { 
 			OS.gtk_tooltips_force_window (handle);
@@ -470,6 +472,7 @@
 int /*long*/ gtk_expose_event (int /*long*/ widget, int /*long*/ eventPtr) {
 	if ((state & OBSCURED) != 0) return 0;
 	int /*long*/ window = OS.GTK_WIDGET_WINDOW (handle);
+	//TODO: Use Cairo
 	int /*long*/ gdkGC = OS.gdk_gc_new (window);
 	OS.gdk_draw_polygon (window, gdkGC, 0, borderPolygon, borderPolygon.length / 2);
 	int x = BORDER + PADDING;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tracker.java
index 9bb9bc7..a67dc3e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tracker.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tracker.java
@@ -311,6 +311,7 @@
 		window = OS.GTK_WIDGET_WINDOW (parent.paintHandle());
 	} 
 	if (window == 0) return;
+	//TODO: Use Cairo
 	int /*long*/ gc = OS.gdk_gc_new (window);
 	if (gc == 0) return;
 	int /*long*/ colormap = OS.gdk_colormap_get_system ();
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
index c19f7cc..67210ef 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Tree.java
@@ -240,29 +240,6 @@
 	if (modelIndex == -1) return 0;
 	boolean setData = false;
 	if ((style & SWT.VIRTUAL) != 0) {
-		/*
-		* Feature in GTK.  On GTK before 2.4, fixed_height_mode is not
-		* supported, and the tree asks for the data of all items.  The
-		* fix is to only provide the data if the row is visible.
-		*/
-		if (OS.GTK_VERSION < OS.VERSION (2, 3, 2)) {
-			int /*long*/ path = OS.gtk_tree_model_get_path (tree_model, iter);
-			OS.gtk_widget_realize (handle);
-			GdkRectangle visible = new GdkRectangle ();
-			OS.gtk_tree_view_get_visible_rect (handle, visible);
-			GdkRectangle area = new GdkRectangle ();
-			OS.gtk_tree_view_get_cell_area (handle, path, tree_column, area);
-			OS.gtk_tree_path_free (path);			
-			if (area.y + area.height < 0 || area.y + visible.y > visible.y + visible.height ) {
-				/* Give an image from the image list to make sure the row has
-				* the correct height.
-				*/
-				if (imageList != null && imageList.pixbufs.length > 0) {
-					if (isPixbuf) OS.g_object_set (cell, OS.pixbuf, imageList.pixbufs [0], 0);
-				}
-				return 0;
-			}
-		}
 		if (!item.cached) {
 			//lastIndexOf = index [0];
 			setData = checkData (item);
@@ -274,7 +251,7 @@
 			ptr [0] = 0;
 			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_PIXBUF, ptr, -1);
 			OS.g_object_set (cell, OS.pixbuf, ptr[0], 0);
-			OS.g_object_unref (ptr [0]);
+			if (ptr [0] != 0) OS.g_object_unref (ptr [0]);
 		} else {
 			ptr [0] = 0;
 			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_TEXT, ptr, -1); 
@@ -285,18 +262,12 @@
 		}
 	}
 	if (customDraw) {
-		/*
-		 * Bug on GTK. Gtk renders the background on top of the checkbox and pixbuf.
-		 * This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-		 */
-		if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-			if (!ownerDraw) {
-				ptr [0] = 0;
-				OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_BACKGROUND, ptr, -1);
-				if (ptr [0] != 0) {
-					OS.g_object_set (cell, OS.cell_background_gdk, ptr[0], 0);
-					OS.gdk_color_free (ptr [0]);
-				}
+		if (!ownerDraw) {
+			ptr [0] = 0;
+			OS.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_BACKGROUND, ptr, -1);
+			if (ptr [0] != 0) {
+				OS.g_object_set (cell, OS.cell_background_gdk, ptr[0], 0);
+				OS.gdk_color_free (ptr [0]);
 			}
 		}
 		if (!isPixbuf) {
@@ -684,12 +655,7 @@
 		createRenderers (checkColumn.handle, checkColumn.modelIndex, false, checkColumn.style);
 	}
 	createRenderers (columnHandle, modelIndex, index == 0, column == null ? 0 : column.style);
-	/*
-	* Use GTK_TREE_VIEW_COLUMN_GROW_ONLY on GTK versions < 2.3.2
-	* because fixed_height_mode is not supported.
-	*/
-	boolean useVirtual = (style & SWT.VIRTUAL) != 0 && OS.GTK_VERSION >= OS.VERSION (2, 3, 2);
-	if (!useVirtual && columnCount == 0) {
+	if ((style & SWT.VIRTUAL) == 0 && columnCount == 0) {
 		OS.gtk_tree_view_column_set_sizing (columnHandle, OS.GTK_TREE_VIEW_COLUMN_GROW_ONLY);
 	} else {
 		OS.gtk_tree_view_column_set_sizing (columnHandle, OS.GTK_TREE_VIEW_COLUMN_FIXED);
@@ -756,10 +722,7 @@
 	OS.gtk_scrolled_window_set_policy (scrolledHandle, hsp, vsp);
 	if ((style & SWT.BORDER) != 0) OS.gtk_scrolled_window_set_shadow_type (scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
 	if ((style & SWT.VIRTUAL) != 0) {
-		/* The fixed_height_mode property only exists in GTK 2.3.2 and greater */
-		if (OS.GTK_VERSION >= OS.VERSION (2, 3, 2)) {
-			OS.g_object_set (handle, OS.fixed_height_mode, true, 0);
-		}
+		OS.g_object_set (handle, OS.fixed_height_mode, true, 0);
 	}
 	if (!searchEnabled ()) {
 		/*
@@ -870,19 +833,8 @@
 	if ((style & SWT.CHECK) != 0 && check) {
 		OS.gtk_tree_view_column_pack_start (columnHandle, checkRenderer, false);
 		OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.active, CHECKED_COLUMN);
-		/*
-		* Feature in GTK. The inconsistent property only exists in GTK 2.2.x.
-		*/
-		if (OS.GTK_VERSION >= OS.VERSION (2, 2, 0)) {
-			OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.inconsistent, GRAYED_COLUMN);
-		}
-		/*
-		* Bug in GTK. GTK renders the background on top of the checkbox.
-		* This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-		*/
-		if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-			if (!ownerDraw) OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-		}
+		OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.inconsistent, GRAYED_COLUMN);
+		if (!ownerDraw) OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
 		if (ownerDraw) {
 			OS.gtk_tree_view_column_set_cell_data_func (columnHandle, checkRenderer, display.cellDataProc, handle, 0);
 			OS.g_object_set_qdata (checkRenderer, Display.SWT_OBJECT_INDEX1, columnHandle);
@@ -927,15 +879,9 @@
 
 	/* Add attributes */
 	OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.pixbuf, modelIndex + CELL_PIXBUF);
-	/*
-	 * Bug on GTK. Gtk renders the background on top of the pixbuf.
-	 * This only happens in version 2.2.1 and earlier. The fix is not to set the background.   
-	 */
-	if (OS.GTK_VERSION > OS.VERSION (2, 2, 1)) {
-		if (!ownerDraw) {
-			OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-			OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
-		}
+	if (!ownerDraw) {
+		OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
+		OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.cell_background_gdk, BACKGROUND_COLUMN);
 	}
 	OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.text, modelIndex + CELL_TEXT);
 	OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, OS.foreground_gdk, FOREGROUND_COLUMN);
@@ -1108,28 +1054,6 @@
 
 
 void destroyItem (TreeItem item) {
-	/*
-	* Bug in GTK.  GTK segment faults when a root tree item
-	* is destroyed when the tree is expanded and the last leaf of
-	* the root is selected.  This only happens in versions earlier
-	* than 2.0.6.  The fix is to collapse the tree item being destroyed
-	* when it is a root, before it is destroyed.
-	*/
-	if (OS.GTK_VERSION < OS.VERSION (2, 0, 6)) {
-		int length = OS.gtk_tree_model_iter_n_children (modelHandle, 0);
-		if (length > 0) {
-			int /*long*/ iter = OS.g_malloc (OS.GtkTreeIter_sizeof ());
-			boolean valid = OS.gtk_tree_model_iter_children (modelHandle, iter, 0);
-			while (valid) {
-				if (item.handle == iter) {
-					item.setExpanded (false);
-					break;
-				}
-				valid = OS.gtk_tree_model_iter_next (modelHandle, iter);
-			}
-			OS.g_free (iter);
-		}
-	}
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
 	OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
 	OS.gtk_tree_store_remove (modelHandle, item.handle);
@@ -1747,21 +1671,7 @@
 public TreeItem[] getSelection () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength  = 0;
-		display.treeSelection = new int [items.length];
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		TreeItem [] result = new TreeItem [display.treeSelectionLength];
-		for (int i=0; i<result.length; i++) result [i] = items [display.treeSelection [i]];
-		return result;
-	}
-	/*
-	* Bug in GTK.  gtk_tree_selection_get_selected_rows() segmentation faults
-	* in versions smaller than 2.2.4 if the model is NULL.  The fix is
-	* to give a valid pointer instead.
-	*/
-	int /*long*/ [] model = OS.GTK_VERSION < OS.VERSION (2, 2, 4) ? new int /*long*/ [1] : null;
-	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, model);
+	int /*long*/ list = OS.gtk_tree_selection_get_selected_rows (selection, null);
 	if (list != 0) {
 		int count = OS.g_list_length (list);
 		TreeItem [] treeSelection = new TreeItem [count];
@@ -1800,12 +1710,6 @@
 public int getSelectionCount () {
 	checkWidget();
 	int /*long*/ selection = OS.gtk_tree_view_get_selection (handle);
-	if (OS.GTK_VERSION < OS.VERSION (2, 2, 0)) {
-		display.treeSelectionLength = 0;
-		display.treeSelection = null;
-		OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle);
-		return display.treeSelectionLength;
-	}
 	return OS.gtk_tree_selection_count_selected_rows (selection);
 }
 
@@ -2038,31 +1942,6 @@
 	return super.gtk_expose_event (widget, eventPtr);
 }
 
-int /*long*/ gtk_key_press_event (int /*long*/ widget, int /*long*/ eventPtr) {
-	int /*long*/ result = super.gtk_key_press_event (widget, eventPtr);
-	if (result != 0) return result;
-	if (OS.GTK_VERSION < OS.VERSION (2, 2 ,0)) {
-		/*
-		* Feature in GTK 2.0.x.  When an item is default selected using
-		* the return key, GTK does not issue notification. The fix is
-		* to issue this notification when the return key is pressed.
-		*/
-		GdkEventKey keyEvent = new GdkEventKey ();
-		OS.memmove (keyEvent, eventPtr, GdkEventKey.sizeof);
-		int key = keyEvent.keyval;
-		switch (key) {
-			case OS.GDK_Return:
-			case OS.GDK_KP_Enter: {
-				Event event = new Event ();
-				event.item = getFocusItem (); 
-				sendSelectionEvent (SWT.DefaultSelection, event, false);
-				break;
-			}
-		}
-	}
-	return result;
-}
-
 int /*long*/ gtk_motion_notify_event (int /*long*/ widget, int /*long*/ event) {
 	int /*long*/ window = OS.GDK_EVENT_WINDOW (event);
 	if (window != OS.gtk_tree_view_get_bin_window (handle)) return 0;
@@ -3003,7 +2882,7 @@
 	OS.gtk_widget_modify_base (handle, 0, color);
 }
 
-void setBackgroundPixmap (int /*long*/ pixmap) {
+void setBackgroundPixmap (Image image) {
 	ownerDraw = true;
 	recreateRenderers ();
 }
@@ -3163,11 +3042,6 @@
 
 void setScrollWidth (int /*long*/ column, TreeItem item) {
 	if (columnCount != 0 || currentItem == item) return;
-	/*
-	* Use GTK_TREE_VIEW_COLUMN_GROW_ONLY on GTK versions < 2.3.2
-	* because fixed_height_mode is not supported.
-	*/
-	if (((style & SWT.VIRTUAL) != 0) && OS.GTK_VERSION < OS.VERSION (2, 3, 2)) return;
 	int width = OS.gtk_tree_view_column_get_fixed_width (column);
 	int itemWidth = calculateWidth (column, item.handle, true);
 	if (width < itemWidth) {
@@ -3519,15 +3393,6 @@
 	OS.gtk_tree_path_free (path);
 }
 
-int /*long*/ treeSelectionProc (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int[] selection, int length) {
-	if (selection != null) {
-		int [] index = new int [1];
-		OS.gtk_tree_model_get (modelHandle, iter, ID_COLUMN, index, -1);
-		selection [(int)/*64*/length] = index [0];
-	}
-	return 0;
-}
-
 void updateScrollBarValue (ScrollBar bar) {
 	super.updateScrollBarValue (bar);
 	/*
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java
index 68d8a81..da70cac 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeItem.java
@@ -1315,18 +1315,19 @@
 public void setExpanded (boolean expanded) {
 	checkWidget();
 	int /*long*/ path = OS.gtk_tree_model_get_path (parent.modelHandle, handle);
-	if (expanded) {
-		OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_EXPAND_ROW);
-		OS.gtk_tree_view_expand_row (parent.handle, path, false);
-		OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_EXPAND_ROW);
-	} else {
-		OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_COLLAPSE_ROW);
-		OS.gtk_widget_realize (parent.handle);
-		OS.gtk_tree_view_collapse_row (parent.handle, path);
-		OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_COLLAPSE_ROW);
+	if (expanded != OS.gtk_tree_view_row_expanded (parent.handle, path)) {
+		if (expanded) {
+			OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_EXPAND_ROW);
+			OS.gtk_tree_view_expand_row (parent.handle, path, false);
+			OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_EXPAND_ROW);
+		} else {
+			OS.g_signal_handlers_block_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_COLLAPSE_ROW);
+			OS.gtk_widget_realize (parent.handle);
+			OS.gtk_tree_view_collapse_row (parent.handle, path);
+			OS.g_signal_handlers_unblock_matched (parent.handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, TEST_COLLAPSE_ROW);
+		}
 	}
 	OS.gtk_tree_path_free (path);
-	cached = true;
 }
 
 
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 6285902..3196831 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
@@ -1679,10 +1679,6 @@
 	return 0;
 }
 
-int /*long*/ treeSelectionProc (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int [] selection, int length) {
-	return 0;
-}
-
 boolean translateTraversal (int event) {
 	return false;
 }
diff --git a/bundles/org.eclipse.swt/buildSWT.xml b/bundles/org.eclipse.swt/buildSWT.xml
index 9ac071b..b1db703 100644
--- a/bundles/org.eclipse.swt/buildSWT.xml
+++ b/bundles/org.eclipse.swt/buildSWT.xml
@@ -86,11 +86,11 @@
 			<param name="fragment" value="org.eclipse.swt.gtk.linux.ppc64"/>
 		</antcall>
 		<antcall target="check_fragment_libraries">
-			<param name="library_count" value="10"/>
+			<param name="library_count" value="11"/>
 			<param name="fragment" value="org.eclipse.swt.gtk.linux.s390"/>
 		</antcall>
 		<antcall target="check_fragment_libraries">
-			<param name="library_count" value="10"/>
+			<param name="library_count" value="11"/>
 			<param name="fragment" value="org.eclipse.swt.gtk.linux.s390x"/>
 		</antcall>
 		<antcall target="check_fragment_libraries">
@@ -159,7 +159,7 @@
 	<target name="check_fragment_libraries" depends="get_version">
 		<echo>Checking ${fragment}</echo>
 		<property name="checkdir" value="~/build/check_libraries"/>
-		<property name="library_count" value="123"/>
+		<property name="library_count" value="125"/>
 		<property name="fragment" value=""/>
 		<fileset id="match" dir="${repo.bin}/bundles/${fragment}">
 			<filename regex="[0-9][0-9][0-9][0-9]."/>
diff --git a/bundles/org.eclipse.swt/buildnotes_swt.html b/bundles/org.eclipse.swt/buildnotes_swt.html
index 01593e7..6026817 100644
--- a/bundles/org.eclipse.swt/buildnotes_swt.html
+++ b/bundles/org.eclipse.swt/buildnotes_swt.html
@@ -11,6 +11,24 @@
 Eclipse Platform Build Notes<br>
 SWT</h1>
 
+<h2>SWT Build 3820 - Saturday January 21, 2012</h2>
+
+<blockquote>
+<a href=https://bugs.eclipse.org/bugs/buglist.cgi?bug_file_loc=;bug_file_loc_type=allwordssubstr;bug_id=;bugidtype=include;chfield=resolution;target_milestone=;chfieldfrom=2012-01-19+20%3A58%3A01+-0500;chfieldto=2012-01-20+22%3A04%3A26+%2B0000;chfieldvalue=FIXED;classification=Eclipse;component=SWT;email1=;email2=;emailtype1=substring;emailtype2=substring;field-1-0-0=classification;field-1-1-0=product;field-1-2-0=component;field0-0-0=noop;keywords=;keywords_type=allwords;long_desc=;long_desc_type=allwordssubstr;product=Platform;query_format=advanced;remaction=;short_desc=;short_desc_type=allwordssubstr;status_whiteboard=;status_whiteboard_type=allwordssubstr;type-1-0-0=anyexact;type-1-1-0=anyexact;type-1-2-0=anyexact;type0-0-0=noop;value-1-0-0=Eclipse;value-1-1-0=Platform;value-1-2-0=SWT;value0-0-0=;votes=;query_based_on=>Bugs fixed</a>
+</blockquote>
+
+<h2>SWT Build 3819 - Friday January 20, 2012</h2>
+
+<blockquote>
+<a href=https://bugs.eclipse.org/bugs/buglist.cgi?bug_file_loc=;bug_file_loc_type=allwordssubstr;bug_id=;bugidtype=include;chfield=resolution;target_milestone=;chfieldfrom=2012-01-16+18%3A13%3A12+-0500;chfieldto=2012-01-20+01%3A57%3A59+%2B0000;chfieldvalue=FIXED;classification=Eclipse;component=SWT;email1=;email2=;emailtype1=substring;emailtype2=substring;field-1-0-0=classification;field-1-1-0=product;field-1-2-0=component;field0-0-0=noop;keywords=;keywords_type=allwords;long_desc=;long_desc_type=allwordssubstr;product=Platform;query_format=advanced;remaction=;short_desc=;short_desc_type=allwordssubstr;status_whiteboard=;status_whiteboard_type=allwordssubstr;type-1-0-0=anyexact;type-1-1-0=anyexact;type-1-2-0=anyexact;type0-0-0=noop;value-1-0-0=Eclipse;value-1-1-0=Platform;value-1-2-0=SWT;value0-0-0=;votes=;query_based_on=>Bugs fixed</a>
+</blockquote>
+
+<h2>SWT Build 3818 - Tuesday January 17, 2012</h2>
+
+<blockquote>
+<a href=https://bugs.eclipse.org/bugs/buglist.cgi?bug_file_loc=;bug_file_loc_type=allwordssubstr;bug_id=;bugidtype=include;chfield=resolution;target_milestone=;chfieldfrom=2012-01-09+16%3A58%3A14+-0500;chfieldto=2012-01-16+23%3A13%3A09+%2B0000;chfieldvalue=FIXED;classification=Eclipse;component=SWT;email1=;email2=;emailtype1=substring;emailtype2=substring;field-1-0-0=classification;field-1-1-0=product;field-1-2-0=component;field0-0-0=noop;keywords=;keywords_type=allwords;long_desc=;long_desc_type=allwordssubstr;product=Platform;query_format=advanced;remaction=;short_desc=;short_desc_type=allwordssubstr;status_whiteboard=;status_whiteboard_type=allwordssubstr;type-1-0-0=anyexact;type-1-1-0=anyexact;type-1-2-0=anyexact;type0-0-0=noop;value-1-0-0=Eclipse;value-1-1-0=Platform;value-1-2-0=SWT;value0-0-0=;votes=;query_based_on=>Bugs fixed</a>
+</blockquote>
+
 <h2>SWT Build 3817b - Tuesday January 10, 2012</h2>
 
 <blockquote>