diff options
Diffstat (limited to 'alacritty_terminal/src/tty/windows/automatic_backend.rs')
-rw-r--r-- | alacritty_terminal/src/tty/windows/automatic_backend.rs | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/alacritty_terminal/src/tty/windows/automatic_backend.rs b/alacritty_terminal/src/tty/windows/automatic_backend.rs new file mode 100644 index 00000000..74a546dd --- /dev/null +++ b/alacritty_terminal/src/tty/windows/automatic_backend.rs @@ -0,0 +1,189 @@ +/// Types to determine the appropriate PTY backend at runtime. +/// +/// Unless the winpty feature is disabled, the PTY backend will automatically fall back to +/// WinPTY when the newer ConPTY API is not supported, as long as the user hasn't explicitly +/// opted into the WinPTY config option. +use std::io::{self, Read, Write}; + +use log::info; +use mio::{Evented, Poll, PollOpt, Ready, Token}; +use mio_anonymous_pipes::{EventedAnonRead, EventedAnonWrite}; +use mio_named_pipes::NamedPipe; + +use crate::config::Config; +use crate::event::OnResize; +use crate::term::SizeInfo; + +use super::{conpty, winpty, Pty}; + +pub fn new<C>(config: &Config<C>, size: &SizeInfo, window_id: Option<usize>) -> Pty { + if let Some(pty) = conpty::new(config, size, window_id) { + info!("Using ConPTY backend"); + pty + } else { + info!("Using WinPTY backend"); + winpty::new(config, size, window_id) + } +} + +pub enum PtyBackend { + Winpty(winpty::Agent), + Conpty(conpty::Conpty), +} + +impl OnResize for PtyBackend { + fn on_resize(&mut self, size: &SizeInfo) { + match self { + PtyBackend::Winpty(w) => w.on_resize(size), + PtyBackend::Conpty(c) => c.on_resize(size), + } + } +} + +// TODO: The ConPTY API currently must use synchronous pipes as the input +// and output handles. This has led to the need to support two different +// types of pipe. +// +// When https://github.com/Microsoft/console/issues/262 lands then the +// Anonymous variant of this enum can be removed from the codebase and +// everything can just use NamedPipe. +pub enum EventedReadablePipe { + Anonymous(EventedAnonRead), + Named(NamedPipe), +} + +pub enum EventedWritablePipe { + Anonymous(EventedAnonWrite), + Named(NamedPipe), +} + +impl Evented for EventedReadablePipe { + fn register( + &self, + poll: &Poll, + token: Token, + interest: Ready, + opts: PollOpt, + ) -> io::Result<()> { + match self { + EventedReadablePipe::Anonymous(p) => p.register(poll, token, interest, opts), + EventedReadablePipe::Named(p) => p.register(poll, token, interest, opts), + } + } + + fn reregister( + &self, + poll: &Poll, + token: Token, + interest: Ready, + opts: PollOpt, + ) -> io::Result<()> { + match self { + EventedReadablePipe::Anonymous(p) => p.reregister(poll, token, interest, opts), + EventedReadablePipe::Named(p) => p.reregister(poll, token, interest, opts), + } + } + + fn deregister(&self, poll: &Poll) -> io::Result<()> { + match self { + EventedReadablePipe::Anonymous(p) => p.deregister(poll), + EventedReadablePipe::Named(p) => p.deregister(poll), + } + } +} + +impl Read for EventedReadablePipe { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + match self { + EventedReadablePipe::Anonymous(p) => p.read(buf), + EventedReadablePipe::Named(p) => p.read(buf), + } + } +} + +impl Evented for EventedWritablePipe { + fn register( + &self, + poll: &Poll, + token: Token, + interest: Ready, + opts: PollOpt, + ) -> io::Result<()> { + match self { + EventedWritablePipe::Anonymous(p) => p.register(poll, token, interest, opts), + EventedWritablePipe::Named(p) => p.register(poll, token, interest, opts), + } + } + + fn reregister( + &self, + poll: &Poll, + token: Token, + interest: Ready, + opts: PollOpt, + ) -> io::Result<()> { + match self { + EventedWritablePipe::Anonymous(p) => p.reregister(poll, token, interest, opts), + EventedWritablePipe::Named(p) => p.reregister(poll, token, interest, opts), + } + } + + fn deregister(&self, poll: &Poll) -> io::Result<()> { + match self { + EventedWritablePipe::Anonymous(p) => p.deregister(poll), + EventedWritablePipe::Named(p) => p.deregister(poll), + } + } +} + +impl Write for EventedWritablePipe { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + match self { + EventedWritablePipe::Anonymous(p) => p.write(buf), + EventedWritablePipe::Named(p) => p.write(buf), + } + } + + fn flush(&mut self) -> io::Result<()> { + match self { + EventedWritablePipe::Anonymous(p) => p.flush(), + EventedWritablePipe::Named(p) => p.flush(), + } + } +} + +impl From<winpty::Agent> for PtyBackend { + fn from(inner: winpty::Agent) -> Self { + PtyBackend::Winpty(inner) + } +} + +impl From<conpty::Conpty> for PtyBackend { + fn from(inner: conpty::Conpty) -> Self { + PtyBackend::Conpty(inner) + } +} + +impl From<EventedAnonRead> for EventedReadablePipe { + fn from(inner: EventedAnonRead) -> Self { + EventedReadablePipe::Anonymous(inner) + } +} + +impl From<NamedPipe> for EventedReadablePipe { + fn from(inner: NamedPipe) -> Self { + EventedReadablePipe::Named(inner) + } +} + +impl From<EventedAnonWrite> for EventedWritablePipe { + fn from(inner: EventedAnonWrite) -> Self { + EventedWritablePipe::Anonymous(inner) + } +} + +impl From<NamedPipe> for EventedWritablePipe { + fn from(inner: NamedPipe) -> Self { + EventedWritablePipe::Named(inner) + } +} |