Zalgorithm

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"

  1. Claude. ↩︎

  2. Claude. ↩︎