Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6801baf
*:ꔫ:*Renderer Project*:ꔫ:*
catilac Oct 11, 2025
ebd4df6
Create workspaces for ffi and the renderer (#1275)
catilac Oct 14, 2025
32c31b5
Inital scaffold for libprocessing ffi.
tychedelia Oct 15, 2025
a596ad2
Remove EAP.
tychedelia Oct 15, 2025
9ae1d01
Update docs.
tychedelia Oct 15, 2025
8f2542b
Factor out gradle utils. Add flag for disabling webgpu and enforcing …
tychedelia Oct 16, 2025
0078714
Remove processing.h
tychedelia Oct 16, 2025
5662716
Set java version for all projects.
tychedelia Oct 16, 2025
7152360
Merge pull request #1287 from tychedelia/1270-ffi-scaffold
tychedelia Oct 16, 2025
33b8b52
libprocessing ffi error handling (#1293)
tychedelia Oct 17, 2025
bc5a524
Basic app lifecycle / surface creation.
tychedelia Oct 22, 2025
fa83874
Throw when not on macos.
tychedelia Oct 22, 2025
2232a0d
Merge pull request #1302 from tychedelia/1271-surface-creation
tychedelia Oct 27, 2025
89f8a65
Implement `background` method (#1308)
tychedelia Nov 10, 2025
1ee012e
Support for windows surfaces. (#1310)
tychedelia Nov 10, 2025
351737c
Implement basic rendering flow (#1322)
tychedelia Nov 20, 2025
f6eaf88
libprocessing submodule
catilac Nov 21, 2025
6eddaf4
--recursive when cloning repo
catilac Nov 21, 2025
dc359d1
Enable submodule checkout in Gradle workflow
Stefterv Nov 24, 2025
39cca3d
Enable submodules in checkout steps
Stefterv Nov 24, 2025
8400db5
Wayland support with new WebGPU renderer
catilac Nov 24, 2025
b40adac
Merge pull request #1340 from catilac/libprocessing-submodule
tychedelia Nov 24, 2025
01f8923
Merge branch 'the-wgpu-moment' into 1305-wayland
catilac Nov 24, 2025
2b9f115
Merge pull request #1343 from catilac/1305-wayland
tychedelia Nov 25, 2025
eee55b5
Gradle fixes from libprocessing refactor. (#1346)
tychedelia Nov 26, 2025
408d542
Updates from libprocessing. (#1392)
tychedelia Jan 28, 2026
4127dc0
Updates from libprocessing.
tychedelia May 2, 2026
fef550b
Merge remote-tracking branch 'origin/main' into the-wgpu-moment
tychedelia May 2, 2026
67ac864
Fixes for compat with main 17.
tychedelia May 3, 2026
079b879
Fixup docs.
tychedelia May 3, 2026
601af33
Upgrade to jdk-25.
tychedelia May 3, 2026
4b3a06a
Upgrade to jdk-25.
tychedelia May 3, 2026
bc8df0b
Materials, lights, input event forwarding, ellipse fix.
tychedelia May 5, 2026
7fedbcf
Get the gradle sketch runner working locally.
tychedelia May 5, 2026
70ba638
Conditionally execute webgpu tests
catilac May 13, 2026
1aa9610
Merge branch 'main' into the-wgpu-moment
catilac Jul 3, 2026
c31caca
ProcessingLibraryPlugin JVM Toggle update
catilac Jul 4, 2026
787ff56
4.5.5 in gradle.properties
catilac Jul 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ generated/
/java/gradle/build
/core/examples/build
/java/gradle/example/.processing

libprocessing/ffi/include/*
/app/windows/obj
/java/android/example/build
/java/android/example/.processing
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "libprocessing"]
path = libprocessing
url = https://github.com/processing/libprocessing
79 changes: 61 additions & 18 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ _**Note:** A paid subscription is **not** required. Everything needed to build a
> [!TIP]
> If you encounter any issues with this process, Read the [Troubleshooting and Setup Tips for IntelliJ IDEA](#troubleshooting-and-setup-tips-intellij-idea)

1. Clone the Processing4 repository to your machine locally
1. Open the cloned repository in IntelliJ IDEA CE
1. When prompted, select **Trust Project**. You can preview the project in Safe Mode but you won't be able to build Processing.
1. IntelliJ may ask if you want to load Gradle project. If you allow this, make sure you are using JDK version 17.
1. In the main menu, go to File > Project Structure > Project Settings > Project.
1. In the SDK Dropdown option, select a JDK version 17 or Download the jdk
1. Click the green Run Icon in the top right of the window. This is also where you can find the option to debug Processing.
1. Logs can be found in the `Build` or `Debug` pane on the bottom left of the window


## VSCode
1. Clone the Processing4 repository to your machine locally
1. Open the cloned repository in VScode
Expand All @@ -46,7 +56,7 @@ If you don't have them installed, you will need to install [Git](https://git-scm

1. **Clone the repository:**
```bash
git clone https://github.com/processing/processing4.git
git clone --recursive https://github.com/processing/processing4.git
cd processing4
```

Expand All @@ -58,8 +68,49 @@ If you don't have them installed, you will need to install [Git](https://git-scm
- [macOS (Apple Silicon)](https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.pkg)
- [Other platforms](https://adoptium.net/temurin/releases/?package=jdk&version=17&os=any&arch=any)

### macOS:
```bash
brew install --cask temurin@17
````

### Windows (using winget):
```bash
winget install --id=EclipseAdoptium.Temurin.17.JDK -e
```

### SDKMAN!

[SDKMAN!](https://sdkman.io/) is a useful tool for developers working on multiple versions of the JVM.

## WebGPU Support (Optional)

To build Processing with the experimental WebGPU renderer, you need JDK 25, Rust, and jextract.

### Install Temurin JDK 25

```bash
brew install --cask temurin@25 # macOS
```

### Install `jextract`

`jextract` generates Java bindings from C header files.
You can download it [here](https://jdk.java.net/jextract/) or install it using SDKMAN!:

```bash
sdk install jextract
````

### Build with WebGPU

```bash
./gradlew build -PenableWebGPU=true
```

3. **Set the `JAVA_HOME` environment variable:**

It may be necessary to set the `JAVA_HOME` environment variable to point to your Temurin JDK installation.

```bash
export JAVA_HOME=/path/to/temurin/jdk-17.0.15+6/
```
Expand Down Expand Up @@ -142,32 +193,24 @@ If you’re building Processing using IntelliJ IDEA and something’s not workin

### Use the Correct JDK (temurin-17)

Make sure IntelliJ is using **temurin-17**. Some users have reported issues with other distributions.

#### 1. Set the Project SDK
Make sure IntelliJ is using **temurin-17**, not another version. If building with WebGPU (`-PenableWebGPU=true`), use **temurin-25** instead.

1. Go to **`File > Project Structure > Project`**
1. Set the **`Project SDK`** to **`temurin-17`**
1. Go to **File > Project Structure > Project**
2. Set the **Project SDK** to: `temurin-17 java version "17.0.15"`

![JDK Selection](.github/media/troubleshooting-Intellij-setting-djk-version-manually.png)

If Temurin 17 is not on the list, you should install it first:

1. Select the **`Download JDK...`** option from the menu
1. Pick **Version**: **`17`**, **Vendor**: **`Eclipse Temurin (AdoptOpenJDK HotSpot)`**
If it is not already installed, you can download it by:
1. Clicking the SDK input field and then selecting the `Download JDK...` option from the menu
2. Select Version: `17`, Vendor: `Eclipse Temurin (AdoptOpenJDK HotSpot)`

<img width="400" alt="JDK Download" src="https://github.com/user-attachments/assets/503a03a4-3e53-4406-9641-2c93e4b45d51" />

#### 2. Set the Gradle JVM

Make sure Gradle also uses Temurin 17:

1. Go to **`Settings > Build, Execution, Deployment > Build Tools > Gradle`**
1. Set **`Gradle JVM`** to **`temurin-17`**
![JDK Download](.github/media/troubleshooting-Intellij-download-jdk.png)

_Note: the exact path in settings may vary depending on your version of IntelliJ._
Now go back to your main window and
1. Click the green Run Icon in the top right of the window.

<img width="800" alt="Gradle JVM" src="https://github.com/user-attachments/assets/ba620114-e663-4887-89e9-8f26fbfefbb2" />

### “Duplicate content roots detected”

Expand Down
48 changes: 29 additions & 19 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,17 @@ compose.desktop {
application {
mainClass = "processing.app.ProcessingKt"

jvmArgs(*listOf(
Pair("processing.version", rootProject.version),
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
Pair("processing.contributions.source", "https://contributions.processing.org/contribs"),
Pair("processing.download.page", "https://processing.org/download/"),
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
Pair("processing.tutorials", "https://processing.org/tutorials/"),
).map { "-D${it.first}=${it.second}" }.toTypedArray())
jvmArgs(
"--enable-native-access=ALL-UNNAMED", // Required for Java 25 native library access
*listOf(
Pair("processing.version", rootProject.version),
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
Pair("processing.contributions.source", "https://contributions.processing.org/contribs"),
Pair("processing.download.page", "https://processing.org/download/"),
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
Pair("processing.tutorials", "https://processing.org/tutorials/"),
).map { "-D${it.first}=${it.second}" }.toTypedArray()
)

nativeDistributions{
modules("jdk.jdi", "java.compiler", "jdk.accessibility", "jdk.zipfs", "java.management.rmi", "java.scripting", "jdk.httpserver")
Expand Down Expand Up @@ -140,7 +143,6 @@ dependencies {
}

tasks.test {
systemProperty("java.awt.headless", "true")
useJUnitPlatform()
workingDir = file("build/test")
workingDir.mkdirs()
Expand Down Expand Up @@ -360,12 +362,12 @@ tasks.register<Zip>("zipDistributable"){
dependsOn("createDistributable", "setExecutablePermissions")
group = "compose desktop"

val dir = provider { distributable().destinationDir.get() }
val packageName = provider { distributable().packageName.get() }
val dir = distributable().destinationDir.get()
val packageName = distributable().packageName.get()

from(dir){ eachFile{ permissions{ unix("755") } } }
archiveBaseName.set(packageName)
destinationDirectory.set(layout.dir(provider { dir.get().file("../").asFile }))
destinationDirectory.set(dir.file("../").asFile)
}

afterEvaluate{
Expand Down Expand Up @@ -431,12 +433,19 @@ tasks.register<Copy>("includeJavaMode") {
from(java.configurations.runtimeClasspath)
into(composeResources("modes/java/mode"))
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
dirPermissions { unix("rwx------") }
}
val enableWebGPU = findProperty("enableWebGPU")?.toString()?.toBoolean() ?: false

tasks.register<Copy>("includeJdk") {
from(Jvm.current().javaHome.absolutePath)
val jdkVersion = if (enableWebGPU) 25 else 17
val jdkHome = project.the<JavaToolchainService>().launcherFor {
languageVersion.set(JavaLanguageVersion.of(jdkVersion))
}.map { it.metadata.installationPath.asFile }

from(jdkHome)
destinationDir = composeResources("jdk").get().asFile

dirPermissions { unix("rwx------") }
fileTree(destinationDir).files.forEach { file ->
file.setWritable(true, false)
file.setReadable(true, false)
Expand Down Expand Up @@ -517,15 +526,14 @@ tasks.register("includeProcessingResources"){
finalizedBy("signResources")
}

tasks.register("signResources"){
tasks.register("signResources") {
onlyIf {
OperatingSystem.current().isMacOsX
&&
compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
}
group = "compose desktop"
val resourcesPath = composeResources("")
val entitlements = file("macos/entitlements.plist").absolutePath

// find jars in the resources directory
val jars = mutableListOf<File>()
Expand Down Expand Up @@ -563,8 +571,11 @@ tasks.register("signResources"){
exclude("*.jar")
exclude("*.so")
exclude("*.dll")
}.forEach{ file ->
Runtime.getRuntime().exec(arrayOf("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--entitlements", entitlements, "--sign", "Developer ID Application", file.absolutePath))
}.forEach{ f ->
ProcessBuilder("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--sign", "Developer ID Application", f.absolutePath)
.inheritIO()
.start()
.waitFor()
}
jars.forEach { file ->
FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos ->
Expand Down Expand Up @@ -615,7 +626,6 @@ tasks.register<Exec>("signApp"){
"--force",
"--deep",
"--options=runtime",
"--entitlements", file("macos/entitlements.plist").absolutePath,
"--sign", "Developer ID Application",
app)
}
Expand Down
29 changes: 29 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,35 @@ plugins {
// Can be deleted after the migration to Gradle is complete
layout.buildDirectory = file(".build")

val enableWebGPU = findProperty("enableWebGPU")?.toString()?.toBoolean() ?: false
val javaVersion = if (enableWebGPU) "25" else "17"
val kotlinJvmTarget = if (enableWebGPU) {
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_25
} else {
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}

allprojects {
tasks.withType<JavaCompile>().configureEach {
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
compilerOptions {
jvmTarget.set(kotlinJvmTarget)
}
}

plugins.withType<JavaPlugin> {
extensions.configure<JavaPluginExtension> {
toolchain {
languageVersion.set(JavaLanguageVersion.of(javaVersion.toInt()))
}
}
}
}

// Configure the dependencyUpdates task
tasks {
dependencyUpdates {
Expand Down
7 changes: 7 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
`kotlin-dsl`
}

repositories {
mavenCentral()
}
56 changes: 56 additions & 0 deletions buildSrc/src/main/kotlin/processing/gradle/CargoBuildTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package processing.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.process.ExecOperations
import javax.inject.Inject

abstract class CargoBuildTask : DefaultTask() {

@get:Inject
abstract val execOperations: ExecOperations

@get:InputDirectory
abstract val cargoWorkspaceDir: DirectoryProperty

@get:Input
abstract val manifestPath: Property<String>

@get:Input
abstract val release: Property<Boolean>

@get:Input
abstract val cargoPath: Property<String>

@get:OutputFile
abstract val outputLibrary: RegularFileProperty

init {
group = "rust"
description = "Builds Rust library using cargo"

// release by default
release.convention(true)
}

@TaskAction
fun build() {
val buildType = if (release.get()) "release" else "debug"
logger.lifecycle("Building Rust library ($buildType mode)...")

val args = mutableListOf("build")
if (release.get()) {
args.add("--release")
}
args.add("--manifest-path")
args.add(manifestPath.get())

execOperations.exec {
workingDir = cargoWorkspaceDir.get().asFile
commandLine = listOf(cargoPath.get()) + args
}
}
}
38 changes: 38 additions & 0 deletions buildSrc/src/main/kotlin/processing/gradle/CargoCleanTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package processing.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.process.ExecOperations
import javax.inject.Inject

abstract class CargoCleanTask : DefaultTask() {

@get:Inject
abstract val execOperations: ExecOperations

@get:InputDirectory
abstract val cargoWorkspaceDir: DirectoryProperty

@get:Input
abstract val manifestPath: Property<String>

@get:Input
abstract val cargoPath: Property<String>

init {
group = "rust"
description = "Cleans Rust build artifacts"
}

@TaskAction
fun clean() {
logger.lifecycle("Cleaning Rust build artifacts...")

execOperations.exec {
workingDir = cargoWorkspaceDir.get().asFile
commandLine(cargoPath.get(), "clean", "--manifest-path", manifestPath.get())
}
}
}
Loading
Loading