From 3ca0e13d03a1e4c6b23d368593ef33ef0ec42e20 Mon Sep 17 00:00:00 2001
From: Patrick Ziegler <ziegler.patrick@hotmail.de>
Date: Tue, 24 Mar 2026 20:52:41 +0100
Subject: [PATCH] Add SVG variants for WindowBuilder cursors

Using pixel-based images still leads to improperly scaled cursors on
Windows if at > 100% zoom. The old cursors are still kept for backwards
compatibility, but on latest SWT versions we'll now use SVGs.
---
 .../wb/internal/gef/core/SharedCursors.java   | 108 ++++++++++++++----
 .../wb/internal/gef/core/icons/Tree_Add.gif   | Bin 125 -> 0 bytes
 .../gef/core/icons/Tree_Add_Cursor.gif        | Bin 1199 -> 0 bytes
 .../gef/core/icons/Tree_Add_Cursor2.gif       | Bin 1185 -> 0 bytes
 .../internal/gef/core/icons/Tree_Add_Mask.gif | Bin 129 -> 0 bytes
 .../wb/internal/gef/core/icons/add_cursor.gif | Bin 1064 -> 0 bytes
 .../wb/internal/gef/core/icons/add_cursor.png | Bin 0 -> 766 bytes
 .../wb/internal/gef/core/icons/add_cursor.svg |  67 +++++++++++
 .../internal/gef/core/icons/add_cursor3.png   | Bin 500 -> 0 bytes
 .../wb/internal/gef/core/icons/addcursor.gif  | Bin 1078 -> 0 bytes
 .../internal/gef/core/icons/cursor@1.5x.svg   |  22 ++++
 .../wb/internal/gef/core/icons/cursor@1x.svg  |  22 ++++
 .../wb/internal/gef/core/icons/cursor@2x.svg  |  22 ++++
 .../internal/gef/core/icons/move_cursor.gif   | Bin 1073 -> 0 bytes
 .../internal/gef/core/icons/move_cursor.png   | Bin 0 -> 809 bytes
 .../internal/gef/core/icons/move_cursor.svg   |  67 +++++++++++
 .../internal/gef/core/icons/move_cursor2.gif  | Bin 1080 -> 0 bytes
 .../internal/gef/core/icons/move_cursor3.png  | Bin 491 -> 0 bytes
 .../wb/internal/gef/core/icons/no_cursor.gif  | Bin 1079 -> 0 bytes
 .../wb/internal/gef/core/icons/no_cursor.png  | Bin 0 -> 896 bytes
 .../wb/internal/gef/core/icons/no_cursor.svg  |  70 ++++++++++++
 .../wb/internal/gef/core/icons/no_cursor3.png | Bin 734 -> 0 bytes
 .../internal/gef/core/icons/noaddcursor.gif   | Bin 1074 -> 0 bytes
 .../wb/core/editor/constants/CoreImages.java  |  10 +-
 .../wb/internal/core/DesignerPlugin.java      |  14 ++-
 25 files changed, 371 insertions(+), 31 deletions(-)
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add.gif
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor.gif
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor2.gif
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Mask.gif
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.gif
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.png
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.svg
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor3.png
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/addcursor.gif
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1.5x.svg
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1x.svg
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@2x.svg
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.gif
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.png
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.svg
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor2.gif
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor3.png
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.gif
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.png
 create mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.svg
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor3.png
 delete mode 100644 org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/noaddcursor.gif

diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/SharedCursors.java b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/SharedCursors.java
index 3bc0f0a2e..4c7989c8d 100644
--- a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/SharedCursors.java
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/SharedCursors.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2023 Google, Inc.
+ * Copyright (c) 2011, 2026 Google, Inc. and others.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License 2.0 which is available at
@@ -12,9 +12,20 @@
  *******************************************************************************/
 package org.eclipse.wb.internal.gef.core;
 
+import org.eclipse.wb.internal.core.DesignerPlugin;
+
 import org.eclipse.draw2d.Cursors;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.DecorationOverlayIcon;
