fix(input): carry key and preedit text as bytes like Zig
Zig's KeyEvent.utf8 and the embedded API's key/preedit text are byte slices passed through to key encoding and the pty; the port converted them lossily to UTF-8. - KeyEvent.utf8 is &[u8] end to end (ghostty-input encoder, core, ghostty-lib C API, libghostty-vt key events, GTK callers). Where Zig validates with Utf8View (alternates, modify-other-keys, ctrl CSI-u, associated text, binding unicode lookup) invalid text takes the same "no UTF-8" fallback. - Invalid preedit UTF-8 behaves like Zig's `try Utf8View.init`: the prior preedit is cleared and marked dirty, the callback returns an error (logged by the C API) and no preedit is set. - The inspector key widget shows invalid key text lossily, display only. Test Plan: - cargo test --workspace --no-fail-fast (3407 passed) - cargo test -p ghostty-lib --features test-platform (C-API key text 0xff 0xfe reaches the pty unchanged) - just check-macos (both), just check-windows, just check-wasm
This commit is contained in:
1 parent
5f16c24760
commit
db954441fa
19 files changed
+277
-144
No files matched your search
@@ -216,7 +216,7 @@ struct OwnedKey {
|
||||
mods: Mods,
|
||||
consumed_mods: Mods,
|
||||
composing: bool,
|
||||
text: String,
|
||||
text: Vec<u8>,
|
||||
unshifted_codepoint: u32,
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ impl OwnedKey {
|
||||
};
|
||||
// SAFETY: per the function contract.
|
||||
let text = unsafe { cstr(e.text) }
|
||||
.map(|c| c.to_string_lossy().into_owned())
|
||||
.map(|c| c.to_bytes().to_vec())
|
||||
.unwrap_or_default();
|
||||
|
||||
// We want to get the physical unmapped key to process keybinds.
|
||||
@@ -1636,7 +1636,7 @@ pub unsafe extern "C" fn ghostty_surface_preedit(
|
||||
} else {
|
||||
// SAFETY: `text` points to `len` readable bytes.
|
||||
let bytes = unsafe { std::slice::from_raw_parts(text.cast::<u8>(), len) };
|
||||
Some(String::from_utf8_lossy(bytes).into_owned())
|
||||
Some(bytes.to_vec())
|
||||
};
|
||||
if let Err(err) = core.preedit_callback(preedit.as_deref()) {
|
||||
log::error!("error in preedit callback err={err}");
|
||||
|
||||
Reference in new issue
Block a user