From 80d792676a89eab7796b0c75e2209db901d1f9ee Mon Sep 17 00:00:00 2001 From: MartinVazquez1982 Date: Thu, 18 Jun 2026 16:01:42 -0300 Subject: [PATCH 1/5] fix getPrimaryMonitor returning zero bounds --- .../src/webMain/java/org/eclipse/swt/widgets/DartDisplay.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swt_native/src/webMain/java/org/eclipse/swt/widgets/DartDisplay.java b/swt_native/src/webMain/java/org/eclipse/swt/widgets/DartDisplay.java index 1afb4ab8..0e44e7ea 100644 --- a/swt_native/src/webMain/java/org/eclipse/swt/widgets/DartDisplay.java +++ b/swt_native/src/webMain/java/org/eclipse/swt/widgets/DartDisplay.java @@ -1386,6 +1386,8 @@ public Monitor[] getMonitors() { public Monitor getPrimaryMonitor() { checkDevice(); Monitor monitor = new Monitor(); + monitor.setBounds(bounds); + monitor.setClientArea(bounds); return monitor; } From 312db2b055da33143f7a405c8d1414fc0ea0e988 Mon Sep 17 00:00:00 2001 From: MartinVazquez1982 Date: Thu, 18 Jun 2026 16:02:28 -0300 Subject: [PATCH 2/5] handle null image path from bundle URLs in DartImage --- .../main/java/org/eclipse/swt/graphics/GraphicsUtils.java | 4 +--- .../webMain/java/org/eclipse/swt/graphics/DartImage.java | 7 +++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/swt_native/src/main/java/org/eclipse/swt/graphics/GraphicsUtils.java b/swt_native/src/main/java/org/eclipse/swt/graphics/GraphicsUtils.java index 984ac6e6..1e68760c 100644 --- a/swt_native/src/main/java/org/eclipse/swt/graphics/GraphicsUtils.java +++ b/swt_native/src/main/java/org/eclipse/swt/graphics/GraphicsUtils.java @@ -173,9 +173,7 @@ public static Color getDefaultBackground(Display display) { * or null if path is null */ static String getFilename(String path) { - if (path == null) { - return null; - } + if (path == null) return null; String fileName = new java.io.File(path).getName(); int dotIndex = fileName.lastIndexOf('.'); return (dotIndex > 0) ? fileName.substring(0, dotIndex) : fileName; diff --git a/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java b/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java index 224a2ff2..bd1923da 100644 --- a/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java +++ b/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java @@ -566,8 +566,11 @@ public DartImage(Device device, ImageFileNameProvider imageFileNameProvider, Ima if (imageFileNameProvider == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); try { - this.filename = GraphicsUtils.getFilename(imageFileNameProvider.getImagePath(100)); - imageData = new ImageData(imageFileNameProvider.getImagePath(100)); + String path100 = imageFileNameProvider.getImagePath(100); + if (path100 == null) + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + this.filename = GraphicsUtils.getFilename(path100); + imageData = new ImageData(path100); initUsingFileNameProvider(imageFileNameProvider); init(imageData, 100); init(); From cd8423677254ff429194c05f30ece32e338ba6ec Mon Sep 17 00:00:00 2001 From: MartinVazquez1982 Date: Thu, 18 Jun 2026 16:04:22 -0300 Subject: [PATCH 3/5] use placeholder image when SVG rasterizer is missing --- .../java/org/eclipse/swt/graphics/DartImage.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java b/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java index bd1923da..8c9d9b5d 100644 --- a/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java +++ b/swt_native/src/webMain/java/org/eclipse/swt/graphics/DartImage.java @@ -933,12 +933,22 @@ void init(ImageData image, int imageZoom) { private void initUsingImageDataProvider(ImageDataProvider imageDataProvider) { this.imageDataProvider = imageDataProvider; - ImageData imageData = imageDataProvider.getImageData(100); + ImageData imageData; + try { + imageData = imageDataProvider.getImageData(100); + } catch (SWTException e) { + imageData = null; + } if (imageData == null) { - SWT.error(SWT.ERROR_INVALID_ARGUMENT); + imageData = new ImageData(1, 1, 32, new PaletteData(0xFF0000, 0xFF00, 0xFF)); } init(imageData, 100); - ImageData imageData2x = imageDataProvider.getImageData(200); + ImageData imageData2x; + try { + imageData2x = imageDataProvider.getImageData(200); + } catch (SWTException e) { + imageData2x = null; + } if (imageData2x != null) { alphaInfo_200 = new AlphaInfo(); } From e24e8b9b3d7b49d04cb4286ccf07d46454967a1a Mon Sep 17 00:00:00 2001 From: MartinVazquez1982 Date: Fri, 19 Jun 2026 12:43:48 -0300 Subject: [PATCH 4/5] tests for issue ready --- .../dev/equo/swt/WebFixesFlutterTest.java | 79 +++++++++++++++++++ .../swt/graphics/GraphicsUtilsTest.java | 5 ++ 2 files changed, 84 insertions(+) create mode 100644 swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java diff --git a/swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java b/swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java new file mode 100644 index 00000000..320a22e1 --- /dev/null +++ b/swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java @@ -0,0 +1,79 @@ +package dev.equo.swt; + +import dev.equo.swt.harness.FlutterHarness; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageDataProvider; +import org.eclipse.swt.graphics.ImageFileNameProvider; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Monitor; +import org.junit.jupiter.api.*; + +import static org.assertj.core.api.Assertions.*; + +/** + * Regression tests for the three web-mode fixes described in CHANGES.md. + * Compiled against the web backend (webMain) via the webTest source set. + * Run with: ./gradlew :swt_native:webTest + */ +@Tag("flutter-it") +class WebFixesFlutterTest { + + private static FlutterHarness flutter; + private static Display display; + + @BeforeAll + static void setup() { + flutter = new FlutterHarness(); + // Injects the harness as the global bridge before Display is created, which + // causes SwtFlutterBridgeWeb.initForDisplay to skip starting its own server. + flutter.init(); + display = new Display(); + } + + @AfterAll + static void teardown() { + if (display != null && !display.isDisposed()) display.dispose(); + if (flutter != null) flutter.teardown(); + } + + // Fix 1: DartDisplay.getPrimaryMonitor() was returning a Monitor with zeroed + // bounds because it omitted the monitor.setBounds(bounds) / setClientArea(bounds) + // calls that getMonitors() already had. After the fix both must agree. + @Test + void getPrimaryMonitor_bounds_consistent_with_getMonitors() { + Monitor primary = display.getPrimaryMonitor(); + Rectangle primaryBounds = primary.getBounds(); + Rectangle firstMonitorBounds = display.getMonitors()[0].getBounds(); + + assertThat(primaryBounds).isEqualTo(firstMonitorBounds); + assertThat(primary.getClientArea()).isEqualTo(primaryBounds); + } + + // Fix 2 (web): When ImageFileNameProvider.getImagePath(100) returns null (as it + // does for JFace bundle-URL resources in web mode), DartImage must throw a + // SWTException so JFace can catch it and fall back to InputStream loading — + // not a NullPointerException which JFace does not catch. + @Test + void imageFileNameProvider_null_path_throws_SWTException_not_NPE() { + ImageFileNameProvider nullPathProvider = zoom -> null; + assertThatThrownBy(() -> new Image(display, nullPathProvider)) + .isInstanceOf(SWTException.class) + .isNotInstanceOf(NullPointerException.class); + } + + // Fix 3: When ImageDataProvider.getImageData(100) throws SWTException (e.g. + // "No SVG rasterizer found"), DartImage must absorb the exception and use a + // 1x1 placeholder instead of propagating it — which would crash the caller + // (ProgressMonitorPart) since it does not wrap new Image() in a try-catch. + @Test + void imageDataProvider_swt_exception_falls_back_to_placeholder() { + ImageDataProvider throwingProvider = zoom -> { + throw new SWTException(SWT.ERROR_UNSUPPORTED_FORMAT); + }; + Image image = new Image(display, throwingProvider); + image.dispose(); + } +} diff --git a/swt_native/src/test/java/org/eclipse/swt/graphics/GraphicsUtilsTest.java b/swt_native/src/test/java/org/eclipse/swt/graphics/GraphicsUtilsTest.java index 26d64733..a399e946 100644 --- a/swt_native/src/test/java/org/eclipse/swt/graphics/GraphicsUtilsTest.java +++ b/swt_native/src/test/java/org/eclipse/swt/graphics/GraphicsUtilsTest.java @@ -43,6 +43,11 @@ public void should_parse_filename(String inputPath) { assertThat(filename).isEqualTo(imageName); } + @Test + public void should_return_null_when_path_is_null() { + assertThat(GraphicsUtils.getFilename(null)).isNull(); + } + @Test public void should_copy_fontdata() { // Create a FontData From b2d901c04acd31cda95fe06e802cc7eb950c0823 Mon Sep 17 00:00:00 2001 From: MartinVazquez1982 Date: Tue, 23 Jun 2026 17:19:17 -0300 Subject: [PATCH 5/5] rename WebFixesFlutterTest to WebDisplayImageFlutterTest and remove fix-referencing comments --- ...Test.java => WebDisplayImageFlutterTest.java} | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) rename swt_native/src/test/java/dev/equo/swt/{WebFixesFlutterTest.java => WebDisplayImageFlutterTest.java} (69%) diff --git a/swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java b/swt_native/src/test/java/dev/equo/swt/WebDisplayImageFlutterTest.java similarity index 69% rename from swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java rename to swt_native/src/test/java/dev/equo/swt/WebDisplayImageFlutterTest.java index 320a22e1..ed2db0b0 100644 --- a/swt_native/src/test/java/dev/equo/swt/WebFixesFlutterTest.java +++ b/swt_native/src/test/java/dev/equo/swt/WebDisplayImageFlutterTest.java @@ -14,12 +14,13 @@ import static org.assertj.core.api.Assertions.*; /** - * Regression tests for the three web-mode fixes described in CHANGES.md. + * Regression tests for web-mode behavior: monitor bounds consistency, + * image provider null-path handling, and image provider exception recovery. * Compiled against the web backend (webMain) via the webTest source set. * Run with: ./gradlew :swt_native:webTest */ @Tag("flutter-it") -class WebFixesFlutterTest { +class WebDisplayImageFlutterTest { private static FlutterHarness flutter; private static Display display; @@ -39,9 +40,6 @@ static void teardown() { if (flutter != null) flutter.teardown(); } - // Fix 1: DartDisplay.getPrimaryMonitor() was returning a Monitor with zeroed - // bounds because it omitted the monitor.setBounds(bounds) / setClientArea(bounds) - // calls that getMonitors() already had. After the fix both must agree. @Test void getPrimaryMonitor_bounds_consistent_with_getMonitors() { Monitor primary = display.getPrimaryMonitor(); @@ -52,10 +50,6 @@ void getPrimaryMonitor_bounds_consistent_with_getMonitors() { assertThat(primary.getClientArea()).isEqualTo(primaryBounds); } - // Fix 2 (web): When ImageFileNameProvider.getImagePath(100) returns null (as it - // does for JFace bundle-URL resources in web mode), DartImage must throw a - // SWTException so JFace can catch it and fall back to InputStream loading — - // not a NullPointerException which JFace does not catch. @Test void imageFileNameProvider_null_path_throws_SWTException_not_NPE() { ImageFileNameProvider nullPathProvider = zoom -> null; @@ -64,10 +58,6 @@ void imageFileNameProvider_null_path_throws_SWTException_not_NPE() { .isNotInstanceOf(NullPointerException.class); } - // Fix 3: When ImageDataProvider.getImageData(100) throws SWTException (e.g. - // "No SVG rasterizer found"), DartImage must absorb the exception and use a - // 1x1 placeholder instead of propagating it — which would crash the caller - // (ProgressMonitorPart) since it does not wrap new Image() in a try-catch. @Test void imageDataProvider_swt_exception_falls_back_to_placeholder() { ImageDataProvider throwingProvider = zoom -> {