Bug 564097 - [GTK][HiDPI] Cairo auto scaling causing scaling problems

Added dynamic changes to icons. Goal is so that Eclipse or
application restart is not required. Right now certain images are scaled
however they are blurry since they are not using the higher resolution
image. Tested primarily on Wayland.

Change-Id: I5e7ef6abbb256f02c5a5774e3b338b0d2407d72b
Signed-off-by: Paul D'Pong <sdamrong@redhat.com>
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 d154647..f3cb10c 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
@@ -6828,42 +6828,6 @@
 }
 #endif
 
-#ifndef NO_gtk_1image_1set_1from_1gicon__JJ
-JNIEXPORT void JNICALL GTK_NATIVE(gtk_1image_1set_1from_1gicon__JJ)
-	(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
-{
-	GTK_NATIVE_ENTER(env, that, gtk_1image_1set_1from_1gicon__JJ_FUNC);
-/*
-	gtk_image_set_from_gicon((GtkImage *)arg0, (GIcon *)arg1);
-*/
-	{
-		GTK_LOAD_FUNCTION(fp, gtk_image_set_from_gicon)
-		if (fp) {
-			((void (CALLING_CONVENTION*)(GtkImage *, GIcon *))fp)((GtkImage *)arg0, (GIcon *)arg1);
-		}
-	}
-	GTK_NATIVE_EXIT(env, that, gtk_1image_1set_1from_1gicon__JJ_FUNC);
-}
-#endif
-
-#ifndef NO_gtk_1image_1set_1from_1gicon__JJI
-JNIEXPORT void JNICALL GTK_NATIVE(gtk_1image_1set_1from_1gicon__JJI)
-	(JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2)
-{
-	GTK_NATIVE_ENTER(env, that, gtk_1image_1set_1from_1gicon__JJI_FUNC);
-/*
-	gtk_image_set_from_gicon((GtkImage *)arg0, (GIcon *)arg1, (GtkIconSize)arg2);
-*/
-	{
-		GTK_LOAD_FUNCTION(fp, gtk_image_set_from_gicon)
-		if (fp) {
-			((void (CALLING_CONVENTION*)(GtkImage *, GIcon *, GtkIconSize))fp)((GtkImage *)arg0, (GIcon *)arg1, (GtkIconSize)arg2);
-		}
-	}
-	GTK_NATIVE_EXIT(env, that, gtk_1image_1set_1from_1gicon__JJI_FUNC);
-}
-#endif
-
 #ifndef NO_gtk_1image_1set_1from_1icon_1name__J_3B
 JNIEXPORT void JNICALL GTK_NATIVE(gtk_1image_1set_1from_1icon_1name__J_3B)
 	(JNIEnv *env, jclass that, jlong arg0, jbyteArray arg1)
@@ -6918,6 +6882,16 @@
 }
 #endif
 
+#ifndef NO_gtk_1image_1set_1from_1surface
+JNIEXPORT void JNICALL GTK_NATIVE(gtk_1image_1set_1from_1surface)
+	(JNIEnv *env, jclass that, jlong arg0, jlong arg1)
+{
+	GTK_NATIVE_ENTER(env, that, gtk_1image_1set_1from_1surface_FUNC);
+	gtk_image_set_from_surface((GtkImage *)arg0, (cairo_surface_t *)arg1);
+	GTK_NATIVE_EXIT(env, that, gtk_1image_1set_1from_1surface_FUNC);
+}
+#endif
+
 #ifndef NO_gtk_1image_1set_1pixel_1size
 JNIEXPORT void JNICALL GTK_NATIVE(gtk_1image_1set_1pixel_1size)
 	(JNIEnv *env, jclass that, jlong arg0, jint arg1)
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 68e3037..003d5d9 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
@@ -543,11 +543,10 @@
 	"gtk_1image_1new_1from_1icon_1name___3B",
 	"gtk_1image_1new_1from_1icon_1name___3BI",
 	"gtk_1image_1new_1from_1pixbuf",
-	"gtk_1image_1set_1from_1gicon__JJ",
-	"gtk_1image_1set_1from_1gicon__JJI",
 	"gtk_1image_1set_1from_1icon_1name__J_3B",
 	"gtk_1image_1set_1from_1icon_1name__J_3BI",
 	"gtk_1image_1set_1from_1pixbuf",
