feat(macos): port Ghostty's macOS code paths (Metal, CoreText, Darwin)

Ports the macOS-specific Zig code behind cfg(target_os = "macos"):
- renderer: a GraphicsApi trait with generic::Renderer<G>; Metal backend
  (all renderer/metal/* files, shaders.metal verbatim, runtime library
  compile, IOSurface layer, CVDisplayLink), shadertoy -> MSL via naga;
  OpenGL remains the backend elsewhere.
- font: CoreText face, shaper and discovery with build.rs backend
  selection (coretext default; coretext-freetype / coretext-harfbuzz /
  coretext-noshape features), no fontconfig/freetype/harfbuzz on Apple.
- input: KeymapDarwin via UCKeyTranslate, option-as-alt, mac keycodes.
- os: macos, mach, cf_release_thread, NSProcessInfo args and macOS
  branches; config: macOS defaults, keybinds, Application Support paths.
- termio/core: login(1) wrapping, openpty/execvpe, Darwin child exit
  handling, os_log logging.

Compile-checked for aarch64/x86_64-apple-darwin (clippy -D warnings
clean) using the cross setup in docs/rewrite/notes/macos-M1.md; cannot
run here. The embedded runtime/C API (embedded.zig) is the next step.

Also includes the cross-platform integration edits shared by the crash,
verification, Windows and macOS work (Cargo target-gating, thread
crash-context hooks, apprt-gtk surface/IME refactor, termio/os cfg
gates), a cfg fix so ghostty-config builds on wasm32, and an allow for
the intentional recursion in the crash overflow test.

Test Plan:
- cargo test --workspace (3224 passed)
- cargo clippy --workspace --all-targets -- -D warnings
- cargo check --target aarch64-apple-darwin -p ghostty-renderer (with
  the documented cross env)
This commit is contained in:
ddidderr committed 2026-10-12 06:02:39 +02:00
1 parent 76771bed0d
commit bab49ee596
124 files changed
+14936 -1242

No files matched your search

+24 -4
View File
@@ -1,24 +1,31 @@
//! A library represents the shared state that the underlying font
//! library implementation(s) require per-process. Port of `font/library.zig`
//! (the `FreetypeLibrary` variant).
//! library implementation(s) require per-process. Port of `font/library.zig`.
//!
//! * FreeType backends: the `FT_Library` (plus a face-creation mutex).
//! * Backends without a library (CoreText, Canvas): an empty library
//! (Zig: `NoopLibrary`).
use std::sync::{Arc, Mutex};
#[cfg(font_freetype)]
use crate::face::freetype::ft;
#[derive(Debug, thiserror::Error)]
pub enum LibraryError {
#[cfg(font_freetype)]
#[error("freetype error {0}")]
Freetype(i32),
}
/// Shared FreeType library state. Cheap to clone.
/// Shared font library state. Cheap to clone.
#[derive(Clone)]
pub struct Library {
#[cfg_attr(not(font_freetype), allow(dead_code))]
pub(crate) inner: Arc<LibraryInner>,
}
pub(crate) struct LibraryInner {
#[cfg(font_freetype)]
pub(crate) lib: ft::Lib,
/// Mutex to be held any time the library is
@@ -27,6 +34,7 @@ pub(crate) struct LibraryInner {
}
impl Library {
#[cfg(font_freetype)]
pub fn init() -> Result<Library, LibraryError> {
let lib = ft::Lib::new().map_err(LibraryError::Freetype)?;
Ok(Library {
@@ -37,8 +45,20 @@ impl Library {
})
}
/// The CoreText backend has no per-process library state.
#[cfg(not(font_freetype))]
#[allow(clippy::unnecessary_wraps)]
pub fn init() -> Result<Library, LibraryError> {
Ok(Library {
inner: Arc::new(LibraryInner {
mutex: Mutex::new(()),
}),
})
}
/// Lock the library mutex (poisoning is ignored: the guarded state is
/// only FreeType's own).
/// only the font library's own).
#[cfg_attr(not(font_freetype), allow(dead_code))]
pub(crate) fn lock(&self) -> std::sync::MutexGuard<'_, ()> {
self.inner
.mutex