1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-11 07:03:35 +03:00
wezterm/src/frontend/mod.rs
Wez Furlong acc895f1cd avoid deadlock while pasting large chunks of text
A big paste could saturate the input/output of the pty and
lead to an effective deadlock; the application wants to send
output to us but we are busy trying to write the paste to it.

Break up large pastes into chunks and send them piece by piece.
This does mean that a large bracketed paste is not an atomic
unit any longer, but it seems to work out ok when pasting into
vim.
2019-03-23 15:25:49 -07:00

108 lines
3.1 KiB
Rust

use crate::config::Config;
use crate::font::FontConfiguration;
use crate::mux::tab::Tab;
use crate::mux::Mux;
use failure::Error;
use promise::Executor;
use serde_derive::*;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
pub mod glium;
pub mod guicommon;
pub mod muxserver;
#[cfg(all(unix, not(feature = "force-glutin"), not(target_os = "macos")))]
pub mod xwindows;
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum FrontEndSelection {
Glutin,
X11,
MuxServer,
Null,
}
impl Default for FrontEndSelection {
fn default() -> Self {
if cfg!(feature = "force-glutin") {
FrontEndSelection::Glutin
} else if cfg!(all(unix, not(target_os = "macos"))) {
FrontEndSelection::X11
} else {
FrontEndSelection::Glutin
}
}
}
thread_local! {
static EXECUTOR: RefCell<Option<Box<Executor>>> = RefCell::new(None);
}
pub fn gui_executor() -> Option<Box<Executor>> {
let mut res = None;
EXECUTOR.with(|exec| {
if let Some(exec) = &*exec.borrow() {
res = Some(exec.clone_executor());
}
});
res
}
impl FrontEndSelection {
pub fn try_new(self, mux: &Rc<Mux>) -> Result<Rc<FrontEnd>, Error> {
let front_end = match self {
FrontEndSelection::Glutin => glium::glutinloop::GlutinFrontEnd::try_new(mux),
#[cfg(all(unix, not(target_os = "macos")))]
FrontEndSelection::X11 => xwindows::x11loop::X11FrontEnd::try_new(mux),
#[cfg(not(all(unix, not(target_os = "macos"))))]
FrontEndSelection::X11 => bail!("X11 not compiled in"),
FrontEndSelection::MuxServer => muxserver::MuxServerFrontEnd::try_new(mux),
FrontEndSelection::Null => muxserver::MuxServerFrontEnd::new_null(mux),
}?;
EXECUTOR.with(|exec| {
*exec.borrow_mut() = Some(front_end.gui_executor());
});
Ok(front_end)
}
// TODO: find or build a proc macro for this
pub fn variants() -> Vec<&'static str> {
vec!["Glutin", "X11", "MuxServer", "Null"]
}
}
impl std::str::FromStr for FrontEndSelection {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"glutin" => Ok(FrontEndSelection::Glutin),
"x11" => Ok(FrontEndSelection::X11),
"muxserver" => Ok(FrontEndSelection::MuxServer),
"null" => Ok(FrontEndSelection::Null),
_ => Err(format_err!(
"{} is not a valid FrontEndSelection variant, possible values are {:?}",
s,
FrontEndSelection::variants()
)),
}
}
}
pub trait FrontEnd {
/// Run the event loop. Does not return until there is either a fatal
/// error, or until there are no more windows left to manage.
fn run_forever(&self) -> Result<(), Error>;
fn spawn_new_window(
&self,
config: &Arc<Config>,
fontconfig: &Rc<FontConfiguration>,
tab: &Rc<Tab>,
) -> Result<(), Error>;
fn gui_executor(&self) -> Box<Executor>;
}