+	"gtk_1image_1set_1from_1surface",
 	"gtk_1image_1set_1pixel_1size",
 	"gtk_1init_1check__",
 	"gtk_1init_1check___3J_3J",
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 5c188ed..3b73e83 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
@@ -541,11 +541,10 @@
 	gtk_1image_1new_1from_1icon_1name___3B_FUNC,
 	gtk_1image_1new_1from_1icon_1name___3BI_FUNC,
 	gtk_1image_1new_1from_1pixbuf_FUNC,
-	gtk_1image_1set_1from_1gicon__JJ_FUNC,
-	gtk_1image_1set_1from_1gicon__JJI_FUNC,
 	gtk_1image_1set_1from_1icon_1name__J_3B_FUNC,
 	gtk_1image_1set_1from_1icon_1name__J_3BI_FUNC,
 	gtk_1image_1set_1from_1pixbuf_FUNC,
+	gtk_1image_1set_1from_1surface_FUNC,
 	gtk_1image_1set_1pixel_1size_FUNC,
 	gtk_1init_1check___FUNC,
 	gtk_1init_1check___3J_3J_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
index c8c5e0d..cd068b8 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java
@@ -1462,20 +1462,10 @@
 	 */
 	public static final native void gtk_image_set_from_pixbuf(long image, long pixbuf);
 	/**
-	 * @method flags=dynamic
 	 * @param image cast=(GtkImage *)
-	 * @param gicon cast=(GIcon *)
-	 * @param size cast=(GtkIconSize)
+	 * @param surface cast=(cairo_surface_t *)
 	 */
-	/* [GTK3 only] */
-	public static final native void gtk_image_set_from_gicon(long image, long gicon, int size);
-	/**
-	 * @method flags=dynamic
-	 * @param image cast=(GtkImage *)
-	 * @param gicon cast=(GIcon *)
-	 */
-	/* [GTK4 only] */
-	public static final native void gtk_image_set_from_gicon(long image, long gicon);
+	public static final native void gtk_image_set_from_surface(long image, long surface);
 	/**
 	 * @method flags=dynamic
 	 * @param icon_name cast=(const gchar *)
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 5d01245..38f1f0e 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
@@ -843,9 +843,8 @@
 	}
 	if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
 	if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
-	Rectangle srcRect = DPIUtil.autoScaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight));
 	Rectangle destRect = DPIUtil.autoScaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight));
-	drawImage(image, srcRect.x, srcRect.y, srcRect.width, srcRect.height, destRect.x, destRect.y, destRect.width, destRect.height, false);
+	drawImage(image, srcX, srcY, srcWidth, srcHeight, destRect.x, destRect.y, destRect.width, destRect.height, false);
 }
 void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
 	/* Refresh Image as per zoom level, if required. */
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 1b50a34..b68d3b3 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
@@ -714,6 +714,21 @@
 }
 
 /**
+ * Refreshes the image for the current device scale factor.
+ * <p>
+ * <b>IMPORTANT:</b> This function 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 used from application code.
+ * </p>
+ *
+ * @noreference This function is not intended to be referenced by clients.
+ */
+public boolean internal_gtk_refreshImageForZoom() {
+	return refreshImageForZoom();
+}
+
+/**
  * Refresh the Image based on the zoom level, if required.
  *
  * @return true if image is refreshed
@@ -1542,6 +1557,11 @@
 @Override
 public String toString () {
 	if (isDisposed()) return "Image {*DISPOSED*}";
+
+	if (imageFileNameProvider != null) {
+		return "Image {" + imageFileNameProvider.getImagePath(100) + "}";
+	}
+
 	return "Image {" + surface + "}";
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
index 91d67c7..a08306b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Button.java
@@ -1056,11 +1056,10 @@
 	if (image != null) {
 		if (image.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
 		imageList = new ImageList ();
-		int imageIndex = imageList.add (image);
-		long pixbuf = imageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon(imageHandle, pixbuf);
+		imageList.add (image);
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 	}
 	this.image = image;
 	updateWidgetsVisibility();
@@ -1220,4 +1219,15 @@
 	return super.windowProc(handle, arg0, user_data);
 }
 
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
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 037882f..21a5ff8 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
@@ -155,7 +155,6 @@
 	long lastHandle;
 	Widget lastWidget;
 	Widget [] widgetTable;
-	Shell firstShell;
 	final static int GROW_SIZE = 1024;
 	static final int SWT_OBJECT_INDEX;
 	static final int SWT_OBJECT_INDEX1;
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 00613e3..d3402dd 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
@@ -647,13 +647,12 @@
 	if (image != null) {
 		if (image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
 		imageList = new ImageList ();
-		int imageIndex = imageList.add (image);
-		long pixbuf = imageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon (imageHandle, pixbuf);
+		imageList.add (image);
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		if (text.length () == 0) GTK.gtk_widget_hide (labelHandle);
 		GTK.gtk_widget_show (imageHandle);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 		GTK.gtk_widget_show (labelHandle);
 		GTK.gtk_widget_hide (imageHandle);
 	}
@@ -698,4 +697,16 @@
 	}
 	return super.windowProc (handle, user_data);
 }
+
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Label.java
index 888090a..809b58c 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Label.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Label.java
@@ -623,13 +623,12 @@
 	imageList = null;
 	if (image != null) {
 		imageList = new ImageList ();
-		int imageIndex = imageList.add (image);
-		long pixbuf = imageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon (imageHandle, pixbuf);
+		imageList.add (image);
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		GTK.gtk_widget_hide (labelHandle);
 		GTK.gtk_widget_show (imageHandle);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 		GTK.gtk_widget_show (labelHandle);
 		GTK.gtk_widget_hide (imageHandle);
 	}
@@ -709,4 +708,16 @@
 	}
 	return super.windowProc(handle, arg0, user_data);
 }
+
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java
index 58cc81b..c901495 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/MenuItem.java
@@ -865,14 +865,14 @@
 
 		if (!GTK.GTK4 && !GTK.GTK_IS_MENU_ITEM (handle)) return;
 		if (OS.SWT_PADDED_MENU_ITEMS && imageHandle != 0) {
-			GTK.gtk_image_set_from_pixbuf(imageHandle, pixbuf);
+			GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		} else {
 			if (imageHandle == 0 && boxHandle != 0) {
 				imageHandle = GTK.gtk_image_new_from_pixbuf (pixbuf);
 				GTK.gtk_container_add (boxHandle, imageHandle);
 				GTK.gtk_box_reorder_child (boxHandle, imageHandle, 0);
 			} else {
-				GTK.gtk_image_set_from_pixbuf(imageHandle, pixbuf);
+				GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 			}
 			if (boxHandle == 0) error (SWT.ERROR_NO_HANDLES);
 		}
@@ -1213,4 +1213,16 @@
 	return maskKeysym.keysym != 0;
 }
 
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
+
 }
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 b6c8c77..e6dc03c 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
@@ -825,17 +825,6 @@
 	* to avoid confusion.
 	*/
 	GTK.gtk_widget_realize (shellHandle);
