155 lines
5.9 KiB
Nix
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);
|
|
};
|
|
}
|