Files
kst4contest/app-desktop/build.gradle.kts
T
Rsclub2_2 fe4215bce9 Remove JavaFX
The second half of Etappe 6 (61 commits). grep -rl "javafx\." over both main
source trees is empty, nothing imports javafx, neither classpath resolves it,
and org.openjfx is out of the build and the version catalog.

The finding that shaped the work: the JavaFX main window was built on every
start and never shown -- primaryStage's setScene and show were both commented
out. Most of those 11,655 lines were dead weight rather than a port. But not
all of them, and that is the trap this commit is really about: dead-looking
methods still fed live Compose sinks. They were cut at their seams instead of
deleted, and a sweep script that follows calls was written to find them,
because reading the code does not reveal them.

In order: the colour derivation frozen as checked-in test data, so the pin
survives JavaFX being removed instead of silently comparing against itself;
the live feeds lifted out of the never-shown window and given names and tests;
the dead scaffolding deleted in slices; then the lifecycle. UiDispatcher now
delivers to the AWT event dispatch thread, the ten Alerts are modal Compose
dialogs, HostServices gives way to java.awt.Desktop with the mailto/http split
JavaFX did not need, and extends Application, start(Stage), stop and launch are
gone -- main builds the runtime and a shutdown hook replaces stop().

An independent review found two deadlocks in that move, both the same failure
class, both invisible to the build: a blocking wait on the event thread for
work that can only advance on the event thread. The profile picker waited on a
latch and froze the client for good; ComposeWindowHost.close waited on
Thread.join and returned with the window still marked open, which made a
profile switch raise the dead runtime's window and leave the rebuilt profile
without its Connect button. A third came out of fixing them: a ComposeDialog
built off the event thread cannot create its GL context and never paints.

Three defects only a GUI run showed, never the build: an NPE on a deleted
field, a Compose menu still hanging on deleted MenuItems, and a category
bookkeeping field that looked dead but is read by the outgoing-message category
resolution -- deleting it would have sent messages in the wrong category.

The binding docs and the manual no longer describe a JavaFX client.
2026-10-05 22:36:01 +02:00

105 lines
4.6 KiB
Kotlin

plugins {
java
alias(libs.plugins.kotlinJvm)
alias(libs.plugins.composeCompiler)
alias(libs.plugins.composeMultiplatform)
}
kotlin {
jvmToolchain(21)
}
dependencies {
// Mirrors the compile-scope entries in pom.xml: a few test classes still live under
// src/main/java and need JUnit and Mockito on the main compile classpath.
implementation(libs.junit.jupiter.api)
implementation(libs.mockito.core.compile)
implementation(libs.jetbrains.annotations)
implementation(project(":core"))
implementation(compose.desktop.currentOs)
implementation(compose.material3)
implementation(libs.sqlite.jdbc)
implementation(libs.jlayer)
testImplementation(libs.junit.jupiter)
testImplementation(libs.mockito.core)
testImplementation(libs.mockito.junit.jupiter)
// Gradle 9 no longer adds the launcher implicitly.
testRuntimeOnly(libs.junit.platform.launcher)
}
compose.desktop {
application {
// Main forwards to Kst4ContestApplication.main. It was a workaround for
// launching a JavaFX Application subclass from the classpath; it stays because
// the packaged launchers and the AUR/Flatpak wrappers name this class.
mainClass = "kst4contest.view.Main"
nativeDistributions {
/*
* Only the formats the building machine can actually produce. Compose rejects a
* foreign one while CONFIGURING the project, not while packaging it, so a list
* naming all five made every Gradle task fail on macOS and Windows — including
* `run` and `test`, which package nothing. The build was Linux-only without
* anyone having decided that.
*/
val host = org.gradle.internal.os.OperatingSystem.current()
targetFormats(
*when {
host.isMacOsX -> arrayOf(
org.jetbrains.compose.desktop.application.dsl.TargetFormat.Dmg,
)
host.isWindows -> arrayOf(
org.jetbrains.compose.desktop.application.dsl.TargetFormat.Msi,
)
else -> arrayOf(
org.jetbrains.compose.desktop.application.dsl.TargetFormat.AppImage,
org.jetbrains.compose.desktop.application.dsl.TargetFormat.Deb,
org.jetbrains.compose.desktop.application.dsl.TargetFormat.Rpm,
)
}
)
/*
* jlink must come from JDK 21, not from whatever the Gradle JVM is.
* jdk.jsobject was removed after 21, and this machine has 26 on PATH;
* Etappe 1 hit the same wall with jpackage.
*/
javaHome = javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(21))
}.get().metadata.installationPath.asFile.absolutePath
/*
* KST4Contest and not praktiKST: this one name drives the app-image
* directory, the launcher, the .app bundle, the bundled icon file
* and -- lowercased -- the deb/rpm package name. Every packaging
* consumer already uses KST4Contest there (AppRun, the Arch and
* Flatpak wrappers, the AUR PKGBUILDs, build-signed-dmg.sh), and the
* shipped deb/rpm must keep the package identity "kst4contest" so an
* installed copy still upgrades.
*/
packageName = "KST4Contest"
packageVersion = providers.gradleProperty("composePackageVersion").get()
/*
* Kept from the former module-info.java. jdk.jsobject went with the map
* bridge: it carried netscape.javascript, and nothing imports that any
* more. jdk.unsupported stays — its justification used to be the JavaFX
* Marlin renderer, but sun.misc.Unsafe is reached by other dependencies
* too, and dropping it is a separate decision from removing JavaFX.
*/
modules(
"java.desktop", "java.net.http", "java.sql",
"jdk.crypto.ec", "jdk.net",
"jdk.xml.dom", "jdk.unsupported",
)
linux { iconFile.set(rootProject.file("packaging/icons/kst4contest.png")) }
windows { iconFile.set(rootProject.file("packaging/icons/kst4contest.ico")) }
macOS {
iconFile.set(rootProject.file("packaging/icons/kst4contest.icns"))
// Must stay de.x08.KST4Contest: build-signed-dmg.sh signs against it.
bundleID = "de.x08.KST4Contest"
}
}
}
}