mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 06:54:45 +03:00
Added support for kitty images protocol using Shared Memory (#1810)
* termwiz: add support for kitty image using shm mode * termwiz: kitty image shm cleanup error handling * termwiz: kitty image shm create wrapper for HANDLE and impl Drop for it * termwiz: kitty image shm refactor windows implementation Signed-off-by: Shreesh Adiga <16567adigashreesh@gmail.com>
This commit is contained in:
parent
14323a08d1
commit
60ec82554b
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4038,6 +4038,7 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"memmem",
|
||||
"nix 0.23.1",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"ordered-float",
|
||||
|
@ -58,6 +58,7 @@ version = "0.3"
|
||||
[target."cfg(unix)".dependencies]
|
||||
signal-hook = "0.1"
|
||||
termios = "0.3"
|
||||
nix = "0.23.1"
|
||||
[target."cfg(windows)".dependencies.winapi]
|
||||
features = [
|
||||
"winbase",
|
||||
@ -68,6 +69,8 @@ features = [
|
||||
"handleapi",
|
||||
"fileapi",
|
||||
"synchapi",
|
||||
"memoryapi",
|
||||
"winnt",
|
||||
]
|
||||
version = "0.3"
|
||||
|
||||
|
@ -246,14 +246,177 @@ impl KittyImageData {
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
Self::SharedMem { .. } => {
|
||||
log::error!("kitty image protocol via shared memory is not supported");
|
||||
Err(std::io::ErrorKind::Unsupported.into())
|
||||
}
|
||||
Self::SharedMem {
|
||||
name,
|
||||
data_offset,
|
||||
data_size,
|
||||
} => read_shared_memory_data(&name, data_offset, data_size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn read_shared_memory_data(
|
||||
name: &str,
|
||||
data_offset: Option<u32>,
|
||||
data_size: Option<u32>,
|
||||
) -> std::result::Result<std::vec::Vec<u8>, std::io::Error> {
|
||||
use nix::sys::mman::{shm_open, shm_unlink};
|
||||
use std::fs::File;
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
let raw_fd = shm_open(
|
||||
name,
|
||||
nix::fcntl::OFlag::O_RDONLY,
|
||||
nix::sys::stat::Mode::empty(),
|
||||
)
|
||||
.map_err(|_| {
|
||||
let err = std::io::Error::last_os_error();
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("shm_open {} failed: {:#}", name, err),
|
||||
)
|
||||
})?;
|
||||
let mut f = unsafe { File::from_raw_fd(raw_fd) };
|
||||
if let Some(offset) = data_offset {
|
||||
f.seek(std::io::SeekFrom::Start(offset.into()))?;
|
||||
}
|
||||
let data = if let Some(len) = data_size {
|
||||
let mut res = vec![0u8; len as usize];
|
||||
f.read_exact(&mut res)?;
|
||||
res
|
||||
} else {
|
||||
let mut res = vec![];
|
||||
f.read_to_end(&mut res)?;
|
||||
res
|
||||
};
|
||||
|
||||
if let Err(err) = shm_unlink(name) {
|
||||
log::warn!(
|
||||
"Unable to unlink kitty image protocol shm file {}: {:#}",
|
||||
name,
|
||||
err
|
||||
);
|
||||
}
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
mod win {
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::memoryapi::{
|
||||
MapViewOfFile, OpenFileMappingW, UnmapViewOfFile, VirtualQuery, FILE_MAP_ALL_ACCESS,
|
||||
};
|
||||
use winapi::um::winnt::{HANDLE, MEMORY_BASIC_INFORMATION};
|
||||
|
||||
struct HandleWrapper {
|
||||
handle: HANDLE,
|
||||
}
|
||||
|
||||
struct SharedMemObject {
|
||||
_handle: HandleWrapper,
|
||||
buf: *mut u8,
|
||||
}
|
||||
|
||||
impl Drop for HandleWrapper {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
CloseHandle(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SharedMemObject {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
UnmapViewOfFile(self.buf as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a rust string to a windows wide string
|
||||
fn wide_string(s: &str) -> Vec<u16> {
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
std::ffi::OsStr::new(s)
|
||||
.encode_wide()
|
||||
.chain(std::iter::once(0))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn read_shared_memory_data(
|
||||
name: &str,
|
||||
data_offset: Option<u32>,
|
||||
data_size: Option<u32>,
|
||||
) -> std::result::Result<std::vec::Vec<u8>, std::io::Error> {
|
||||
let wide_name = wide_string(&name);
|
||||
|
||||
let handle = unsafe { OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, wide_name.as_ptr()) };
|
||||
if handle.is_null() {
|
||||
let err = std::io::Error::last_os_error();
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("OpenFileMappingW {} failed: {:#}", name, err),
|
||||
));
|
||||
}
|
||||
|
||||
let handle_wrapper = HandleWrapper { handle };
|
||||
let buf = unsafe { MapViewOfFile(handle_wrapper.handle, FILE_MAP_ALL_ACCESS, 0, 0, 0) };
|
||||
if buf.is_null() {
|
||||
let err = std::io::Error::last_os_error();
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("MapViewOfFile failed: {:#}", err),
|
||||
));
|
||||
}
|
||||
|
||||
let shm = SharedMemObject {
|
||||
_handle: handle_wrapper,
|
||||
buf: buf as *mut u8,
|
||||
};
|
||||
|
||||
let mut memory_info = MEMORY_BASIC_INFORMATION::default();
|
||||
let res = unsafe {
|
||||
VirtualQuery(
|
||||
shm.buf as _,
|
||||
&mut memory_info as *mut MEMORY_BASIC_INFORMATION,
|
||||
std::mem::size_of::<MEMORY_BASIC_INFORMATION>(),
|
||||
)
|
||||
};
|
||||
if res == 0 {
|
||||
let err = std::io::Error::last_os_error();
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"Can't get the size of Shared Memory, VirtualQuery failed: {:#}",
|
||||
err
|
||||
),
|
||||
));
|
||||
}
|
||||
let mut size = memory_info.RegionSize;
|
||||
let offset = data_offset.unwrap_or(0) as usize;
|
||||
if offset >= size {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"offset {} bigger than or equal to shm region size {}",
|
||||
offset, size
|
||||
),
|
||||
));
|
||||
}
|
||||
size = size.saturating_sub(offset);
|
||||
if let Some(val) = data_size {
|
||||
size = size.min(val as usize);
|
||||
}
|
||||
let buf_slice = unsafe { std::slice::from_raw_parts(shm.buf.add(offset), size) };
|
||||
let data = buf_slice.to_vec();
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
use win::read_shared_memory_data;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum KittyImageVerbosity {
|
||||
Verbose,
|
||||
|
Loading…
Reference in New Issue
Block a user