Files
amethyst/scripts/add-deb-wayland-deps.sh
Claude 26318792a3 feat(desktop): draw natively on Wayland in every Linux release
The Linux packages ran on X11 only: the bundled Temurin runtime's AWT has
no Wayland toolkit, and the Flatpak required --socket=x11. On a Wayland
session the app needed XWayland, and with no Xwayland it could not start.

- Linux packages now bundle the JetBrains Runtime 21, whose AWT has a
  Wayland toolkit (WLToolkit). CI's Linux legs install it with
  actions/setup-java (distribution: jetbrains), and release CI fails a
  Linux build whose runtime lacks libawt_wlawt.so. macOS and Windows keep
  Temurin.
- WaylandDisplay picks WLToolkit in main() when $WAYLAND_DISPLAY names a
  live socket and the runtime has it, and sets the Wayland app_id
  ($FLATPAK_ID, else "Amethyst", which the desktop entries already match).
  AMETHYST_X11=1 keeps a Wayland session on XWayland.
- Compose's Window can't draw under WLToolkit (Skiko's surface locks the
  window through JAWT for an X11 handle), so AppWindow hosts the main
  window and the fullscreen video window in a Swing frame with a
  ComposePanel that draws through Swing on Skiko's CPU renderer, carrying
  the WindowState both ways, the close request, window-wide shortcuts and
  the crash window. On X11, macOS and Windows it is Compose's Window, as
  before. The crash dialog follows the same split.
- JBR's Wayland toolkit detaches every window from a shutdown hook off
  the event thread, which Compose rejects: each logout or kill left a
  crash report. The Wayland frames skip that teardown off the event
  thread.
- Flatpak: --socket=wayland + --socket=fallback-x11 instead of x11.
- .rpm requires libwayland-client, libwayland-cursor and libxkbcommon;
  scripts/add-deb-wayland-deps.sh adds libxkbcommon0 (opened with dlopen)
  to the .deb.
- Compose marks its jlink/jpackage tasks' JDK @Internal, so the build
  cache restored a Temurin runtime image into a JBR build. The JDK's
  release file is now a task input.
- scripts/wayland-smoke-test.sh starts a packaged app on a headless sway
  with Xwayland off and passes only on a native Wayland window; the PR
  .deb smoke test runs it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEcMZXsXFEWpfxgSMAgFKq
2026-10-13 03:43:41 +00:00

59 lines
2.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Ensure a jpackage-built desktop .deb declares libxkbcommon0, which the
# bundled JetBrains Runtime loads to read the keyboard on Wayland.
#
# Why this is needed: the Linux packages bundle the JetBrains Runtime so the
# app can draw natively on Wayland (WLToolkit, lib/runtime/lib/libawt_wlawt.so;
# see desktopApp/.../platform/WaylandDisplay.kt). jpackage's dpkg-shlibdeps
# pass picks up what that library links (libwayland-client0,
# libwayland-cursor0), but libxkbcommon is opened with dlopen at runtime, so it
# never makes it into Depends. Every Wayland desktop already has it (GTK and
# the compositors depend on it); a minimal install might not, and then keys
# don't reach the app.
#
# Same approach as scripts/add-deb-libegl-dep.sh: rewrite the .deb after the fact.
#
# Usage: add-deb-wayland-deps.sh <path-to-deb> [<path-to-deb> ...]
set -euo pipefail
source "$(dirname "${BASH_SOURCE[0]}")/deb-control.sh"
add_libxkbcommon() {
local control="$1"
if grep -qE '(^| )libxkbcommon0( |,|$)' "$control"; then
return
fi
sed -i -E 's/^(Depends: .*[^,[:space:]])[[:space:]]*$/\1, libxkbcommon0/' "$control"
}
# An unmatched glob reaches us as the literal pattern: fail rather than ship a .deb without the dep.
if [[ $# -eq 0 ]]; then
echo "error: no .deb given" >&2
exit 1
fi
for deb in "$@"; do
if [[ ! -f "$deb" ]]; then
echo "error: not a file: $deb" >&2
exit 1
fi
# Only a runtime with the Wayland toolkit needs it (a .deb built on a stock JDK has none).
# The listing is captured first: `grep -q` on a pipe can exit before dpkg-deb finishes, and
# pipefail would read that SIGPIPE as no match.
listing="$(dpkg-deb -c "$deb")"
if ! grep -q '/libawt_wlawt\.so$' <<< "$listing"; then
echo "No Wayland toolkit in the bundled runtime, leaving as-is: $deb"
continue
fi
deb_edit_control "$deb" add_libxkbcommon
if [[ $DEB_CONTROL_CHANGED -eq 1 ]]; then
echo "Added libxkbcommon0 dep: $deb"
else
echo "libxkbcommon0 already in Depends, leaving as-is: $deb"
fi
done