The fullRowRepaint toggle existed only to bisect the black-bar repaint artifact, which is now fixed, so drop it. Document the two remaining render-debug flags (profile, debugRepaint) in the README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
154 lines
4.8 KiB
Markdown
154 lines
4.8 KiB
Markdown
# jprototerm
|
|
|
|
JavaFX canvas terminal prototype using `jlibghostty` for terminal emulation and Nix for
|
|
the build environment. It builds a plain JavaFX application (JDK 25, JavaFX 25 via Gradle)
|
|
packaged as a Nix derivation — no GraalVM/GluonFX native image. It supports tiled and
|
|
floating panes and tabs.
|
|
|
|
> [!CAUTION]
|
|
> `nix profile add` has only been tested on **Debian with the proprietary NVIDIA driver**.
|
|
> The runtime GL shim hardcodes Debian's `/lib/x86_64-linux-gnu` driver paths and selects
|
|
> the NVIDIA GLX/EGL vendor, so it likely won't work yet on other distros, Wayland-only
|
|
> setups, or Mesa/AMD/Intel GPUs. I'm happy to accept pull requests that broaden host
|
|
> support.
|
|
|
|
## Build
|
|
|
|
```sh
|
|
nix build
|
|
./result/bin/jprototerm
|
|
```
|
|
|
|
Install it into a profile (see the caution above on host support):
|
|
|
|
```sh
|
|
nix profile add .
|
|
jprototerm
|
|
```
|
|
|
|
Or install straight from the remote — note the `git+https://` scheme (a bare `https://`
|
|
URL is treated as a tarball, not a git repo):
|
|
|
|
```sh
|
|
nix profile add git+https://gitea.gregorlohaus.com/gregor/jprototerm
|
|
```
|
|
|
|
Add `?ref=<branch-or-tag>` to pin a revision. The target machine needs Nix with the
|
|
`nix-command` and `flakes` features enabled and network access — the build fetches the
|
|
`jlibghostty`/`ghostty` flake inputs plus the JDK and Gradle from the binary caches.
|
|
|
|
The flake bundles everything the app needs — the JDK 25 runtime, the Maven JavaFX modules
|
|
and their native libraries, and the gtk/glib/freetype/X11 libraries they load — **except**
|
|
the system OpenGL/graphics drivers. `libGL` is supplied by the host at runtime through a GL
|
|
shim in the launcher wrapper, so the same closure runs against NixOS, Mesa, or vendor
|
|
(e.g. NVIDIA) GPU drivers.
|
|
|
|
Gradle dependencies are vendored in `deps.json` for the pure Nix sandbox. Regenerate it
|
|
after changing dependencies in `build.gradle` (the update script writes `deps.json` in the
|
|
current directory):
|
|
|
|
```sh
|
|
$(nix build .#gradleDepsUpdateScript --no-link --print-out-paths)
|
|
```
|
|
|
|
For development:
|
|
|
|
```sh
|
|
nix develop
|
|
gradle run
|
|
```
|
|
|
|
The Gradle project is the source of truth for the JavaFX build.
|
|
|
|
## Config
|
|
|
|
Configuration is read from:
|
|
|
|
```text
|
|
$XDG_CONFIG_HOME/jprototerm/config.toml
|
|
```
|
|
|
|
If `XDG_CONFIG_HOME` is unset, the fallback is:
|
|
|
|
```text
|
|
$HOME/.config/jprototerm/config.toml
|
|
```
|
|
|
|
If no config file exists, jprototerm writes the default config on startup.
|
|
|
|
Example, also available in `config.example.toml`:
|
|
|
|
```toml
|
|
[terminal]
|
|
columns = 100
|
|
rows = 30
|
|
shell = "/bin/bash"
|
|
font_family = "JetBrainsMono Nerd Font"
|
|
font_size = 15
|
|
|
|
[window]
|
|
width = 1200
|
|
height = 760
|
|
|
|
[kitty_graphics]
|
|
enabled = true
|
|
|
|
[scrollback]
|
|
editor_command = "vi {file}"
|
|
|
|
[env.override]
|
|
ZELLIJ_SESSION_NAME = ""
|
|
|
|
[keybindings]
|
|
navigate_left = "ALT+H"
|
|
navigate_down = "ALT+J"
|
|
navigate_up = "ALT+K"
|
|
navigate_right = "ALT+L"
|
|
toggle_floating = "ALT+F"
|
|
new_pane = "ALT+N"
|
|
close_pane = "ALT+X"
|
|
new_tab = "ALT+A"
|
|
previous_tab = "ALT+SHIFT+H"
|
|
next_tab = "ALT+SHIFT+L"
|
|
open_font_selector = "ALT+T"
|
|
open_scrollback = "ALT+S"
|
|
```
|
|
|
|
## Defaults
|
|
|
|
- `Alt+h/j/k/l`: navigate panes
|
|
- `Alt+n`: new pane — a floating pane when floating panes are shown, otherwise a new tiled
|
|
pane (tiled panes are split equally across the width)
|
|
- `Alt+f`: show or hide all floating panes
|
|
- `Alt+x`: close the active pane; closing a tab's last pane closes the tab, and closing the
|
|
last pane of the last tab quits
|
|
- `Alt+a`: new tab
|
|
- `Alt+Shift+h` / `Alt+Shift+l`: previous / next tab
|
|
- `Alt+t`: open the font selector
|
|
- `Alt+s`: open the active pane scrollback in `$EDITOR`
|
|
- Font default: `JetBrainsMono Nerd Font`
|
|
- Kitty graphics protocol parsing is enabled by default
|
|
|
|
Each tab has its own stack of tiled and floating panes; only the active tab is rendered. A
|
|
thin tab bar appears at the top when more than one tab is open. Closing the last tiled pane
|
|
while floating panes exist promotes the most recently active floating pane to a tiled pane.
|
|
|
|
## Diagnostics
|
|
|
|
Two render-debugging flags are off by default and add no overhead unless enabled. Pass them
|
|
as JVM system properties (each also has an environment-variable equivalent). With the
|
|
packaged binary the JVM picks them up from `JDK_JAVA_OPTIONS`:
|
|
|
|
```sh
|
|
JDK_JAVA_OPTIONS="-Djprototerm.profile=true" ./result/bin/jprototerm
|
|
```
|
|
|
|
- `-Djprototerm.profile=true` (or `JPROTOTERM_PROFILE=1`): print a `[render-profile]` line to
|
|
stderr every N renders with the per-frame cost of each render stage — `snapshot` (terminal
|
|
state marshalling), `fingerprint` (change detection), `draw` (canvas painting), and the
|
|
`frame-total`. Set `-Djprototerm.profile.frames=<N>` to change the dump interval (default
|
|
120).
|
|
- `-Djprototerm.debugRepaint=true` (or `JPROTOTERM_DEBUG_REPAINT=1`): paint each per-column
|
|
repaint run's cleared span red instead of clearing it. Repainted regions flash red, so you
|
|
can see exactly which cells are being redrawn each frame.
|