Files
playpen/flake.nix
T

155 lines
5.9 KiB
Nix

{
description = "Playpen: vertical-tab terminal with web panes and saved layouts, built on libghostty-vt";
inputs = {
# Ghostty tracks nixpkgs-unstable to get GTK 4.20 / GNOME 49. We follow
# suit so that our zig-gobject bindings (shared with Ghostty) match the
# GObject introspection data of the GTK we link against.
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
systems = {
url = "github:nix-systems/default";
flake = false;
};
# Zig 0.16.0 is not in nixpkgs yet; libghostty-vt requires it.
zig = {
url = "github:mitchellh/zig-overlay";
inputs = {
nixpkgs.follows = "nixpkgs";
flake-compat.follows = "flake-compat";
systems.follows = "systems";
};
};
};
outputs = {
self,
nixpkgs,
zig,
systems,
...
}: let
inherit (nixpkgs) lib legacyPackages;
forAllSystems = f:
lib.genAttrs (import systems) (system: f legacyPackages.${system} system);
in {
devShells = forAllSystems (pkgs: system: {
default = pkgs.mkShell {
name = "playpen";
nativeBuildInputs = [
zig.packages.${system}."0.16.0"
pkgs.pkg-config
pkgs.gdb
# The review pane's UI is a React app built by Vite, and `zig build`
# runs that build (see build.zig) so the bundle it embeds can never be
# older than the source it came from. Nothing else here needs node.
pkgs.nodejs_22
# Used by ./shot.sh to run the app inside a throwaway headless
# compositor and screenshot it, so UI can be checked without
# touching the developer's real session.
pkgs.sway
pkgs.grim
pkgs.wtype
];
buildInputs = with pkgs; [
# GTK4 + libadwaita, the same native UI stack Ghostty uses on Linux.
gtk4
libadwaita
# Powers the web panes. The 6.0 ABI is the GTK4 build of WebKitGTK;
# the 4.x ABIs are GTK3 and would pull in a second, conflicting GTK.
webkitgtk_6_0
# TLS for the web panes. GIO has no TLS backend built in — it loads
# one as a module — so without this every https:// page fails with
# "TLS support is not available" while http:// still works.
glib-networking
# The GPU stack WebKit's web process renders through. It has to be
# this mesa and not the host's — see the shellHook below.
mesa
glib
gobject-introspection
pango
cairo
harfbuzz
gdk-pixbuf
graphene
# Windowing backends GTK links against.
wayland
libxkbcommon
libx11
# Font stack used by Pango for glyph rasterization.
fontconfig
freetype
# Icon themes so the app doesn't render missing-image icons.
adwaita-icon-theme
hicolor-icon-theme
];
shellHook = ''
# The runtime data GTK needs to find at startup: its own GSettings
# schemas and the icon themes our widgets pull symbolic icons from.
#
# These are exported under their own names, rather than only folded
# into XDG_DATA_DIRS, because `mise run install` reads them back out
# to bake into the installed launcher. The built binary already has
# an RPATH into the Nix store and runs fine outside this shell, but
# it still has to be pointed at this data or GTK aborts on a missing
# schema and falls back to broken-image icons.
export PLAYPEN_GSETTINGS_SCHEMA_DIR="${pkgs.gtk4}/share/gsettings-schemas/${pkgs.gtk4.name}/glib-2.0/schemas"
export PLAYPEN_RUNTIME_DATA_DIRS="${pkgs.gtk4}/share/gsettings-schemas/${pkgs.gtk4.name}:${pkgs.adwaita-icon-theme}/share:${pkgs.hicolor-icon-theme}/share"
# The GIO module holding the TLS backend. Same story as the schemas:
# it is found by path at runtime, so the installer bakes it in too.
export PLAYPEN_GIO_MODULE_DIR="${pkgs.glib-networking}/lib/gio/modules"
export GSETTINGS_SCHEMA_DIR="$PLAYPEN_GSETTINGS_SCHEMA_DIR"
export XDG_DATA_DIRS="$PLAYPEN_RUNTIME_DATA_DIRS:$XDG_DATA_DIRS"
export GIO_EXTRA_MODULES="$PLAYPEN_GIO_MODULE_DIR''${GIO_EXTRA_MODULES:+:$GIO_EXTRA_MODULES}"
# WebKit's web process renders through mesa, and every piece of that
# path has to come from the *same* mesa. Two things go wrong on a
# non-NixOS host if we leave it alone, and both kill the web process
# at startup with "Could not create default EGL display:
# EGL_BAD_PARAMETER", leaving web panes permanently blank:
#
# - libglvnd falls back to /usr/share/glvnd/egl_vendor.d and loads
# the *host's* mesa as the EGL vendor, while WebKit is linked
# against Nix's libgbm. A GBM device made by one mesa is rejected
# by the other.
# - Nix's libgbm looks for its backend in /run/opengl-driver/lib/gbm,
# a path that only exists on NixOS.
#
# Pointing all three at this mesa keeps the stack self-consistent.
# It still uses the real GPU through /dev/dri; this is not a
# software-rendering fallback.
export PLAYPEN_EGL_VENDOR_DIR="${pkgs.mesa}/share/glvnd/egl_vendor.d"
export PLAYPEN_DRI_DRIVERS_PATH="${pkgs.mesa}/lib/dri"
export PLAYPEN_GBM_BACKENDS_PATH="${pkgs.mesa}/lib/gbm"
export __EGL_VENDOR_LIBRARY_DIRS="$PLAYPEN_EGL_VENDOR_DIR"
export LIBGL_DRIVERS_PATH="$PLAYPEN_DRI_DRIVERS_PATH"
export GBM_BACKENDS_PATH="$PLAYPEN_GBM_BACKENDS_PATH"
'';
};
});
formatter = forAllSystems (pkgs: _: pkgs.alejandra);
};
}