diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-09-27 00:06:29 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-27 00:06:29 +0300 |
| commit | fff6c820aa45f4eabb9b2e0456326dc74cca5a25 (patch) | |
| tree | 94128973cbc95a304f311f15c0eab95b49d05655 /src/ghostty/native_source.rs | |
| parent | c33fd40eab3d92b564d7dd25bbfdd462e4b7aba2 (diff) | |
refactor: extract libghostty-vt binding into ghostty-vt workspace crate (#4661)
* refactor: extract libghostty-vt binding into ghostty-vt workspace crate
* fix: build libghostty-vt into each build's out dir
Diffstat (limited to 'src/ghostty/native_source.rs')
| -rw-r--r-- | src/ghostty/native_source.rs | 165 |
1 files changed, 0 insertions, 165 deletions
diff --git a/src/ghostty/native_source.rs b/src/ghostty/native_source.rs deleted file mode 100644 index 3e4e8a3f..00000000 --- a/src/ghostty/native_source.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! Host-owned immutable file snapshots retained by the native image lifetime. -use super::{ffi, Error, GhosttyResultExt}; -use crate::pane_graphics_files::{FileStore, OwnedExport}; -use std::ffi::c_void; -use std::ptr; -use std::sync::{Arc, OnceLock}; - -static SOURCES: OnceLock<FileStore> = OnceLock::new(); - -// These getters never materialize native pixels. The image borrow protects the -// host's strong reference until we have acquired our own. -pub(super) fn image_source( - image: ffi::GhosttyKittyGraphicsImage, -) -> Result<Option<Arc<OwnedExport>>, Error> { - let mut context: *mut c_void = ptr::null_mut(); - let result = unsafe { - ffi::ghostty_kitty_graphics_image_get( - image, - ffi::GhosttyKittyGraphicsImageData_GHOSTTY_KITTY_IMAGE_DATA_FILE_CONTEXT, - (&mut context as *mut *mut c_void).cast(), - ) - }; - if result == ffi::GhosttyResult_GHOSTTY_NO_VALUE { - return Ok(None); - } - result.into_result()?; - if context.is_null() { - return Ok(None); - } - let mut identity = 0u64; - unsafe { - ffi::ghostty_kitty_graphics_image_get( - image, - ffi::GhosttyKittyGraphicsImageData_GHOSTTY_KITTY_IMAGE_DATA_FILE_IDENTITY, - (&mut identity as *mut u64).cast(), - ) - .into_result()?; - let source = context.cast::<OwnedExport>(); - // All terminal snapshot callbacks in this wrapper produce this type. - // Identity is immutable and does not depend on decoded pixel storage. - if (*source).fingerprint() != identity { - return Err(Error(ffi::GhosttyResult_GHOSTTY_INVALID_VALUE)); - } - Arc::increment_strong_count(source); - Ok(Some(Arc::from_raw(source))) - } -} - -pub(super) fn set_forwarding(terminal: ffi::GhosttyTerminal, enabled: bool) -> Result<(), Error> { - let callback = if enabled && cfg!(target_os = "linux") { - snapshot as *const () as *const c_void - } else { - ptr::null() - }; - unsafe { - ffi::ghostty_terminal_set( - terminal, - ffi::GhosttyTerminalOption_GHOSTTY_TERMINAL_OPT_KITTY_IMAGE_SNAPSHOT_FILE, - callback, - ) - .into_result() - } -} - -unsafe extern "C" fn snapshot( - _terminal: ffi::GhosttyTerminal, - _userdata: *mut c_void, - request: *const ffi::GhosttyKittyImageSnapshotFileRequest, - out: *mut ffi::GhosttyKittyImageFileBacking, -) -> bool { - std::panic::catch_unwind(|| { - if request.is_null() || out.is_null() || !cfg!(target_os = "linux") { - return false; - } - let request = unsafe { &*request }; - if request.size != std::mem::size_of::<ffi::GhosttyKittyImageSnapshotFileRequest>() { - return false; - } - let Ok(len) = usize::try_from(request.expected_len) else { - return false; - }; - let Ok(source) = SOURCES - .get_or_init(FileStore::native_sources) - .snapshot(request.fd, len) - else { - return false; - }; - let source = Arc::new(source); - let backing = ffi::GhosttyKittyImageFileBacking { - identity: source.fingerprint(), - len: source.len(), - context: Arc::into_raw(source).cast_mut().cast(), - read: Some(read), - release: Some(release), - }; - unsafe { - out.write(backing); - } - true - }) - .unwrap_or(false) -} - -unsafe extern "C" fn read(context: *mut c_void, dest: *mut u8, len: usize) -> bool { - std::panic::catch_unwind(|| { - if context.is_null() || dest.is_null() { - return false; - } - let source = unsafe { &*context.cast::<OwnedExport>() }; - if len != source.len() || len > isize::MAX as usize { - return false; - } - source - .read_into(unsafe { std::slice::from_raw_parts_mut(dest, len) }) - .is_ok() - }) - .unwrap_or(false) -} - -unsafe extern "C" fn release(context: *mut c_void) { - let _ = std::panic::catch_unwind(|| { - if !context.is_null() { - drop(unsafe { Arc::from_raw(context.cast::<OwnedExport>()) }); - } - }); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn invalid_requests_decline_without_transferring_ownership() { - let mut out = ffi::GhosttyKittyImageFileBacking::default(); - let mut request = ffi::GhosttyKittyImageSnapshotFileRequest { - size: std::mem::size_of::<ffi::GhosttyKittyImageSnapshotFileRequest>(), - fd: -1, - expected_len: 4, - }; - unsafe { - assert!(!snapshot( - ptr::null_mut(), - ptr::null_mut(), - &request, - &mut out - )); - assert!(out.context.is_null()); - request.size = 0; - assert!(!snapshot( - ptr::null_mut(), - ptr::null_mut(), - &request, - &mut out - )); - assert!(!snapshot( - ptr::null_mut(), - ptr::null_mut(), - ptr::null(), - &mut out - )); - assert!(out.context.is_null()); - release(ptr::null_mut()); - } - } -} |
