upgrade javafx to v26 with headless plaform
What changed, and why it matters
This commit upgrades the user-interface toolkit (JavaFX) from version 18/25 to version 26 and switches the headless mode from an older 'Monocle' setup to JavaFX 26's built-in 'Headless' glass platform. It also removes a locally maintained copy of the JavaFX Gradle plugin in favor of the upstream published plugin. The changes are primarily build-system and UI-platform modernization. There is no direct evidence in the commit that this fixes a specific security vulnerability, but dependency upgrades can indirectly improve security by removing old, potentially vulnerable components and reducing custom build code.
Treat this as a routine maintenance/dependency-hygiene commit. Verify the upgraded JavaFX 26 artifacts and the new upstream Gradle plugin are fetched from trusted repositories and that reproducible builds still pass. Monitor JavaFX 26 release notes for any security advisories. No immediate incident response is warranted based solely on this diff.
Security signals we found
Dependency upgrade: JavaFX 18/25 -> 26
Removal of vendored/in-tree JavaFX Gradle plugin buildSrc code
Headless platform migration from Monocle to JavaFX native Headless glass platform
No explicit security fix, CVE, or vulnerability description in commit message or diff
Evidence from the diff
The diff updates build.gradle to use JavaFX 26 uniformly (previously 18 for headless builds and 25.0.2 for desktop) and replaces the in-tree buildSrc JavaFX Gradle plugin with the upstream ‘org.openjfx.javafxplugin’ version 0.1.0. Headless JVM arguments change from ‘-Dglass.platform=Monocle -Dmonocle.platform=Headless -Dprism.order=sw’ to ‘-Dglass.platform=Headless’. Interface.java now detects ‘Headless’ as the glass.platform value. UI code removes @SuppressWarnings(‘deprecation’) and switches from TreeTableView/TableView.CONSTRAINED_RESIZE_POLICY to CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN, enabled by JavaFX 20+. AppController.java guards macOS menu setup with an additional Interface.DESKTOP check. No explicit security bug or CVE is mentioned.
Changed components
build.gradlebuildSrc JavaFX Gradle plugin (removed)org.openjfx.javafxplugin Gradle plugin (added)AppController macOS menu initializationInterface headless detectionCoinTreeTable column resize policyServerAliasDialog column resize policyInspect captured patch +11 / −543
diff --git a/build.gradle b/build.gradle
index 742cf59..6476878 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
plugins {
id 'application'
- id 'org-openjfx-javafxplugin'
+ id 'org.openjfx.javafxplugin' version '0.1.0'
id 'org.beryx.jlink' version '3.2.1'
id 'org.gradlex.extra-java-module-info' version '1.13.1'
id 'io.matthewnelson.kmp.tor.resource-filterjar' version '408.21.0'
@@ -32,7 +32,7 @@ tasks.withType(AbstractArchiveTask).configureEach {
}
javafx {
- version = headless ? "18" : "25.0.2"
+ version = "26"
modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.swing', 'javafx.graphics' ]
}
@@ -162,7 +162,7 @@ application {
applicationDefaultJvmArgs += ["-Dprism.lcdtext=false", "-Xdock:name=Sparrow"]
}
if(headless) {
- applicationDefaultJvmArgs += ["-Dglass.platform=Monocle", "-Dmonocle.platform=Headless", "-Dprism.order=sw"]
+ applicationDefaultJvmArgs += ["-Dglass.platform=Headless"]
}
}
@@ -256,7 +256,7 @@ jlink {
jvmArgs += ["-Dprism.lcdtext=false", "--add-opens=javafx.graphics/com.sun.glass.ui.mac=com.sparrowwallet.merged.module"]
}
if(headless) {
- jvmArgs += ["-Dglass.platform=Monocle", "-Dmonocle.platform=Headless", "-Dprism.order=sw"]
+ jvmArgs += ["-Dglass.platform=Headless"]
}
}
addExtraDependencies("javafx")
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
deleted file mode 100644
index a479973..0000000
--- a/buildSrc/build.gradle
+++ /dev/null
@@ -1,23 +0,0 @@
-plugins {
- id 'java-gradle-plugin' // so we can assign and ID to our plugin
-}
-
-dependencies {
- implementation 'com.google.gradle:osdetector-gradle-plugin:1.7.3'
-}
-
-repositories {
- mavenCentral()
- maven {
- url = uri("https://plugins.gradle.org/m2/")
- }
-}
-
-gradlePlugin {
- plugins {
- register("org-openjfx-javafxplugin") {
- id = "org-openjfx-javafxplugin"
- implementationClass = "org.openjfx.gradle.JavaFXPlugin"
- }
- }
-}
diff --git a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXModule.java b/buildSrc/src/main/java/org/openjfx/gradle/JavaFXModule.java
deleted file mode 100644
index 982d844..0000000
--- a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXModule.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2018, 2020, Gluon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * * Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.openjfx.gradle;
-
-import org.gradle.api.GradleException;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.Set;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public enum JavaFXModule {
-
- BASE,
- GRAPHICS(BASE),
- CONTROLS(BASE, GRAPHICS),
- FXML(BASE, GRAPHICS),
- MEDIA(BASE, GRAPHICS),
- SWING(BASE, GRAPHICS),
- WEB(BASE, CONTROLS, GRAPHICS, MEDIA);
-
- static final String PREFIX_MODULE = "javafx.";
- private static final String PREFIX_ARTIFACT = "javafx-";
-
- private List<JavaFXModule> dependentModules;
-
- JavaFXModule(JavaFXModule...dependentModules) {
- this.dependentModules = List.of(dependentModules);
- }
-
- public static Optional<JavaFXModule> fromModuleName(String moduleName) {
- return Stream.of(JavaFXModule.values())
- .filter(javaFXModule -> moduleName.equals(javaFXModule.getModuleName()))
- .findFirst();
- }
-
- public String getModuleName() {
- return PREFIX_MODULE + name().toLowerCase(Locale.ROOT);
- }
-
- public String getModuleJarFileName() {
- return getModuleName() + ".jar";
- }
-
- public String getArtifactName() {
- return PREFIX_ARTIFACT + name().toLowerCase(Locale.ROOT);
- }
-
- public boolean compareJarFileName(JavaFXPlatform platform, String jarFileName) {
- Pattern p = Pattern.compile(getArtifactName() + "-.+-" + platform.getClassifier() + "\\.jar");
- return p.matcher(jarFileName).matches();
- }
-
- public static Set<JavaFXModule> getJavaFXModules(List<String> moduleNames) {
- validateModules(moduleNames);
-
- return moduleNames.stream()
- .map(JavaFXModule::fromModuleName)
- .flatMap(Optional::stream)
- .flatMap(javaFXModule -> javaFXModule.getMavenDependencies().stream())
- .collect(Collectors.toSet());
- }
-
- public static void validateModules(List<String> moduleNames) {
- var invalidModules = moduleNames.stream()
- .filter(module -> JavaFXModule.fromModuleName(module).isEmpty())
- .collect(Collectors.toList());
-
- if (! invalidModules.isEmpty()) {
- throw new GradleException("Found one or more invalid JavaFX module names: " + invalidModules);
- }
- }
-
- public List<JavaFXModule> getDependentModules() {
- return dependentModules;
- }
-
- public List<JavaFXModule> getMavenDependencies() {
- List<JavaFXModule> dependencies = new ArrayList<>(dependentModules);
- dependencies.add(0, this);
- return dependencies;
- }
-}
diff --git a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXOptions.java b/buildSrc/src/main/java/org/openjfx/gradle/JavaFXOptions.java
deleted file mode 100644
index 70cdf94..0000000
--- a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXOptions.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2018, Gluon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * * Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.openjfx.gradle;
-
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.repositories.FlatDirectoryArtifactRepository;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.openjfx.gradle.JavaFXModule.PREFIX_MODULE;
-
-public class JavaFXOptions {
-
- private static final String MAVEN_JAVAFX_ARTIFACT_GROUP_ID = "org.openjfx";
- private static final String JAVAFX_SDK_LIB_FOLDER = "lib";
-
- private final Project project;
- private final JavaFXPlatform platform;
-
- private String version = "16";
- private String sdk;
- private String configuration = "implementation";
- private String lastUpdatedConfiguration;
- private List<String> modules = new ArrayList<>();
- private FlatDirectoryArtifactRepository customSDKArtifactRepository;
-
- public JavaFXOptions(Project project) {
- this.project = project;
- this.platform = JavaFXPlatform.detect(project);
- }
-
- public JavaFXPlatform getPlatform() {
- return platform;
- }
-
- public String getVersion() {
- return version;
- }
-
- public void setVersion(String version) {
- this.version = version;
- updateJavaFXDependencies();
- }
-
- /**
- * If set, the JavaFX modules will be taken from this local
- * repository, and not from Maven Central
- * @param sdk, the path to the local JavaFX SDK folder
- */
- public void setSdk(String sdk) {
- this.sdk = sdk;
- updateJavaFXDependencies();
- }
-
- public String getSdk() {
- return sdk;
- }
-
- /** Set the configuration name for dependencies, e.g.
- * 'implementation', 'compileOnly' etc.
- * @param configuration The configuration name for dependencies
- */
- public void setConfiguration(String configuration) {
- this.configuration = configuration;
- updateJavaFXDependencies();
- }
-
- public String getConfiguration() {
- return configuration;
- }
-
- public List<String> getModules() {
- return modules;
- }
-
- public void setModules(List<String> modules) {
- this.modules = modules;
- updateJavaFXDependencies();
- }
-
- public void modules(String...moduleNames) {
- setModules(List.of(moduleNames));
- }
-
- private void updateJavaFXDependencies() {
- clearJavaFXDependencies();
-
- String configuration = getConfiguration();
- JavaFXModule.getJavaFXModules(this.modules).stream()
- .sorted()
- .forEach(javaFXModule -> {
- if (customSDKArtifactRepository != null) {
- project.getDependencies().add(configuration, Map.of("name", javaFXModule.getModuleName()));
- } else {
- project.getDependencies().add(configuration,
- String.format("%s:%s:%s:%s", MAVEN_JAVAFX_ARTIFACT_GROUP_ID, javaFXModule.getArtifactName(),
- getVersion(), getPlatform().getClassifier()));
- }
- });
- lastUpdatedConfiguration = configuration;
- }
-
- private void clearJavaFXDependencies() {
- if (customSDKArtifactRepository != null) {
- project.getRepositories().remove(customSDKArtifactRepository);
- customSDKArtifactRepository = null;
- }
-
- if (sdk != null && ! sdk.isEmpty()) {
- Map<String, String> dirs = new HashMap<>();
- dirs.put("name", "customSDKArtifactRepository");
- if (sdk.endsWith(File.separator)) {
- dirs.put("dirs", sdk + JAVAFX_SDK_LIB_FOLDER);
- } else {
- dirs.put("dirs", sdk + File.separator + JAVAFX_SDK_LIB_FOLDER);
- }
- customSDKArtifactRepository = project.getRepositories().flatDir(dirs);
- }
-
- if (lastUpdatedConfiguration == null) {
- return;
- }
- var configuration = project.getConfigurations().findByName(lastUpdatedConfiguration);
- if (configuration != null) {
- if (customSDKArtifactRepository != null) {
- configuration.getDependencies()
- .removeIf(dependency -> dependency.getName().startsWith(PREFIX_MODULE));
- }
- configuration.getDependencies()
- .removeIf(dependency -> MAVEN_JAVAFX_ARTIFACT_GROUP_ID.equals(dependency.getGroup()));
- }
- }
-}
diff --git a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlatform.java b/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlatform.java
deleted file mode 100644
index 58347f1..0000000
--- a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlatform.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2018, Gluon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * * Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.openjfx.gradle;
-
-import com.google.gradle.osdetector.OsDetector;
-import org.gradle.api.GradleException;
-import org.gradle.api.Project;
-
-import java.awt.*;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
-public enum JavaFXPlatform {
-
- LINUX("linux", "linux-x86_64"),
- LINUX_MONOCLE("linux-monocle", "linux-x86_64-monocle"),
- LINUX_AARCH64("linux-aarch64", "linux-aarch_64"),
- LINUX_AARCH64_MONOCLE("linux-aarch64-monocle", "linux-aarch_64-monocle"),
- WINDOWS("win", "windows-x86_64"),
- WINDOWS_MONOCLE("win-monocle", "windows-x86_64-monocle"),
- OSX("mac", "osx-x86_64"),
- OSX_MONOCLE("mac-monocle", "osx-x86_64-monocle"),
- OSX_AARCH64("mac-aarch64", "osx-aarch_64"),
- OSX_AARCH64_MONOCLE("mac-aarch64-monocle", "osx-aarch_64-monocle");
-
- private final String classifier;
- private final String osDetectorClassifier;
-
- JavaFXPlatform( String classifier, String osDetectorClassifier ) {
- this.classifier = classifier;
- this.osDetectorClassifier = osDetectorClassifier;
- }
-
- public String getClassifier() {
- return classifier;
- }
-
- public static JavaFXPlatform detect(Project project) {
-
- String osClassifier = project.getExtensions().getByType(OsDetector.class).getClassifier();
-
- if("true".equals(System.getProperty("java.awt.headless"))) {
- osClassifier += "-monocle";
- }
-
- for ( JavaFXPlatform platform: values()) {
- if ( platform.osDetectorClassifier.equals(osClassifier)) {
- return platform;
- }
- }
-
- String supportedPlatforms = Arrays.stream(values())
- .map(p->p.osDetectorClassifier)
- .collect(Collectors.joining("', '", "'", "'"));
-
- throw new GradleException(
- String.format(
- "Unsupported JavaFX platform found: '%s'! " +
- "This plugin is designed to work on supported platforms only." +
- "Current supported platforms are %s.", osClassifier, supportedPlatforms )
- );
-
- }
-}
diff --git a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlugin.java b/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlugin.java
deleted file mode 100644
index a3faafc..0000000
--- a/buildSrc/src/main/java/org/openjfx/gradle/JavaFXPlugin.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2018, Gluon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * * Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.openjfx.gradle;
-
-import com.google.gradle.osdetector.OsDetectorPlugin;
-import org.gradle.api.Plugin;
-import org.gradle.api.Project;
-import org.openjfx.gradle.tasks.ExecTask;
-
-public class JavaFXPlugin implements Plugin<Project> {
-
- @Override
- public void apply(Project project) {
- project.getPlugins().apply(OsDetectorPlugin.class);
-
- project.getExtensions().create("javafx", JavaFXOptions.class, project);
-
- project.getTasks().register("configJavafxRun", ExecTask.class, project);
- }
-}
diff --git a/buildSrc/src/main/java/org/openjfx/gradle/tasks/ExecTask.java b/buildSrc/src/main/java/org/openjfx/gradle/tasks/ExecTask.java
deleted file mode 100644
index d62abcb..0000000
--- a/buildSrc/src/main/java/org/openjfx/gradle/tasks/ExecTask.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2019, 2021, Gluon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * * Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package org.openjfx.gradle.tasks;
-
-import org.gradle.api.DefaultTask;
-import org.gradle.api.GradleException;
-import org.gradle.api.Project;
-import org.gradle.api.file.FileCollection;
-import org.gradle.api.plugins.ApplicationPlugin;
-import org.gradle.api.tasks.JavaExec;
-import org.gradle.api.tasks.TaskAction;
-import org.openjfx.gradle.JavaFXModule;
-import org.openjfx.gradle.JavaFXOptions;
-import org.openjfx.gradle.JavaFXPlatform;
-
-import javax.inject.Inject;
-import java.io.File;
-import java.util.Arrays;
-import java.util.TreeSet;
-
-public class ExecTask extends DefaultTask {
- private final Project project;
- private JavaExec execTask;
-
- @Inject
- public ExecTask(Project project) {
- this.project = project;
- project.getPluginManager().withPlugin(ApplicationPlugin.APPLICATION_PLUGIN_NAME, e -> {
- execTask = (JavaExec) project.getTasks().findByName(ApplicationPlugin.TASK_RUN_NAME);
- if (execTask != null) {
- execTask.dependsOn(this);
- } else {
- throw new GradleException("Run task not found.");
- }
- });
- }
-
- @TaskAction
- public void action() {
- if (execTask != null) {
- JavaFXOptions javaFXOptions = project.getExtensions().getByType(JavaFXOptions.class);
- JavaFXModule.validateModules(javaFXOptions.getModules());
-
- var definedJavaFXModuleNames = new TreeSet<>(javaFXOptions.getModules());
- if (!definedJavaFXModuleNames.isEmpty()) {
- final FileCollection classpathWithoutJavaFXJars = execTask.getClasspath().filter(
- jar -> Arrays.stream(JavaFXModule.values()).noneMatch(javaFXModule -> jar.getName().contains(javaFXModule.getArtifactName()))
- );
- final FileCollection javaFXPlatformJars = execTask.getClasspath().filter(jar -> isJavaFXJar(jar, javaFXOptions.getPlatform()));
- execTask.setClasspath(classpathWithoutJavaFXJars.plus(javaFXPlatformJars));
- }
- } else {
- throw new GradleException("Run task not found. Please, make sure the Application plugin is applied");
- }
- }
-
- private static boolean isJavaFXJar(File jar, JavaFXPlatform platform) {
- return jar.isFile() &&
- Arrays.stream(JavaFXModule.values()).anyMatch(javaFXModule ->
- javaFXModule.compareJarFileName(platform, jar.getName()) ||
- javaFXModule.getModuleJarFileName().equals(jar.getName()));
- }
-}
diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java
index 345467d..d6fec7e 100644
--- a/src/main/java/com/sparrowwallet/sparrow/AppController.java
+++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java
@@ -471,7 +471,7 @@ public class AppController implements Initializable {
private void setPlatformApplicationMenu() {
OsType osType = OsType.getCurrent();
- if(osType == OsType.MACOS) {
+ if(osType == OsType.MACOS && Interface.get() == Interface.DESKTOP) {
MenuToolkit tk = MenuToolkit.toolkit();
MenuItem settings = new MenuItem("Settings...");
settings.setOnAction(this::openSettings);
diff --git a/src/main/java/com/sparrowwallet/sparrow/Interface.java b/src/main/java/com/sparrowwallet/sparrow/Interface.java
index ef2c73f..0dda896 100644
--- a/src/main/java/com/sparrowwallet/sparrow/Interface.java
+++ b/src/main/java/com/sparrowwallet/sparrow/Interface.java
@@ -8,13 +8,13 @@ public enum Interface {
public static Interface get() {
if(currentInterface == null) {
boolean headless = java.awt.GraphicsEnvironment.isHeadless();
- boolean monocle = "Monocle".equalsIgnoreCase(System.getProperty("glass.platform"));
+ boolean headlessPlatform = "Headless".equalsIgnoreCase(System.getProperty("glass.platform"));
- if(headless || monocle) {
+ if(headless || headlessPlatform) {
currentInterface = TERMINAL;
- if(headless && !monocle) {
- throw new UnsupportedOperationException("Headless environment detected but Monocle platform not found");
+ if(headless && !headlessPlatform) {
+ throw new UnsupportedOperationException("Headless environment detected but headless glass platform not found");
}
} else {
currentInterface = DESKTOP;
diff --git a/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java
index 9dbd5bd..7e72785 100644
--- a/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java
+++ b/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java
@@ -208,7 +208,6 @@ public class CoinTreeTable extends TreeTableView<Entry> {
return null;
}
- @SuppressWarnings("deprecation")
protected void setupColumnWidths() {
Double[] savedWidths = getSavedColumnWidths();
for(int i = 0; i < getColumns().size(); i++) {
@@ -216,8 +215,7 @@ public class CoinTreeTable extends TreeTableView<Entry> {
column.setPrefWidth(savedWidths != null && getColumns().size() == savedWidths.length ? savedWidths[i] : STANDARD_WIDTH);
}
- //TODO: Replace with TreeTableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN when JavaFX 20+ has headless support
- setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
+ setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
getColumns().getLast().widthProperty().addListener((_, _, _) -> walletTableChanged());
diff --git a/src/main/java/com/sparrowwallet/sparrow/settings/ServerAliasDialog.java b/src/main/java/com/sparrowwallet/sparrow/settings/ServerAliasDialog.java
index 5960bdd..9a7bc97 100644
--- a/src/main/java/com/sparrowwallet/sparrow/settings/ServerAliasDialog.java
+++ b/src/main/java/com/sparrowwallet/sparrow/settings/ServerAliasDialog.java
@@ -29,7 +29,6 @@ public class ServerAliasDialog extends Dialog<Server> {
private final TableView<ServerEntry> serverTable;
private final Button closeButton;
- @SuppressWarnings("deprecation")
public ServerAliasDialog(ServerType serverType) {
this.serverType = serverType;
@@ -61,7 +60,7 @@ public class ServerAliasDialog extends Dialog<Server> {
serverTable.getColumns().add(urlColumn);
serverTable.getColumns().add(aliasColumn);
serverTable.setEditable(true);
- serverTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
+ serverTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
List<Server> servers = serverType == ServerType.BITCOIN_CORE ? Config.get().getRecentCoreServers() : Config.get().getRecentElectrumServers();
List<ServerEntry> serverEntries = servers.stream().map(server -> new ServerEntry(serverType, server)).collect(Collectors.toList());
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.