From 56a8fb89098a74518e574181a24525a2a1d7669f Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Fri, 3 Oct 2025 19:19:46 -0400 Subject: [PATCH] Avoid reading org.eclipse.swt.* properties too early The value of org.eclipse.swt.internal.gdk.backend is not set until a display is created at least once since this value is assigned in the Display constructor. To be able to detect if Display has been created, set "org.eclipse.swt.internal.gdk.backend" on wayland too. A similar problem exists for org.eclipse.swt.internal.gtk.version in relation to OS. This is a fix for a regression caused by moving the setting of org.eclipse.swt.internal.gdk.backend from OS to Display in 5d67ce66d23165bd252339134ca86889b9594b63. That commit fixed an unrelated bug, but sometimes bad initialization of isX11 is an unintended side effect causing tests to be skipped or run in unexpected ways since isX11 was not correct. See for example https://github.com/eclipse-platform/eclipse.platform.swt/pull/2592 for a test that was silently being skipped and had bitrotten as a result. --- .../gtk/org/eclipse/swt/widgets/Display.java | 8 ++++ .../eclipse/swt/tests/junit/SwtTestUtil.java | 47 +++++++++++++++++-- .../Test_org_eclipse_swt_dnd_Clipboard.java | 4 +- .../Test_org_eclipse_swt_widgets_Display.java | 4 +- .../Test_org_eclipse_swt_widgets_Shell.java | 10 ++-- 5 files changed, 60 insertions(+), 13 deletions(-) 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 5b52c106f48..b59ebb0b777 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 @@ -1211,6 +1211,14 @@ void createDisplay (DeviceData data) { xDisplay = GTK.GTK4 ? 0 : GDK.gdk_x11_get_default_xdisplay(); // set GDK backend if we are on X11 System.setProperty("org.eclipse.swt.internal.gdk.backend", "x11"); + } else if (OS.isWayland()) { + // only other option for backend is Wayland at the moment + System.setProperty("org.eclipse.swt.internal.gdk.backend", "wayland"); + } else { + // unreachable at the moment since isWayland is defined as !isX11 + // but if other items are added in the future this should be changed + // from unknown to real value. + System.setProperty("org.eclipse.swt.internal.gdk.backend", "unknown"); } if (OS.SWT_DEBUG) Device.DEBUG = true; if (!GTK.GTK4) { diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/SwtTestUtil.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/SwtTestUtil.java index 3d5f188d43b..bf0de69dcfa 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/SwtTestUtil.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/SwtTestUtil.java @@ -100,10 +100,49 @@ public class SwtTestUtil { /** Useful if you want some tests not to run on Jenkins with user "genie.platform" */ public final static boolean isRunningOnContinousIntegration = isGTK && ("genie.platform".equalsIgnoreCase(System.getProperty("user.name"))); - public final static boolean isX11 = isGTK - && "x11".equals(System.getProperty("org.eclipse.swt.internal.gdk.backend")); - public final static boolean isGTK4 = isGTK - && System.getProperty("org.eclipse.swt.internal.gtk.version", "").startsWith("4"); + /** + * Return whether running on x11. This is dynamically set at runtime and cannot + * be accessed before the corresponding property is initialized in Display. + * + * Note: this method still must be called after the first + * Display is created to be valid + */ + public final static boolean isX11() { + if (!isGTK) { + return false; + } + String backend = System.getProperty("org.eclipse.swt.internal.gdk.backend"); + + if ("x11".equals(backend)) { + return true; + } else if ("wayland".equals(backend)) { + return false; + } + fail("org.eclipse.swt.internal.gdk.backend System property is not set yet. Create a new Display before calling isX11"); + throw new IllegalStateException("unreachable"); + } + + /** + * Return whether running on GTK4. This is dynamically set at runtime and cannot + * be accessed before the corresponding property is initialized in OS. + * + * Note: this method still must be called after the static + * block of OS is run. + */ + public final static boolean isGTK4() { + if (!isGTK) { + return false; + } + + String version = System.getProperty("org.eclipse.swt.internal.gtk.version", ""); + if (version.startsWith("4")) { + return true; + } else if (!version.isBlank()) { + return false; + } + fail("org.eclipse.swt.internal.gtk.version System property is not set yet. Create a new Display (or otherwise access OS) before calling isGTK4"); + throw new IllegalStateException("unreachable"); + } /** * The palette used by images. See {@link #getAllPixels(Image)} and {@link #createImage} diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java index 3690dcdc7cb..a912fb4c701 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_dnd_Clipboard.java @@ -80,7 +80,7 @@ public void setUp() { } private void sleep() throws InterruptedException { - if (SwtTestUtil.isGTK4) { + if (SwtTestUtil.isGTK4()) { /** * TODO remove all uses of sleep and change them to processEvents with the * suitable conditional, or entirely remove them @@ -351,7 +351,7 @@ public void test_setContents() throws Exception { String result = runOperationInThread(remote::getStringContents); assertEquals(helloWorld, result); } catch (Exception | AssertionError e) { - if (SwtTestUtil.isGTK4 && !SwtTestUtil.isX11) { + if (SwtTestUtil.isGTK4() && !SwtTestUtil.isX11()) { // TODO make the code + test stable throw new RuntimeException( "This test is really unstable on wayland backend, at least with Ubuntu 25.04", e); diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Display.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Display.java index 5802d11f132..bf97574e158 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Display.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Display.java @@ -1247,7 +1247,7 @@ public void test_setCursorLocationII(TestInfo info) { display.setCursorLocation(location.x, location.y); // don't put cursor into a corner, since that could trigger special platform events drainEventQueue(display, 150); // workaround for https://bugs.eclipse.org/492569 Point actual = display.getCursorLocation(); - if (!BUG_492569 && SwtTestUtil.isX11) { + if (!BUG_492569 && SwtTestUtil.isX11()) { if (!location.equals(actual)) { Screenshots.takeScreenshot(getClass(), info.getDisplayName()); // Bug 528968 This call causes crash on Wayland. fail("\nExpected:"+location.toString()+" Actual:"+actual.toString()); @@ -1279,7 +1279,7 @@ public void test_setCursorLocationLorg_eclipse_swt_graphics_Point(TestInfo info) } drainEventQueue(display, 150); // workaround for https://bugs.eclipse.org/492569 Point actual = display.getCursorLocation(); - if (!BUG_492569 && SwtTestUtil.isX11) { + if (!BUG_492569 && SwtTestUtil.isX11()) { if (!location.equals(actual)) { Screenshots.takeScreenshot(getClass(), info.getDisplayName()); // Bug 528968 This call causes crash on Wayland. fail("\nExpected:"+location.toString()+" Actual:"+actual.toString()); diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java index cd144f8b425..7dc27a47b50 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Shell.java @@ -460,7 +460,7 @@ public void test_getImeInputMode() { @Test public void test_getLocation() { //Setting location for Windows is not supported in GTK4 - if (SwtTestUtil.isGTK4) { + if (SwtTestUtil.isGTK4()) { return; } shell.setLocation(10,15); @@ -656,7 +656,7 @@ public void test_setBoundsLorg_eclipse_swt_graphics_Rectangle() { */ @Test public void test_activateEventSend() throws InterruptedException { - assumeTrue((SwtTestUtil.isGTK && SwtTestUtil.isX11) || SwtTestUtil.isGTK4, + assumeTrue((SwtTestUtil.isGTK && SwtTestUtil.isX11()) || SwtTestUtil.isGTK4(), "Feature only works on GTK3 in x11 or GTK4 - https://bugs.eclipse.org/436841"); AtomicBoolean activateCalled = new AtomicBoolean(); @@ -708,7 +708,7 @@ public void test_activateEventSend() throws InterruptedException { */ @Test public void test_setBounds() throws Exception { - if (SwtTestUtil.isX11) { + if (SwtTestUtil.isX11()) { Rectangle bounds = new Rectangle(100, 200, 200, 200); Rectangle bounds2 = new Rectangle(150, 250, 250, 250); @@ -1037,7 +1037,7 @@ public void test_Issue450_NoShellActivateOnSetFocus() { @Override public void test_setLocationLorg_eclipse_swt_graphics_Point() { //Setting location for Windows is not supported in GTK4 - if (SwtTestUtil.isGTK4) { + if (SwtTestUtil.isGTK4()) { return; } super.test_setLocationLorg_eclipse_swt_graphics_Point(); @@ -1047,7 +1047,7 @@ public void test_setLocationLorg_eclipse_swt_graphics_Point() { @Override public void test_setLocationII() { //Setting location for Windows is not supported in GTK4 - if (SwtTestUtil.isGTK4) { + if (SwtTestUtil.isGTK4()) { return; } super.test_setLocationII();