GtkGLArea had numerous downsides that forced us to invent unsightly
hacks in our renderer to work around them, most chiefly the fact that it
holds its own GdkGLContext on the main thread (GL contexts are not at
all thread-safe), forcing us to keep our GL calls on the main thread. It
also does not interact well with triple-buffering and initialization is
forced to be this sort of deferred song-and-dance since we need to wait
for the GLArea to initialize its GL context before we can initialize the
renderer, the core surface, and then most things in the GTK surface.
We instead invent our own custom widget named RenderSurface that takes
simple DMABUFs and displays them. The task of obtaining a GL context
falls to manual EGL bindings, since we also need EGL to export OpenGL
textures into DMABUFs. We keep the EGL context solely on the render
thread meaning that the main thread never concerns itself with rendering
except when being notified that the renderer has pushed a new frame.
What makes this extra significant is that now the entire GTK apprt no
longer depends on OpenGL in any way, shape or form. As long as it is
being fed DMABUFs, it can render from whichever graphics API you want.
This means we can add more backends based on OpenGL ES or more likely
Vulkan rather painlessly in the future.
**AI disclosure**: I came up with the idea and let Pi implement most of
the nitty-gritty details around EGL, as well as replumbing the renderer
and cleaning up all the GTK-specific workarounds there. I then carefully
vetted every line of code and spent roughly as much time reviewing as
coding. Most of the documentation and all commit messages are in my own
words.
Bumps
[c-hive/gha-remove-artifacts](https://github.com/c-hive/gha-remove-artifacts)
from 1.4.0 to 1.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/c-hive/gha-remove-artifacts/releases">c-hive/gha-remove-artifacts's
releases</a>.</em></p>
<blockquote>
<h2>v1.8.0</h2>
<p>Enhancements:</p>
<ul>
<li>New <code>skip-recent-commits</code> input keeps every artifact of
the N most recent commits, regardless of how many artifacts each commit
produced. Applied before <code>skip-recent</code>, so the two can be
combined. Fixes <a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/28">#28</a></li>
<li><code>GITHUB_TOKEN</code> can now be set on both <code>env:</code>
and <code>with:</code> (for example when it is exported for all steps)
without the action failing. The input takes precedence. Fixes <a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/48">#48</a></li>
</ul>
<h2>v1.7.0</h2>
<p>Enhancements:</p>
<ul>
<li>New <code>dry-run</code> input: logs which artifacts would be
removed without deleting anything.</li>
<li>Stricter input validation. <code>age</code> now rejects fractional
amounts and units that are not durations (for example <code>30 D</code>,
which moment silently treated as zero); <code>skip-recent</code> and
<code>max-retries</code> must be non-negative integers. Previously such
values could make every artifact eligible for deletion.</li>
<li>Artifacts without commit information are reported separately from
tagged ones when <code>skip-tags</code> is on.</li>
</ul>
<p>Maintenance:</p>
<ul>
<li>Rewritten in TypeScript under <code>src/</code>, bundled with
esbuild</li>
<li>Unit tests for input parsing and the cleanup plan, plus end-to-end
tests against a mock GitHub API covering deletion, rate limit retries
and failure handling</li>
<li>CI split into lint, typecheck, test, build and run jobs</li>
<li>Dropped dependencies: yn, dotenv-safe, cross-env,
eslint-plugin-import</li>
</ul>
<h2>v1.6.0</h2>
<p>Enhancements:</p>
<ul>
<li>Artifacts are now listed repo-wide instead of per workflow run. This
cuts API requests by roughly two orders of magnitude and removes the
hardcoded 90-day window, so artifacts on repositories with longer
retention are now cleaned up too. Fixes <a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/62">#62</a></li>
<li>A failed deletion no longer aborts the run: remaining artifacts are
still processed and the action fails at the end with a count.</li>
<li>With <code>skip-tags</code>, artifacts without commit information
are kept rather than deleted.</li>
<li>The log ends with a summary of removed and skipped artifacts. Fixes
<a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/21">#21</a></li>
</ul>
<p>Maintenance:</p>
<ul>
<li>CI checks that <code>dist/</code> matches the source instead of
auto-committing it</li>
<li>Removed CodeQL workflow, pre-commit hooks and
eslint-plugin-import</li>
<li>Dependency purposes documented in <code>package.json</code></li>
</ul>
<h2>v1.5.0</h2>
<p>Enhancements:</p>
<ul>
<li>New <code>max-retries</code> input caps how often a rate-limited
request is retried before the action fails. <strong>Default: 5.</strong>
Previously requests were retried indefinitely; set a larger value to
keep the old behaviour. Fixes <a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/36">#36</a>,
<a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/49">#49</a>,
<a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/51">#51</a></li>
<li>Action runtime updated to Node 24 (<a
href="https://redirect.github.com/c-hive/gha-remove-artifacts/issues/63">#63</a>)</li>
</ul>
<p>Maintenance:</p>
<ul>
<li>All dependencies upgraded (<code>@actions/core</code> 3,
<code>@octokit/action</code> 8, <code>@octokit/plugin-throttling</code>
11, moment 2.30). <code>pnpm audit</code> reports no known
vulnerabilities.</li>
<li>Source converted to ESM, bundled with <code>@vercel/ncc</code></li>
<li>Tooling: pnpm, ESLint 10, Prettier 3, CI on Node 24</li>
<li>Docs: <code>action.yml</code> description, updated retention docs
link</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="62c2fbea93"><code>62c2fbe</code></a>
Bump version to 1.8.0</li>
<li><a
href="449a616233"><code>449a616</code></a>
Add skip-recent-commits input and accept GITHUB_TOKEN from env and
input</li>
<li><a
href="4bff15786b"><code>4bff157</code></a>
Bump version to 1.7.0</li>
<li><a
href="a52e55eb4f"><code>a52e55e</code></a>
Add end-to-end tests against a mock GitHub API</li>
<li><a
href="03f14e2351"><code>03f14e2</code></a>
Simplify config parsing, logging and tsconfig</li>
<li><a
href="04de7b0694"><code>04de7b0</code></a>
Address review findings on the TypeScript rewrite</li>
<li><a
href="8b74b1b6fc"><code>8b74b1b</code></a>
Rewrite in TypeScript, add tests, merge CI workflows</li>
<li><a
href="73aaf4a5bf"><code>73aaf4a</code></a>
Bump version to 1.6.0</li>
<li><a
href="c4da97c8ee"><code>c4da97c</code></a>
Ignore CLAUDE.local.md</li>
<li><a
href="614c11c542"><code>614c11c</code></a>
Describe each dependency in package.json</li>
<li>Additional commits viewable in <a
href="44fc7acaf1...62c2fbea93">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Bumps
[flatpak/flatpak-github-actions/flatpak-builder](https://github.com/flatpak/flatpak-github-actions)
from 6.7 to 6.8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/flatpak/flatpak-github-actions/releases">flatpak/flatpak-github-actions/flatpak-builder's
releases</a>.</em></p>
<blockquote>
<h2>v6.8</h2>
<ul>
<li>Add saveCache flag</li>
<li>Add ability to override artifact name</li>
<li>Add buildDebugBundle flag</li>
<li>Update tests, documentation and dependencies</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7932741660"><code>7932741</code></a>
Update all dependencies and regenerate dist</li>
<li><a
href="09e3d61868"><code>09e3d61</code></a>
readme: Don't specify setting cache key to github.sha (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/261">#261</a>)</li>
<li><a
href="23e622281a"><code>23e6222</code></a>
Update runtime versions and docker images to latest</li>
<li><a
href="a3ab43f581"><code>a3ab43f</code></a>
flatpak-builder: Add saveCache flag</li>
<li><a
href="8e357b1556"><code>8e357b1</code></a>
ci: Remove unnecessary 'needs' from debug bundle job</li>
<li><a
href="26e19caa3a"><code>26e19ca</code></a>
ci: Add test for artifact-name</li>
<li><a
href="06d246b4d5"><code>06d246b</code></a>
flatpak-builder: Add ability to override artifact name</li>
<li><a
href="a262264771"><code>a262264</code></a>
ci: Add job that uses build-debug-bundle</li>
<li><a
href="f7362292df"><code>f736229</code></a>
flatpak-builder: Add buildDebugBundle flag</li>
<li><a
href="3b10954431"><code>3b10954</code></a>
ci: Update actions to versions using Node 24</li>
<li>See full diff in <a
href="401fe28a83...7932741660">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Update the macOS Sparkle dependency from 2.9.0 to 2.9.4.
This keeps the Swift package resolution and all tag/tip release workflow
downloads aligned on the same version. Sparkle 2.9.2 included fixes for
GHSA-g3hp-f6mg-559v and GHSA-hg88-v3cw-3qrh; 2.9.4 is the current stable
release.
Validation:
- verified the 2.9.4 release contains
`Sparkle-for-Swift-Package-Manager.zip`
- verified the lockfile revision matches the 2.9.4 tag
- `jq empty` on `Package.resolved`
- `git diff --check`
I could not run Xcode package resolution locally because the active
developer directory is Command Line Tools rather than a full Xcode
installation.
Replace a bunch of type-specific Wasm allocation functions with a
generic byte allocator and reusable opaque out-parameters for pointers.
This makes it a lot more ergonomic (relatively) to use the Wasm
interface and removes a dozen or so exports.
This also updates the `ghostty_type_json` `abi` field with a maximum
alignment value that host sides can use to keep every allocation aligned
properly, easily, without hardcoding numbers.
This adds a test to verify this all works as intended and runs in CI.
Replace a bunch of type-specific Wasm allocation functions with a generic
byte allocator and reusable opaque out-parameters for pointers. This
makes it a lot more ergonomic (relatively) to use the Wasm interface
and removes a dozen or so exports.
This also updates the `ghostty_type_json` `abi` field with a maximum
alignment value that host sides can use to keep every allocation aligned
properly, easily, without hardcoding numbers.
This adds a test to verify this all works as intended and runs in CI.
The ABI manifest previously had no machine-readable grammar or test that
the public export conformed to it.
Define a Draft 2020-12 schema and add a build check that executes
ghostty_type_json for native and wasm libraries before validation. Run
both forms in CI and publish the schema with the generated API docs.
This introduces a `-Dvt-features` build option for libghostty-vt that
compiles out optional feature areas, primarily so size-conscious
embedders (e.g. wasm) can significantly trim the binary.
The flag is similar to `-Dcpu`, `+feature` or `feature` to enable it,
`-feature` to disable, magic word `all` to turn all features on or off.
Example: `-Dvt-features=-all,+render-state` builds only the render state
API.
Added CI to verify the lib and tests _compile_ (we don't run it) for
each individual feature.
### Sizes
wasm32, ReleaseFast:
| Build | Bytes | Brotli |
|---|---|---|
| default (all features) | 876,500 | 218,309 |
| web interactive
(`-all,+render-state,+input-encode,+selection,+color,+grid-introspection`)
| 661,119 | 168,994 |
| read-only viewer (`-all,+render-state`) | 537,441 | 132,858 |
| bare VT core (`-all`) | 515,422 | 125,756 |
| xterm.js browser bundle (incl. renderers) | 488,663 | 99,311 |
| @xterm/headless | 182,672 | 39,651 |
Note: xterm versions are stable as of this commit.
### C Header Note
I didn't do a `vt/features.h` style header that has macros to guard
symbols for the various features. This is something we should do in the
future. The way it is now, the C header always declares everything, and
its not a problem unless an unavailable function is referenced at link
time.