1
1
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:
Wez Furlong 2019-02-16 23:36:50 -08:00
parent f976ca6e23
commit c650cbbf08
6 changed files with 206 additions and 16 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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))
}

View File

@ -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;