diff options
author | David Hewitt <1939362+davidhewitt@users.noreply.github.com> | 2018-12-28 16:01:58 +0000 |
---|---|---|
committer | Christian Duerr <chrisduerr@users.noreply.github.com> | 2018-12-28 16:01:58 +0000 |
commit | f1bc6802e1d0d03feaa43e61c2bf465795a96da9 (patch) | |
tree | d2b993eb020631ca1de14b47eb0d9213ee37dd90 /src/tty/windows.rs | |
parent | ec6f756946c998d327316d370b381003e51d3a70 (diff) | |
download | alacritty-f1bc6802e1d0d03feaa43e61c2bf465795a96da9.tar.gz alacritty-f1bc6802e1d0d03feaa43e61c2bf465795a96da9.zip |
Add support for Windows ConPTY APIv0.2.4-conpty
Diffstat (limited to 'src/tty/windows.rs')
-rw-r--r-- | src/tty/windows.rs | 286 |
1 files changed, 0 insertions, 286 deletions
diff --git a/src/tty/windows.rs b/src/tty/windows.rs deleted file mode 100644 index 4895b37d..00000000 --- a/src/tty/windows.rs +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2016 Joe Wilm, The Alacritty Project Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::io; -use std::fs::OpenOptions; -use std::os::raw::c_void; -use std::os::windows::io::{FromRawHandle, IntoRawHandle}; -use std::os::windows::fs::OpenOptionsExt; -use std::env; -use std::cell::UnsafeCell; -use std::u16; - -use dunce::canonicalize; -use mio; -use mio::Evented; -use mio_named_pipes::NamedPipe; -use winapi::um::synchapi::WaitForSingleObject; -use winapi::um::winbase::{WAIT_OBJECT_0, FILE_FLAG_OVERLAPPED}; -use winapi::shared::winerror::WAIT_TIMEOUT; -use winpty::{ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty}; -use winpty::Config as WinptyConfig; - -use crate::config::{Config, Shell}; -use crate::display::OnResize; -use crate::cli::Options; -use crate::tty::EventedReadWrite; -use crate::term::SizeInfo; - -/// Handle to the winpty agent process. Required so we know when it closes. -static mut HANDLE: *mut c_void = 0usize as *mut c_void; - -/// How long the winpty agent should wait for any RPC request -/// This is a placeholder value until we see how often long responses happen -const AGENT_TIMEOUT: u32 = 10000; - -pub fn process_should_exit() -> bool { - unsafe { - match WaitForSingleObject(HANDLE, 0) { - // Process has exited - WAIT_OBJECT_0 => { - info!("wait_object_0"); - true - } - // Reached timeout of 0, process has not exited - WAIT_TIMEOUT => false, - // Error checking process, winpty gave us a bad agent handle? - _ => { - info!("Bad exit: {}", ::std::io::Error::last_os_error()); - true - } - } - } -} - -pub struct Pty<'a, R: io::Read + Evented + Send, W: io::Write + Evented + Send> { - // TODO: Provide methods for accessing this safely - pub winpty: UnsafeCell<Winpty<'a>>, - - conout: R, - conin: W, - read_token: mio::Token, - write_token: mio::Token, -} - -pub fn new<'a>( - config: &Config, - options: &Options, - size: &SizeInfo, - _window_id: Option<usize>, -) -> Pty<'a, NamedPipe, NamedPipe> { - // Create config - let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap(); - - wconfig.set_initial_size(size.cols().0 as i32, size.lines().0 as i32); - wconfig.set_mouse_mode(&MouseMode::Auto); - wconfig.set_agent_timeout(AGENT_TIMEOUT); - - // Start agent - let mut winpty = Winpty::open(&wconfig).unwrap(); - let (conin, conout) = (winpty.conin_name(), winpty.conout_name()); - - // Get process commandline - let default_shell = &Shell::new(env::var("COMSPEC").unwrap_or_else(|_| "cmd".into())); - let shell = config.shell().unwrap_or(default_shell); - let initial_command = options.command().unwrap_or(shell); - let mut cmdline = initial_command.args().to_vec(); - cmdline.insert(0, initial_command.program().into()); - - // Warning, here be borrow hell - let cwd = options.working_dir.as_ref().map(|dir| canonicalize(dir).unwrap()); - let cwd = cwd.as_ref().map(|dir| dir.to_str().unwrap()); - - // Spawn process - let spawnconfig = SpawnConfig::new( - SpawnFlags::AUTO_SHUTDOWN | SpawnFlags::EXIT_AFTER_SHUTDOWN, - None, // appname - Some(&cmdline.join(" ")), - cwd, - None, // Env - ).unwrap(); - - let default_opts = &mut OpenOptions::new(); - default_opts - .share_mode(0) - .custom_flags(FILE_FLAG_OVERLAPPED); - - let (conout_pipe, conin_pipe); - unsafe { - conout_pipe = NamedPipe::from_raw_handle( - default_opts - .clone() - .read(true) - .open(conout) - .unwrap() - .into_raw_handle(), - ); - conin_pipe = NamedPipe::from_raw_handle( - default_opts - .clone() - .write(true) - .open(conin) - .unwrap() - .into_raw_handle(), - ); - }; - - if let Some(err) = conout_pipe.connect().err() { - if err.kind() != io::ErrorKind::WouldBlock { - panic!(err); - } - } - assert!(conout_pipe.take_error().unwrap().is_none()); - - if let Some(err) = conin_pipe.connect().err() { - if err.kind() != io::ErrorKind::WouldBlock { - panic!(err); - } - } - assert!(conin_pipe.take_error().unwrap().is_none()); - - winpty.spawn(&spawnconfig).unwrap(); - - unsafe { - HANDLE = winpty.raw_handle(); - } - - Pty { - winpty: UnsafeCell::new(winpty), - conout: conout_pipe, - conin: conin_pipe, - // Placeholder tokens that are overwritten - read_token: 0.into(), - write_token: 0.into(), - } -} - -impl<'a> EventedReadWrite for Pty<'a, NamedPipe, NamedPipe> { - type Reader = NamedPipe; - type Writer = NamedPipe; - - #[inline] - fn register( - &mut self, - poll: &mio::Poll, - token: &mut Iterator<Item = &usize>, - interest: mio::Ready, - poll_opts: mio::PollOpt, - ) -> io::Result<()> { - self.read_token = (*token.next().unwrap()).into(); - self.write_token = (*token.next().unwrap()).into(); - if interest.is_readable() { - poll.register( - &self.conout, - self.read_token, - mio::Ready::readable(), - poll_opts, - )? - } else { - poll.register( - &self.conout, - self.read_token, - mio::Ready::empty(), - poll_opts, - )? - } - if interest.is_writable() { - poll.register( - &self.conin, - self.write_token, - mio::Ready::writable(), - poll_opts, - )? - } else { - poll.register( - &self.conin, - self.write_token, - mio::Ready::empty(), - poll_opts, - )? - } - Ok(()) - } - - #[inline] - fn reregister(&mut self, poll: &mio::Poll, interest: mio::Ready, poll_opts: mio::PollOpt) -> io::Result<()> { - if interest.is_readable() { - poll.reregister( - &self.conout, - self.read_token, - mio::Ready::readable(), - poll_opts, - )?; - } else { - poll.reregister( - &self.conout, - self.read_token, - mio::Ready::empty(), - poll_opts, - )?; - } - if interest.is_writable() { - poll.reregister( - &self.conin, - self.write_token, - mio::Ready::writable(), - poll_opts, - )?; - } else { - poll.reregister( - &self.conin, - self.write_token, - mio::Ready::empty(), - poll_opts, - )?; - } - Ok(()) - } - - #[inline] - fn deregister(&mut self, poll: &mio::Poll) -> io::Result<()> { - poll.deregister(&self.conout)?; - poll.deregister(&self.conin)?; - Ok(()) - } - - #[inline] - fn reader(&mut self) -> &mut NamedPipe { - &mut self.conout - } - - #[inline] - fn read_token(&self) -> mio::Token { - self.read_token - } - - #[inline] - fn writer(&mut self) -> &mut NamedPipe { - &mut self.conin - } - - #[inline] - fn write_token(&self) -> mio::Token { - self.write_token - } -} - -impl<'a> OnResize for Winpty<'a> { - fn on_resize(&mut self, sizeinfo: &SizeInfo) { - let (cols, lines) = (sizeinfo.cols().0, sizeinfo.lines().0); - if cols > 0 && cols <= u16::MAX as usize && lines > 0 && lines <= u16::MAX as usize { - self.set_size(cols as u16, lines as u16) - .unwrap_or_else(|_| info!("Unable to set winpty size, did it die?")); - } - } -} |