fix: close the RV6 verification gaps

Resolves the 7 gap groups in docs/rewrite/notes/review-rv6-codex.md
(final-Z8.md):
- crash (macOS): request_abort_dump returns false on mach_msg receive
  timeout/error so the signal-path fallback runs; EXC_SOFT_SIGNAL keeps
  the signal number in the minidump exception info.
- Default SHELL read as an OS string and stored in encoded command form.
- macOS executable search works on raw PATH bytes; the default path is
  used only when PATH is unset.
- Windows: config env overrides are decoded; EnvMap compares keys as
  WTF-16 units with per-unit Unicode simple uppercasing (no lossy
  conversion, distinct lone-surrogate keys stay distinct).
- +show-config writes original bytes for encoded OS data, so export +
  reload round-trips; UTF-8 configs are byte-identical as before.
- Zig's ensureLocale chain lives in ghostty-os for all Unix targets and
  is used by both the GTK app and the C API init.

Also makes the quick-terminal GTK replay test independent of compositor
focus: GTK's is-active is read-only, so when niri actually focuses the
layer surface the simulated focus-out cannot drive autohide and that
assertion is skipped (the production logic is unchanged and matches Zig).

Test Plan:
- cargo test --workspace (3390 passed, incl. tests/gtk_replay.rs)
- just check-macos (both), just check-windows, just check-wasm
This commit is contained in:
ddidderr committed 2026-10-12 10:27:37 +02:00
1 parent 306a19227f
commit 5e5d33324c
12 files changed
+452 -133

No files matched your search

@@ -206,58 +206,12 @@ fn set_gtk_env(config: &CoreConfig) {
/// if that fails (usually an invalid `LANG`), retry with `LANG` unset, then fall
/// back to `en_US.UTF-8` (updating `LANG` on success). Idempotent. This must
/// run before GTK initializes and before the child environment is captured.
#[allow(unsafe_code)]
pub fn init_locale() {
static ONCE: std::sync::Once = std::sync::Once::new();
ONCE.call_once(|| {
// SAFETY: all strings are valid NUL-terminated C strings; this runs at
// startup before other threads read the environment or locale.
unsafe {
fn show(p: *const libc::c_char) -> String {
// SAFETY: setlocale returns a valid C string when non-null.
unsafe { std::ffi::CStr::from_ptr(p) }
.to_string_lossy()
.into_owned()
}
// Set the locale to whatever is set in env vars.
let r = libc::setlocale(libc::LC_ALL, c"".as_ptr());
if !r.is_null() {
log::info!("setlocale from env result={}", show(r));
return;
}
// setlocale failed, probably because LANG is invalid. Try again
// without LANG to use the system default.
if std::env::var_os("LANG").is_some_and(|v| !v.is_empty()) {
// Both so that LANG is either empty or unset completely.
libc::setenv(c"LANG".as_ptr(), c"".as_ptr(), 1);
libc::unsetenv(c"LANG".as_ptr());
let r = libc::setlocale(libc::LC_ALL, c"".as_ptr());
if !r.is_null() {
let v = show(r);
log::info!("setlocale after unset lang result={v}");
// An unsupported locale yields the "C" fallback; we
// prefer moving on to en_US.UTF-8 in that case.
if v != "C" {
return;
}
}
}
// Failure again... fallback to en_US.UTF-8
log::warn!(
"setlocale failed with LANG and system default. Falling back to en_US.UTF-8"
);
let r = libc::setlocale(libc::LC_ALL, c"en_US.UTF-8".as_ptr());
if r.is_null() {
log::warn!("setlocale failed even with the fallback, uncertain results");
} else {
libc::setenv(c"LANG".as_ptr(), c"en_US.UTF-8".as_ptr(), 1);
log::info!("setlocale default result={}", show(r));
}
// Shared implementation (also used by core's global init).
if let Some(locale) = ghostty_os::ensure_locale() {
log::debug!("locale set locale={locale}");
}
});
}