-
-	if (display.firstShell == null) {
-		display.firstShell = this;
-
-		int dpi = 96;
-		long window = GTK.gtk_widget_get_window(shellHandle);
-		long monitor = GDK.gdk_display_get_monitor_at_window(GDK.gdk_display_get_default(), window);
-		long scale_factor = GDK.gdk_monitor_get_scale_factor(monitor);
-
-		DPIUtil.setDeviceZoom(DPIUtil.mapDPIToZoom (dpi * (int)scale_factor));
-	}
 }
 
 @Override
@@ -927,8 +916,7 @@
 @Override
 void hookEvents () {
 	super.hookEvents ();
-	long notifyAddress = display.notifyCallback.getAddress();
-	OS.g_signal_connect (shellHandle, OS.dpi_changed, notifyAddress, Widget.DPI_CHANGED);
+	OS.g_signal_connect (shellHandle, OS.dpi_changed, display.notifyProc, Widget.DPI_CHANGED);
 
 	if (GTK.GTK4) {
 		// Replace configure-event, map-event with generic event handler
@@ -938,7 +926,7 @@
 		// Replaced "window-state-event" with GdkSurface "notify::state", pass shellHandle as user_data
 		GTK.gtk_widget_realize(shellHandle);
 		long gdkSurface = gtk_widget_get_surface (shellHandle);
-		OS.g_signal_connect (gdkSurface, OS.notify_state, notifyAddress, shellHandle);
+		OS.g_signal_connect (gdkSurface, OS.notify_state, display.notifyProc, shellHandle);
 		OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [SIZE_ALLOCATE_GTK4], 0, display.getClosure (SIZE_ALLOCATE_GTK4), false);
 	} else {
 		OS.g_signal_connect_closure_by_id (shellHandle, display.signalIds [WINDOW_STATE_EVENT], 0, display.getClosure (WINDOW_STATE_EVENT), false);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
index 1adc30a..d0e2ce5 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TabItem.java
@@ -400,11 +400,11 @@
 		} else {
 			imageList.put (imageIndex, image);
 		}
-		long pixbuf = imageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon (imageHandle, pixbuf);
+
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		GTK.gtk_widget_show (imageHandle);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 		GTK.gtk_widget_hide (imageHandle);
 	}
 }
