summaryrefslogtreecommitdiff
path: root/src/tty/windows.rs
diff options
context:
space:
mode:
authorDavid Hewitt <1939362+davidhewitt@users.noreply.github.com>2018-12-28 16:01:58 +0000
committerChristian Duerr <chrisduerr@users.noreply.github.com>2018-12-28 16:01:58 +0000
commitf1bc6802e1d0d03feaa43e61c2bf465795a96da9 (patch)
treed2b993eb020631ca1de14b47eb0d9213ee37dd90 /src/tty/windows.rs
parentec6f756946c998d327316d370b381003e51d3a70 (diff)
downloadalacritty-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.rs286
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?"));
- }
- }
-}