Setting up Processing on Hyprland Arch Linux
What I did to install and configure Processing on an Arch Linux system that uses the Wayland server protocol (as opposed to X11) and the Hyprland tiling window manager . Those system details are relevant.
This note is definitely not a guide! It’s just what worked for me.
Note to self: this took a few tries. Processing is now in ~/processing4new. I can live with new
being appended to the directory name. Sooner or later it might cause an issue.
Update: January 21. It turns out I was following the wrong build instructions! The file at https://github.com/processing/processing4/blob/main/build/README.md starts by saying:
This folder contains files for the legacy Ant build system. This build system will be removed in the future when we’re sure we no longer need it.
That’s what gave me the hint to build with Gradle, but it didn’t occur to me that the up-to-date build instructions are at https://github.com/processing/processing4/blob/main/BUILD.md .
The significant difference between what I did and the correct approach is that I built using jdk17-openjdk when you’re supposed to use java-17-temurin. I’ve rebuilt Processing using java-17-temurin
(downloaded from the AUR. The AUR version is a bit ahead of the version recommended in the BUILD.md file).
The BUILD.md file says to set the JAVA_HOME environmental variable. I didn’t do that, but I set the system’s java to java-17-temurin with the archlinux-java utility.
The build errors I was getting with jdk17-openjdk also occur with java-17-temurin:
> Task :app:run
java.lang.reflect.InaccessibleObjectException: Unable to make field private static java.lang.String sun.awt.X11.XToolkit.awtAppClassName accessible: module java.desktop does not "opens sun.awt.X11" to unnamed module @6a522ee2
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
# ...
It seems those errors can be ignored.
The BUILD.md file says that a Processing package can be generated with ./gradlew package. On
Arch Linux, this fails with:
❯ ./gradlew package
> Task :app:packageDeb FAILED
FAILURE: Build failed with an exception.
# ...
It makes sense that building a DEB package would fail on Arch Linux.
I created a package as I did previously with:
❯ ./gradlew createDistributable
That worked.
There seems to be an expectation from the
processing.nvim plugin
and in references I’m seeing online that a processing-java package is available on the system. I’m not finding it, or seeing how to create it. What I’ve ended up with is a Processing binary that accepts a cli command. That seems to be the equivalent of what processing-java does (or used to do (?)).
Running ./Processing commands with the Processing binary I created with jdk17-openjdk worked
without issues, but always started with the error message:
pure virtual method called
terminate called without an active exception
That’s a C++ runtime error that indicates something’s trying to call an abstract virtual method that
hasn’t been implemented. That error is gone after building with the correct Java version. It’s not
clear to me what the error was affecting. ./gradlew test passes on either build. It’s nice to not
see the error message though.
I’ll update this note soon to incorporate these details.
Building Processing from source on Arch Linux
Clone the repo from https://github.com/processing/processing4 .
Install Processing dependencies
The repo’s
build/README.md file
says:
Download and install JDK 17 from https://adoptium.net/
Make sure ant is installed for your platform.
Open a Terminal window/Command Prompt/whatever and type:
cd /path/to/processing4/build
ant run
On my system the JDK version was:
❯ java --version
openjdk 25.0.1 2025-10-21
OpenJDK Runtime Environment (build 25.0.1)
OpenJDK 64-Bit Server VM (build 25.0.1, mixed mode, sharing)
I installed jdk17-openjdk with pacman:
sudo pacman -S jdk17-openjdk
Then (possibly temporarily, possibly for ever) set the system’s default Java to jdk17-openjdk
with:
sudo archlinux-java set jdk17-openjdk
I also installed ant from the Arch repo.
Building Processing
I tried building Processing by following the “detailed” instructions from the README:
cd /path/to/processing4
cd build
ant build
Running ant build failed with:
compile:
[mkdir] Created dir: /home/me/processing4/app/bin
[copy] Copying 1 file to /home/me/processing4/app/bin
[javac] Compiling 120 source files to /home/me/processing4/app/bin
[javac] /home/me/processing4/app/src/processing/app/Base.java:29: error: package org.jetbrains.annotations does not exist
[javac] import org.jetbrains.annotations.NotNull;
# ...
Then I remembered that last year I managed to build Processing using Gradle instead of ant. (Note that I’m not a Java developer. I have no idea what I’m doing with it.)
Building Processing with Gradle
From the ~/Processing4 directory, I ran:
./gradlew tasks
That listed a bunch of tasks.
I ran ./gradlew build and got a bunch of output. I wasn’t paying attention.
Then I ran ./gradlew run, a Processing window opened, but nothing happened when I attempted to run
a sketch. In the console window there were the errors:
> Task :app:run
java.lang.reflect.InaccessibleObjectException: Unable to make field private static java.lang.String sun.awt.X11.XToolkit.awtAppClassName accessible: module java.desktop does not "opens sun.awt.X11" to unnamed module @6a522ee2
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
# ...
Processing is trying to access internal AWT classes that are not normally accessible.1
The fix was to make a change to ~/processing4/app/build.gradle.kts: 2
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(),
"--add-opens", "java.desktop/sun.awt=ALL-UNNAMED", // added line
"--add-opens", "java.desktop/sun.awt.X11=ALL-UNNAMED", // added line
"--add-opens", "java.desktop/sun.java2d=ALL-UNNAMED" // added line
)
The change is the "--add-opens" flags that are after the call .toTypedArray
Processing now seemed to build and run when ./gradlew run was called.
It sort of worked a couple of times, but the UI was janky. Then it went back to its previous state of not allowing me to run sketches. Note that I wasn’t paying alot of attention to what I was doing.
Building processing so that it doesn’t have to rebuild on every call to gradlew run
Looking at the output of ./gradlew tasks, the ./gradlew createDistributable task seemed hopeful.
I ran:
❯ ./gradlew createDistributable
> Task :app:createDistributable
The distribution is written to /home/me/processing4new/app/build/compose/binaries/main/app
BUILD SUCCESSFUL in 22s
55 actionable tasks: 11 executed, 44 up-to-date
The actual executable file is in:
/home/me/processing4new/app/build/compose/binaries/main/app/Processing/bin
Running it with ./Processing opened the Processing UI, but again wouldn’t allow me to run a
sketch. It was also doing something weird with the mouse cursor. Attempting to run it with GDK_BACKEND=x11 ./Processing didn’t resolve the issue. I’m sure there were relevant log files.
Running Processing from the command line
Running ./Processing --help was helpful:
❯ ./Processing --help
pure virtual method called
terminate called without an active exception
Usage: processing [<options>] [<sketches>]... <command> [<args>]...
Start the Processing IDE
Options:
-v, --version Print version information
-h, --help Show this message and exit
Arguments:
<sketches> Sketches to open
Commands:
lsp Start the Processing Language Server
cli
contributions Manage Processing contributions
sketchbook Manage the sketchbook
sketch Manage a Processing sketch
I didn’t actually want to use the Processing editor, so I tried creating a scratch.pde file and calling:
/Processing cli --sketch=/home/me/sketchbook/scratch/ --run
Success!
Running processing sketches from Neovim
The
processing.nvim
plugin seems to be actively
maintained. The issue for my setup is that the plugin assumes that processing-java is available.
Instead of dealing with that issue, I just added an executable processing-java script to ~/bin:
#!/usr/bin/env bash
exec ~/processing4new/app/build/compose/binaries/main/app/Processing/bin/Processing cli "$@"
Calling processing-java now calls my Processing binary, with the args that are passed to the
original call. That seems fine.
Installing and configuring processing.nvim
I’m using LazyVim.
~/.config/nvim/lua/plugins/processing.lua:
return {
'sophieforrest/processing.nvim',
lazy = false,
version = "^1",
init = function()
vim.g.processing_nvim = {
highlight = {
enable = true,
},
lsp = {
cmd = {
vim.fn.expand("~/processing4new/app/build/compose/binaries/main/app/Processing/bin/Processing"),
"lsp"
},
},
}
end,
}
This is mostly just installing the plugin. The lsp section calls my Processing binary with the
lsp argument to start the LSP.
I’m not sure that anything is ever stopping the Processing LSP though. Will check on that.
Ctags
The processing.nvim plugin will generate ctags with the Processing ctags command. I installed
ctags with sudo pacman -S ctags. The command now works.
Running Processing sketches from inside Neovim
Sketches can be run with the :make command.
Getting the output of print statements into the terminal
It’s not clear to me where or if output of print statements in sketches ends up when sketches are
run with the :make command from inside Neovim. To get around that, I’m just running sketches from
the terminal:
processing-java --sketch=complex_numbers/ --run
Stopping the LSP
With my current setup, the Processing LSP is not being automatically stopped when a Processing
buffer is closed. The :LSPStop command returns the notice: Invalid servername 'processing-lsp'.
The :Processing lsp stop that’s supplied by the plugin command works though.
I think the issue here is on the Processing end and not with the processing.nvim plugin.
Processing LSP processes can be cleaned up from htop, or with something like:
alias clean-processing="pkill -f 'Processing.*lsp'"
Or just run:
pkill -f 'Processing.*lsp'
To just view all running processes:
pgrep -fa "Processing.*lsp"