+import org.eclipse.jface.viewers.IDecoration;
 import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Device;
 import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageDataProvider;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
 
 /**
  * A shared collection of Cursors.
@@ -23,25 +34,78 @@
  * @coverage gef.core
  */
 public class SharedCursors extends Cursors {
-	public static final Cursor CURSOR_TREE_ADD = new Cursor(null,
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/Tree_Add_Mask.gif")),
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/Tree_Add.gif")),
-			0,
-			0);
-	public static final Cursor CURSOR_TREE_ADD_MAC = new Cursor(null,
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/Tree_Add_Cursor2.gif")),
-			0,
-			0);
-	public static final Cursor CURSOR_ADD = new Cursor(null,
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/add_cursor.gif")),
-			0,
-			0);
-	public static final Cursor CURSOR_MOVE = new Cursor(null,
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/move_cursor.gif")),
-			0,
-			0);
-	public static final Cursor CURSOR_NO = new Cursor(null,
-			new ImageData(SharedCursors.class.getResourceAsStream("icons/no_cursor.gif")),
-			0,
-			0);
+
+	/**
+	 * Local cache to store the cursor data for each zoom level.
+	 */
+	private static final ImageDescriptor CURSOR_AT_100_ZOOM = createDescriptor("icons/cursor@1x.svg"); //$NON-NLS-1$
+	private static final ImageDescriptor CURSOR_AT_150_ZOOM = createDescriptor("icons/cursor@1.5x.svg"); //$NON-NLS-1$
+	private static final ImageDescriptor CURSOR_AT_200_ZOOM = createDescriptor("icons/cursor@2x.svg"); //$NON-NLS-1$
+	private static final ImageDescriptor CURSOR_DESCRIPTOR = ImageDescriptor.createFromImageDataProvider(zoom -> {
+		if (zoom < 150) {
+			return CURSOR_AT_100_ZOOM.getImageData(100);
+		}
+		if (zoom < 200) {
+			return CURSOR_AT_150_ZOOM.getImageData(100);
+		}
+		return CURSOR_AT_200_ZOOM.getImageData(100);
+	});
+
+	public static final Cursor CURSOR_ADD = createCursor("icons/add_cursor.svg");
+	public static final Cursor CURSOR_MOVE = createCursor("icons/move_cursor.svg");
+	public static final Cursor CURSOR_NO = createCursor("icons/no_cursor.svg");
+
+	private static Cursor createCursor(String sourceName) {
+		if (DesignerPlugin.isSvgSupported()) {
+			ImageDescriptor src1 = createDescriptor(sourceName);
+			ImageDescriptor src = new DecorationOverlayIcon(src1, CURSOR_DESCRIPTOR, IDecoration.TOP_LEFT) {
+				@Override
+				// Disabled by default due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=97506
+				protected boolean supportsZoomLevel(int zoomLevel) {
+					return true;
+				}
+			};
+			return createCursor(src, 0, 0);
+		}
+		ImageDescriptor src = createDescriptor(sourceName);
+		return createCursor(src, 0, 0);
+	}
+
+	/**
+	 * Creates and returns an image descriptor from the given file. If the file is
+	 * an SVG, it will be automatically swapped out with a PNG if not yet supported
+	 * by SWT.
+	 */
+	public static ImageDescriptor createDescriptor(String filename) {
+		URL resourceURL = SharedCursors.class.getResource(DesignerPlugin.getEffectiveFileName(filename));
+		return ImageDescriptor.createFromURL(resourceURL);
+	}
+
+	/**
+	 * This method attempts to create the cursor using a constructor introduced in
+	 * SWT 3.131.0 that takes an {@link ImageDataProvider}. If this constructor is
+	 * not available (SWT versions prior to 3.131.0), it falls back to using the
+	 * older constructor that accepts {@link ImageData}.
+	 */
+	private static Cursor createCursor(ImageDescriptor source, int hotspotX, int hotspotY) {
+		try {
+			ImageDataProvider provider = zoom -> {
+				if (zoom < 150) {
+					return source.getImageData(100);
+				}
+				if (zoom < 200) {
+					return source.getImageData(150);
+				}
+				return source.getImageData(200);
+			};
+			Constructor<Cursor> ctor = Cursor.class.getConstructor(Device.class, ImageDataProvider.class, int.class,
+					int.class);
+			return ctor.newInstance(null, provider, hotspotX, hotspotY);
+		} catch (NoSuchMethodException e) {
+			// SWT version < 3.131.0 (no ImageDataProvider-based constructor)
+			return new Cursor(null, source.getImageData(100), hotspotX, hotspotY); // older constructor
+		} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+			throw new RuntimeException("Failed to instantiate Cursor", e); //$NON-NLS-1$
+		}
+	}
 }
