From fd672f36f78d169ff7e6f78039529886bf8aa1a6 Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Wed, 3 Jun 2026 11:53:43 +0200 Subject: [PATCH] fix cursor bug, only use java if daemon is not available --- flake.nix | 1 + .../jprototerm/GhosttyTerminalRenderer.java | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index bfa08b4..6570bbf 100644 --- a/flake.nix +++ b/flake.nix @@ -122,6 +122,7 @@ | sha256sum | cut -c1-16).jsa" makeWrapper "${pkgs.jdk25}/bin/java" "$out/bin/jprototerm" \ + --run 'if [ "$#" -eq 0 ]; then if [ -n "''${XDG_RUNTIME_DIR:-}" ]; then jprototermSock="$XDG_RUNTIME_DIR/jprototerm/daemon.sock"; else jprototermSock="/tmp/jprototerm-''${USER:-user}/daemon.sock"; fi; if [ -S "$jprototermSock" ] && printf "%s\n" "$(pwd)" | ${pkgs.socat}/bin/socat - UNIX-CONNECT:"$jprototermSock" >/dev/null 2>&1; then exit 0; fi; fi' \ --run 'export JPROTOTERM_HOST_LD_LIBRARY_PATH="''${LD_LIBRARY_PATH:-}"' \ --run 'cdsDir="''${XDG_CACHE_HOME:-$HOME/.cache}/jprototerm"; mkdir -p "$cdsDir"' \ --add-flags "-XX:+AutoCreateSharedArchive" \ diff --git a/src/main/java/com/gregor/jprototerm/GhosttyTerminalRenderer.java b/src/main/java/com/gregor/jprototerm/GhosttyTerminalRenderer.java index 940d42c..bd45e48 100644 --- a/src/main/java/com/gregor/jprototerm/GhosttyTerminalRenderer.java +++ b/src/main/java/com/gregor/jprototerm/GhosttyTerminalRenderer.java @@ -104,8 +104,15 @@ final class GhosttyTerminalRenderer extends TerminalRenderer { software.paintFullOrShifted(gc, target.snapshotFull(), px, py, width, height, active); } else if (dirty == DIRTY_PARTIAL) { software.paintDirty(gc, target, snapshot, px, py, width, height, active); + } else if (software.cursorChanged(snapshot)) { + // dirty == FALSE means no cell content changed, but the cursor can still have moved, + // changed style, or toggled visibility on its own (e.g. plain cursor-left/right, or the + // hide/redraw/show dance fish does around a line edit). No row was marshalled, so diff + // against the full snapshot: it repaints just the old and new cursor rows and redraws + // the cursor. Without this the old cursor is left erased and the new one never drawn. + software.paintFullOrShifted(gc, target.snapshotFull(), px, py, width, height, active); } - // dirty == FALSE: nothing visible changed. + // dirty == FALSE with an unchanged cursor: nothing visible changed. gc.restore(); kittyImageNodes = List.of(); } @@ -616,6 +623,12 @@ final class GhosttyTerminalRenderer extends TerminalRenderer { gc.drawImage(image, px, py); } + // Whether the cursor differs from what we last drew (position, style or visibility). Used to + // catch cursor-only updates that arrive with a FALSE global dirty flag. + private boolean cursorChanged(RenderStateSnapshot snapshot) { + return !CursorState.from(snapshot).equals(lastCursor); + } + private boolean canDiff(RenderStateSnapshot snapshot) { return rowHashes.length == snapshot.rows() && snapshot.renderRows().size() == snapshot.rows(); }