@@ -492,4 +492,15 @@
 	toolTipText = string;
 }
 
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableColumn.java
index 41830d0..bbbf66b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableColumn.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableColumn.java
@@ -626,11 +626,10 @@
 		}
 		int imageIndex = headerImageList.indexOf (image);
 		if (imageIndex == -1) imageIndex = headerImageList.add (image);
-		long pixbuf = headerImageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon (imageHandle, pixbuf);
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		GTK.gtk_widget_show (imageHandle);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 		GTK.gtk_widget_hide (imageHandle);
 	}
 }
@@ -812,4 +811,15 @@
 	sendEvent (SWT.Resize);
 }
 
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java
index b1b77fb..6435563 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ToolItem.java
@@ -717,8 +717,7 @@
 		if (imageList != null) {
 			int index = imageList.indexOf (hotImage);
 			if (index != -1 && imageHandle != 0) {
-				long pixbuf = imageList.getPixbuf (index);
-				gtk_image_set_from_gicon(imageHandle, pixbuf);
+				GTK.gtk_image_set_from_surface(imageHandle, hotImage.surface);
 			}
 		}
 	}
@@ -775,8 +774,7 @@
 			if (imageList != null) {
 				int index = imageList.indexOf (image);
 				if (index != -1 && imageHandle != 0) {
-					long pixbuf = imageList.getPixbuf (index);
-					gtk_image_set_from_gicon(imageHandle, pixbuf);
+					GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 				}
 			}
 		}
@@ -800,6 +798,7 @@
 	super.hookEvents ();
 	if ((style & SWT.SEPARATOR) != 0) return;
 	OS.g_signal_connect_closure (handle, OS.clicked, display.getClosure (CLICKED), false);
+
 	/*
 	 * Feature in GTK. GtkToolItem does not respond to basic listeners
 	 * such as button-press, enter-notify to it. The fix is to assign
@@ -1189,10 +1188,10 @@
 		} else {
 			imageList.put (imageIndex, image);
 		}
-		long pixbuf = imageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon(imageHandle, pixbuf);
+
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 	} else {
-		gtk_image_set_from_gicon(imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 	}
 	/*
 	* If Text/Image of a tool-item changes, then it is
@@ -1450,4 +1449,26 @@
 	}
 	return nameText;
 }
+
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	if (hotImage != null) {
+		hotImage.internal_gtk_refreshImageForZoom();
+		setHotImage(hotImage);
+	}
+
+	if (disabledImage != null) {
+		disabledImage.internal_gtk_refreshImageForZoom();
+		setDisabledImage(disabledImage);
+	}
+
+	return 0;
+}
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeColumn.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeColumn.java
index 38931f2..5b851e5 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeColumn.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TreeColumn.java
@@ -601,11 +601,10 @@
 		}
 		int imageIndex = headerImageList.indexOf (image);
 		if (imageIndex == -1) imageIndex = headerImageList.add (image);
-		long pixbuf = headerImageList.getPixbuf (imageIndex);
-		gtk_image_set_from_gicon (imageHandle, pixbuf);
+		GTK.gtk_image_set_from_surface(imageHandle, image.surface);
 		GTK.gtk_widget_show (imageHandle);
 	} else {
-		gtk_image_set_from_gicon (imageHandle, 0);
+		GTK.gtk_image_set_from_surface(imageHandle, 0);
 		GTK.gtk_widget_hide (imageHandle);
 	}
 }
@@ -785,4 +784,15 @@
 	sendEvent (SWT.Resize);
 }
 
+@Override
+long dpiChanged(long object, long arg0) {
+	super.dpiChanged(object, arg0);
+
+	if (image != null) {
+		image.internal_gtk_refreshImageForZoom();
+		setImage(image);
+	}
+
+	return 0;
+}
 }
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 046708f..a7e7898 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
@@ -1158,6 +1158,9 @@
 }
 
 void hookEvents () {
+	if (handle != 0) {
+		OS.g_signal_connect (handle, OS.dpi_changed, display.notifyProc, Widget.DPI_CHANGED);
+	}
 }
 
 /*
@@ -2350,9 +2353,6 @@
 	GTK.gtk_widget_get_preferred_size (widget, requisition, null);
 }
 
-void gtk_image_set_from_gicon (long imageHandle, long pixbuf){
-	GTK.gtk_image_set_from_gicon(imageHandle, pixbuf, GTK.GTK_ICON_SIZE_SMALL_TOOLBAR);
-}
 /**
  * Retrieves the amount of space around the outside of the container.
  * On GTK3: this is done using gtk_container_get_border_width.