mirror of
https://github.com/wez/wezterm.git
synced 2024-11-10 15:04:32 +03:00
flesh out some of the windows pty impl
This commit is contained in:
parent
f976ca6e23
commit
c650cbbf08
@ -30,6 +30,15 @@ path = "term"
|
||||
[dependencies.termwiz]
|
||||
path = "termwiz"
|
||||
|
||||
[target."cfg(windows)".dependencies.winapi]
|
||||
features = [
|
||||
"winuser",
|
||||
"consoleapi",
|
||||
"handleapi",
|
||||
"fileapi",
|
||||
"namedpipeapi",
|
||||
]
|
||||
version = "~0.3"
|
||||
|
||||
[target.'cfg(any(target_os = "android", all(unix, not(target_os = "macos"))))'.dependencies]
|
||||
freetype = "~0.4"
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Generic system dependent windows via glium+glutin
|
||||
|
||||
use super::MasterPty;
|
||||
use super::{Child, Command};
|
||||
use clipboard::{Clipboard, ClipboardImpl, Paste};
|
||||
use config::Config;
|
||||
use failure::Error;
|
||||
@ -11,7 +12,6 @@ use guiloop::{GuiEventLoop, SessionTerminated};
|
||||
use opengl::render::Renderer;
|
||||
use opengl::textureatlas::OutOfTextureSpace;
|
||||
use std::io::Write;
|
||||
use std::process::{Child, Command};
|
||||
use std::rc::Rc;
|
||||
use term::KeyCode;
|
||||
use term::KeyModifiers;
|
||||
|
@ -50,7 +50,6 @@ extern crate xcb_util;
|
||||
#[cfg(all(unix, not(feature = "force-glutin"), not(target_os = "macos")))]
|
||||
mod xwindows;
|
||||
|
||||
use std::process::Command;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod config;
|
||||
@ -71,11 +70,11 @@ use font::FontConfiguration;
|
||||
#[cfg(unix)]
|
||||
mod pty;
|
||||
#[cfg(unix)]
|
||||
pub use pty::{openpty, MasterPty, SlavePty};
|
||||
pub use pty::{openpty, Child, Command, MasterPty, SlavePty};
|
||||
#[cfg(windows)]
|
||||
mod winpty;
|
||||
#[cfg(windows)]
|
||||
pub use winpty::{openpty, MasterPty, SlavePty};
|
||||
pub use winpty::{openpty, Child, Command, MasterPty, SlavePty};
|
||||
#[cfg(unix)]
|
||||
mod sigchld;
|
||||
|
||||
|
@ -9,9 +9,11 @@ use std::io;
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::process::Stdio;
|
||||
use std::ptr;
|
||||
|
||||
pub use std::process::{Child, Command};
|
||||
|
||||
/// Represents the master end of a pty.
|
||||
/// The file descriptor will be closed when the Pty is dropped.
|
||||
pub struct MasterPty {
|
||||
|
199
src/winpty.rs
199
src/winpty.rs
@ -1,9 +1,117 @@
|
||||
use failure::Error;
|
||||
use std::io;
|
||||
use std::process::{Child, Command};
|
||||
use std::io::Error as IoError;
|
||||
extern crate winapi;
|
||||
use std::os::windows::raw::HANDLE;
|
||||
use std::ptr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use winpty::winapi::shared::minwindef::DWORD;
|
||||
use winpty::winapi::shared::winerror::{HRESULT, S_OK};
|
||||
use winpty::winapi::um::fileapi::{ReadFile, WriteFile};
|
||||
use winpty::winapi::um::handleapi::*;
|
||||
use winpty::winapi::um::namedpipeapi::CreatePipe;
|
||||
use winpty::winapi::um::wincon::COORD;
|
||||
|
||||
pub struct MasterPty {}
|
||||
pub struct SlavePty {}
|
||||
pub use std::process::{Child, Command};
|
||||
|
||||
type HPCON = HANDLE;
|
||||
|
||||
extern "system" {
|
||||
fn CreatePseudoConsole(
|
||||
size: COORD,
|
||||
hInput: HANDLE,
|
||||
hOutput: HANDLE,
|
||||
flags: DWORD,
|
||||
hpc: *mut HPCON,
|
||||
) -> HRESULT;
|
||||
fn ResizePseudoConsole(hpc: HPCON, size: COORD) -> HRESULT;
|
||||
fn ClosePseudoConsole(hpc: HPCON);
|
||||
}
|
||||
|
||||
struct PsuedoCon {
|
||||
con: HPCON,
|
||||
}
|
||||
unsafe impl Send for PsuedoCon {}
|
||||
unsafe impl Sync for PsuedoCon {}
|
||||
impl Drop for PsuedoCon {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ClosePseudoConsole(self.con) };
|
||||
}
|
||||
}
|
||||
impl PsuedoCon {
|
||||
fn new(size: COORD, input: &OwnedHandle, output: &OwnedHandle) -> Result<Self, Error> {
|
||||
let mut con: HPCON = INVALID_HANDLE_VALUE;
|
||||
let result = unsafe { CreatePseudoConsole(size, input.handle, output.handle, 0, &mut con) };
|
||||
ensure!(
|
||||
result == S_OK,
|
||||
"failed to create psuedo console: HRESULT {}",
|
||||
result
|
||||
);
|
||||
Ok(Self { con })
|
||||
}
|
||||
fn resize(&self, size: COORD) -> Result<(), Error> {
|
||||
let result = unsafe { ResizePseudoConsole(self.con, size) };
|
||||
ensure!(
|
||||
result == S_OK,
|
||||
"failed to resize console to {}x{}: HRESULT: {}",
|
||||
size.X,
|
||||
size.Y,
|
||||
result
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct OwnedHandle {
|
||||
handle: HANDLE,
|
||||
}
|
||||
unsafe impl Send for OwnedHandle {}
|
||||
impl Drop for OwnedHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CloseHandle(self.handle) };
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
con: PsuedoCon,
|
||||
readable: OwnedHandle,
|
||||
writable: OwnedHandle,
|
||||
size: winsize,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
pub fn resize(
|
||||
&mut self,
|
||||
num_rows: u16,
|
||||
num_cols: u16,
|
||||
pixel_width: u16,
|
||||
pixel_height: u16,
|
||||
) -> Result<(), Error> {
|
||||
self.con.resize(COORD {
|
||||
X: num_cols as i16,
|
||||
Y: num_rows as i16,
|
||||
})?;
|
||||
self.size = winsize {
|
||||
ws_row: num_rows,
|
||||
ws_col: num_cols,
|
||||
ws_xpixel: pixel_width,
|
||||
ws_ypixel: pixel_height,
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MasterPty {
|
||||
inner: Arc<Mutex<Inner>>,
|
||||
}
|
||||
|
||||
pub struct SlavePty {
|
||||
inner: Arc<Mutex<Inner>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct winsize {
|
||||
pub ws_row: u16,
|
||||
pub ws_col: u16,
|
||||
@ -19,15 +127,19 @@ impl MasterPty {
|
||||
pixel_width: u16,
|
||||
pixel_height: u16,
|
||||
) -> Result<(), Error> {
|
||||
bail!("MasterPty::resize not implemented")
|
||||
let mut inner = self.inner.lock().unwrap();
|
||||
inner.resize(num_rows, num_cols, pixel_width, pixel_height)
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> Result<winsize, Error> {
|
||||
bail!("MasterPty::get_size not implemented")
|
||||
let inner = self.inner.lock().unwrap();
|
||||
Ok(inner.size.clone())
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> Result<Self, Error> {
|
||||
bail!("MasterPty::try_clone not implemented")
|
||||
Ok(Self {
|
||||
inner: self.inner.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clear_nonblocking(&self) -> Result<(), Error> {
|
||||
@ -37,7 +149,21 @@ impl MasterPty {
|
||||
|
||||
impl io::Write for MasterPty {
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
|
||||
unimplemented!();
|
||||
let mut num_wrote = 0;
|
||||
let ok = unsafe {
|
||||
WriteFile(
|
||||
self.inner.lock().unwrap().writable.handle as *mut _,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len() as u32,
|
||||
&mut num_wrote,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if ok == 0 {
|
||||
Err(IoError::last_os_error())
|
||||
} else {
|
||||
Ok(num_wrote as usize)
|
||||
}
|
||||
}
|
||||
fn flush(&mut self) -> Result<(), io::Error> {
|
||||
Ok(())
|
||||
@ -46,7 +172,21 @@ impl io::Write for MasterPty {
|
||||
|
||||
impl io::Read for MasterPty {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
|
||||
unimplemented!();
|
||||
let mut num_read = 0;
|
||||
let ok = unsafe {
|
||||
ReadFile(
|
||||
self.inner.lock().unwrap().readable.handle as *mut _,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len() as u32,
|
||||
&mut num_read,
|
||||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
if ok == 0 {
|
||||
Err(IoError::last_os_error())
|
||||
} else {
|
||||
Ok(num_read as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +196,52 @@ impl SlavePty {
|
||||
}
|
||||
}
|
||||
|
||||
fn pipe() -> Result<(OwnedHandle, OwnedHandle), Error> {
|
||||
let mut read: HANDLE = INVALID_HANDLE_VALUE;
|
||||
let mut write: HANDLE = INVALID_HANDLE_VALUE;
|
||||
if unsafe { CreatePipe(&mut read, &mut write, ptr::null_mut(), 0) } == 0 {
|
||||
bail!("CreatePipe failed: {}", IoError::last_os_error());
|
||||
}
|
||||
Ok((OwnedHandle { handle: read }, OwnedHandle { handle: write }))
|
||||
}
|
||||
|
||||
pub fn openpty(
|
||||
num_rows: u16,
|
||||
num_cols: u16,
|
||||
pixel_width: u16,
|
||||
pixel_height: u16,
|
||||
) -> Result<(MasterPty, SlavePty), Error> {
|
||||
bail!("openpty not implemented")
|
||||
let (stdin_read, stdin_write) = pipe()?;
|
||||
let (stdout_read, stdout_write) = pipe()?;
|
||||
|
||||
let con = PsuedoCon::new(
|
||||
COORD {
|
||||
X: num_cols as i16,
|
||||
Y: num_rows as i16,
|
||||
},
|
||||
&stdin_read,
|
||||
&stdout_write,
|
||||
)?;
|
||||
|
||||
let size = winsize {
|
||||
ws_row: num_rows,
|
||||
ws_col: num_cols,
|
||||
ws_xpixel: pixel_width,
|
||||
ws_ypixel: pixel_height,
|
||||
};
|
||||
|
||||
let master = MasterPty {
|
||||
inner: Arc::new(Mutex::new(Inner {
|
||||
con,
|
||||
readable: stdout_read,
|
||||
writable: stdin_write,
|
||||
size,
|
||||
})),
|
||||
};
|
||||
|
||||
let slave = SlavePty {
|
||||
inner: master.inner.clone(),
|
||||
};
|
||||
|
||||
Ok((master, slave))
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::super::opengl::render::Renderer;
|
||||
use super::super::{get_shell, spawn_window};
|
||||
use super::xkeysyms;
|
||||
use super::{Child, Command};
|
||||
use super::{Connection, Window};
|
||||
use clipboard::{Clipboard, ClipboardImpl, Paste};
|
||||
use config::Config;
|
||||
@ -14,8 +15,6 @@ use pty::MasterPty;
|
||||
use std::cell::RefCell;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::process::Child;
|
||||
use std::process::Command;
|
||||
use std::rc::Rc;
|
||||
use term::{self, KeyCode, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
|
||||
use termwiz::hyperlink::Hyperlink;
|
||||
|
Loading…
Reference in New Issue
Block a user