\ No newline at end of file
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add.gif
deleted file mode 100644
index 75d6cc23b6110514ffb9c9edfe5f74e9e346e836..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor.gif
deleted file mode 100644
index 3c0caf3db26b595900837df6c8464ef1345d4ee6..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor2.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Cursor2.gif
deleted file mode 100644
index c1bdbe9ef08c3a77e8429b119590db899c6b0b91..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Mask.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/Tree_Add_Mask.gif
deleted file mode 100644
index 0fb52a6a07868b9da5f7561ca023a4d76b6f7c8e..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.gif
deleted file mode 100644
index b5a819008adc9c7f41e801bc4ed58801c0671fb8..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.png
new file mode 100644
index 0000000000000000000000000000000000000000..f43a2fde3508f3277cc6ddbb791d8422231b7688
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.svg
new file mode 100644
index 000000000..6b71f00b9
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg1"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1">
+    <linearGradient
+       id="linearGradient3">
+      <stop
+         style="stop-color:#70b87a;stop-opacity:1;"
+         offset="0"
+         id="stop3" />
+      <stop
+         style="stop-color:#299548;stop-opacity:1;"
+         offset="1"
+         id="stop4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1">
+      <stop
+         style="stop-color:#3c9c55;stop-opacity:1;"
+         offset="0"
+         id="stop1" />
+      <stop
+         style="stop-color:#1a8e3d;stop-opacity:1;"
+         offset="1"
+         id="stop2" />
+    </linearGradient>
+    <linearGradient
+       xlink:href="#linearGradient1"
+       id="linearGradient2"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       xlink:href="#linearGradient3"
+       id="linearGradient4"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <g
+     id="layer1">
+    <circle
+       style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient2);stroke-width:1;stroke-opacity:1"
+       id="path1"
+       cx="18"
+       cy="24"
+       r="6.5" />
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-opacity:1"
+       d="m 15,25 v -2 h 2 v -2 h 2 v 2 h 2 v 2 h -2 v 2 h -2 v -2 z"
+       id="path2" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor3.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/add_cursor3.png
deleted file mode 100644
index 543c56e5982dfb5889f68d6fe9a522e1f0aba64f..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/addcursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/addcursor.gif
deleted file mode 100644
index 92fcac4b645196e4431067e621e37639f11e4dfd..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1.5x.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1.5x.svg
new file mode 100644
index 000000000..85a3f9084
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1.5x.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="48"
+   height="48"
+   viewBox="0 0 12.7 12.7"
+   version="1.1"
+   id="svg5"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs2" />
+  <g
+     id="layer1"
+     transform="translate(0,-0.05476875)">
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
+       d="M 0.1322915,0.18708826 V 6.8016437 l 1.5875,-1.4551806 1.190625,2.38125 0.7937499,-0.396875 -0.7937499,-1.984375 v -0.396875 h 1.9843749 z"
+       id="path1516" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1x.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1x.svg
new file mode 100644
index 000000000..cd22d6738
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@1x.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="32"
+   height="32"
+   viewBox="0 0 8.4666665 8.4666666"
+   version="1.1"
+   id="svg5"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs2" />
+  <g
+     id="layer1"
+     transform="translate(0,-0.18706042)">
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
+       d="M 0.13229166,0.31937992 V 4.8172966 L 1.190625,3.7589632 1.984375,5.3464632 2.5135417,5.0818799 1.984375,3.7589632 V 3.4943799 h 1.3229167 z"
+       id="path1516" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@2x.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@2x.svg
new file mode 100644
index 000000000..1b3f3ae79
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/cursor@2x.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="64"
+   height="64"
+   viewBox="0 0 16.933333 16.933332"
+   version="1.1"
+   id="svg5"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs2" />
+  <g
+     id="layer1"
+     transform="translate(0,-0.1870604)">
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
+       d="M 0.1322915,0.31937992 V 8.7860464 L 2.2489581,7.1985465 3.8364581,10.373547 4.8947914,9.8443798 3.8364581,7.1985465 V 6.6693798 h 2.6458333 z"
+       id="path1516" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.gif
deleted file mode 100644
index d72830d8d186c252e882cdfdc028e00bdeba5f0a..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.png
new file mode 100644
index 0000000000000000000000000000000000000000..68220fa5c262ca4269acc797914e6786ea149632
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.svg
new file mode 100644
index 000000000..410f85be6
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg1"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1">
+    <linearGradient
+       id="linearGradient3">
+      <stop
+         style="stop-color:#70b87a;stop-opacity:1;"
+         offset="0"
+         id="stop3" />
+      <stop
+         style="stop-color:#299548;stop-opacity:1;"
+         offset="1"
+         id="stop4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1">
+      <stop
+         style="stop-color:#3c9c55;stop-opacity:1;"
+         offset="0"
+         id="stop1" />
+      <stop
+         style="stop-color:#1a8e3d;stop-opacity:1;"
+         offset="1"
+         id="stop2" />
+    </linearGradient>
+    <linearGradient
+       xlink:href="#linearGradient1"
+       id="linearGradient2"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       xlink:href="#linearGradient3"
+       id="linearGradient4"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <g
+     id="layer1">
+    <circle
+       style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient2);stroke-width:1;stroke-opacity:1"
+       id="path1"
+       cx="18"
+       cy="24"
+       r="6.5" />
+    <path
+       style="display:inline;fill:none;stroke:#ffffff;stroke-width:1.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+       d="m 14.582641,22.830041 2.000031,4.000494 4.975069,-5.970391"
+       id="path4065" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor2.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor2.gif
deleted file mode 100644
index 8fa3c9858772baabe4592c3e9292aa426b9c1913..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor3.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/move_cursor3.png
deleted file mode 100644
index 35d34a50c7b93eb3fcaf3e1796131376b3726d74..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.gif
deleted file mode 100644
index 77cfaeab8fec15d66b0698c5c022ef8ab88f2824..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.png
new file mode 100644
index 0000000000000000000000000000000000000000..a675bedab610dbc223145b75d7605321d9e50fc2
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.svg b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.svg
new file mode 100644
index 000000000..cc552c222
--- /dev/null
+++ b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="32"
+   height="32"
+   viewBox="0 0 32 32"
+   version="1.1"
+   id="svg1"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs1">
+    <linearGradient
+       id="linearGradient3">
+      <stop
+         style="stop-color:#fee1a7;stop-opacity:1;"
+         offset="0"
+         id="stop3" />
+      <stop
+         style="stop-color:#da5e35;stop-opacity:1;"
+         offset="1"
+         id="stop4" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1">
+      <stop
+         style="stop-color:#e4967b;stop-opacity:1;"
+         offset="0"
+         id="stop1" />
+      <stop
+         style="stop-color:#d74f23;stop-opacity:1;"
+         offset="1"
+         id="stop2" />
+    </linearGradient>
+    <linearGradient
+       xlink:href="#linearGradient1"
+       id="linearGradient2"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       xlink:href="#linearGradient3"
+       id="linearGradient4"
+       x1="10.961023"
+       y1="17.062119"
+       x2="25.077953"
+       y2="31.093788"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <g
+     id="layer1">
+    <circle
+       style="fill:url(#linearGradient4);fill-opacity:1;stroke:url(#linearGradient2);stroke-width:1;stroke-opacity:1"
+       id="path1"
+       cx="18"
+       cy="24"
+       r="6.5" />
+    <rect
+       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-opacity:1"
+       id="rect4"
+       width="6"
+       height="2"
+       x="15"
+       y="23" />
+  </g>
+</svg>
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor3.png b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/no_cursor3.png
deleted file mode 100644
index 3e482ff7e3ebc958e11dc76f2eb03cd809f93334..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/noaddcursor.gif b/org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/core/icons/noaddcursor.gif
deleted file mode 100644
index 2807e1e615afc441c42d67da4b30fe1d61e5a353..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/org.eclipse.wb.core/src/org/eclipse/wb/core/editor/constants/CoreImages.java b/org.eclipse.wb.core/src/org/eclipse/wb/core/editor/constants/CoreImages.java
index dec919913..94a9a4235 100644
--- a/org.eclipse.wb.core/src/org/eclipse/wb/core/editor/constants/CoreImages.java
+++ b/org.eclipse.wb.core/src/org/eclipse/wb/core/editor/constants/CoreImages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2024, 2025 Patrick Ziegler and others.
+ * Copyright (c) 2024, 2026 Patrick Ziegler and others.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License 2.0 which is available at
@@ -145,14 +145,8 @@ private static ImageDescriptor of(String fileName) {
 	 * method, using the bundle of containing the class as reference.
 	 */
 	protected static ImageDescriptor of(Bundle bundle, String fileName) {
-		String effectiveFileName;
-		if (!DesignerPlugin.isSvgSupported() && fileName.endsWith(".svg")) { //$NON-NLS-1$
-			effectiveFileName = fileName.replaceFirst("\\.svg$", ".png"); //$NON-NLS-1$ //$NON-NLS-2$
-		} else {
-			effectiveFileName = fileName;
-		}
 		return ExecutionUtils.runObjectLog(() -> {
-			URI uri = URI.create("platform:/plugin/" + bundle.getSymbolicName() + "/icons/" + effectiveFileName);
+			URI uri = URI.create("platform:/plugin/" + bundle.getSymbolicName() + "/icons/" + DesignerPlugin.getEffectiveFileName(fileName));
 			URL url = uri.toURL();
 			return ImageDescriptor.createFromURL(url);
 		}, ImageDescriptor.getMissingImageDescriptor());
diff --git a/org.eclipse.wb.core/src/org/eclipse/wb/internal/core/DesignerPlugin.java b/org.eclipse.wb.core/src/org/eclipse/wb/internal/core/DesignerPlugin.java
index 7eb9a9bc7..e6675b620 100644
--- a/org.eclipse.wb.core/src/org/eclipse/wb/internal/core/DesignerPlugin.java
+++ b/org.eclipse.wb.core/src/org/eclipse/wb/internal/core/DesignerPlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2024 Google, Inc.
+ * Copyright (c) 2011, 2026 Google, Inc. and others.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License 2.0 which is available at
@@ -418,6 +418,18 @@ public static boolean isSvgSupported() {
 		return isSvgSupported;
 	}
 
+	/**
+	 * If {@code fileName} ends with {@code .svg}, the extension is changed to
+	 * {@code .png} if not yet supported by SWT.
+	 */
+	public static String getEffectiveFileName(String fileName) {
+		// If the SWT version doesn't yet support SVGs, fall back to PNG
+		if (!isSvgSupported() && fileName.endsWith(".svg")) { //$NON-NLS-1$
+			return fileName.replaceFirst("\\.svg$", ".png"); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return fileName;
+	}
+
 	////////////////////////////////////////////////////////////////////////////
 	//
 	// Linux only
