alacritty/alacritty_terminal/src/tty/windows/automatic_backend.rs

191 lines
5.2 KiB
Rust

//! 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)
}
}