From f642bd56d645d1caeb7b5712c1282c027a288417 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Tue, 26 Mar 2019 08:22:16 -0700 Subject: [PATCH] introduce mux Domain concept All locations that were setting up ptys now do so via the Domain concept. We still need a way to set up a persistent global domain. --- pty/src/lib.rs | 11 +++++++ src/frontend/glium/glutinloop.rs | 2 +- src/frontend/guicommon/window.rs | 26 +++++---------- src/frontend/xwindows/x11loop.rs | 2 +- src/main.rs | 50 +++++++++-------------------- src/mux/domain.rs | 54 ++++++++++++++++++++++++++++++++ src/mux/mod.rs | 1 + 7 files changed, 90 insertions(+), 56 deletions(-) create mode 100644 src/mux/domain.rs diff --git a/pty/src/lib.rs b/pty/src/lib.rs index 0d323b9cc..f1c8733b3 100644 --- a/pty/src/lib.rs +++ b/pty/src/lib.rs @@ -64,6 +64,17 @@ pub struct PtySize { pub pixel_height: u16, } +impl Default for PtySize { + fn default() -> Self { + PtySize { + rows: 24, + cols: 80, + pixel_width: 0, + pixel_height: 0, + } + } +} + /// Represents the master/control end of the pty pub trait MasterPty: std::io::Write { /// Inform the kernel and thus the child process that the window resized. diff --git a/src/frontend/glium/glutinloop.rs b/src/frontend/glium/glutinloop.rs index 7f51f6776..e56f00fb6 100644 --- a/src/frontend/glium/glutinloop.rs +++ b/src/frontend/glium/glutinloop.rs @@ -215,7 +215,7 @@ impl GuiEventLoop { config: &Arc, fonts: &Rc, ) -> Result<(), Error> { - let tab = spawn_tab(&config, None)?; + let tab = spawn_tab(&config)?; // FIXME: Domain self.mux.add_tab(self.gui_executor(), &tab)?; let events = Self::get().expect("to be called on gui thread"); let window = GliumTerminalWindow::new(&events, &fonts, &config, &tab)?; diff --git a/src/frontend/guicommon/window.rs b/src/frontend/guicommon/window.rs index 6635a5874..88da422ad 100644 --- a/src/frontend/guicommon/window.rs +++ b/src/frontend/guicommon/window.rs @@ -1,6 +1,6 @@ use crate::config::Config; use crate::font::FontConfiguration; -use crate::frontend::guicommon::localtab::LocalTab; +use crate::mux::domain::{Domain, LocalDomain}; use crate::mux::tab::{Tab, TabId}; use crate::mux::window::WindowId; use crate::mux::Mux; @@ -8,7 +8,7 @@ use crate::opengl::render::Renderer; use crate::opengl::textureatlas::OutOfTextureSpace; use failure::{format_err, Error}; use glium; -use portable_pty::{PtySize, PtySystemSelection}; +use portable_pty::PtySize; use std::rc::Rc; use std::sync::Arc; @@ -157,35 +157,23 @@ pub trait TerminalWindow { fn spawn_tab(&mut self) -> Result { let config = self.config(); + let domain = LocalDomain::new(config)?; // FIXME: Domain let dims = self.get_dimensions(); let rows = (dims.height as usize + 1) / dims.cell_height; let cols = (dims.width as usize + 1) / dims.cell_width; - let pty_sys = PtySystemSelection::default().get()?; - let (pty, slave) = pty_sys.openpty(PtySize { + let size = PtySize { rows: rows as u16, cols: cols as u16, pixel_width: dims.width, pixel_height: dims.height, - })?; - let cmd = config.build_prog(None)?; + }; - let process = slave.spawn_command(cmd)?; - eprintln!("spawned: {:?}", process); - - let mux = Mux::get().unwrap(); - - let terminal = term::Terminal::new( - rows, - cols, - config.scrollback_lines.unwrap_or(3500), - config.hyperlink_rules.clone(), - ); - - let tab: Rc = Rc::new(LocalTab::new(terminal, process, pty)); + let tab = domain.spawn(size, None)?; let tab_id = tab.tab_id(); + let mux = Mux::get().unwrap(); let len = { let mut window = mux diff --git a/src/frontend/xwindows/x11loop.rs b/src/frontend/xwindows/x11loop.rs index 8a64a9a00..db61eadfe 100644 --- a/src/frontend/xwindows/x11loop.rs +++ b/src/frontend/xwindows/x11loop.rs @@ -213,7 +213,7 @@ impl GuiEventLoop { config: &Arc, fonts: &Rc, ) -> Result<(), Error> { - let tab = spawn_tab(&config, None)?; + let tab = spawn_tab(&config)?; // FIXME: Domain self.mux.add_tab(self.gui_executor(), &tab)?; let events = Self::get().expect("to be called on gui thread"); let window = X11TerminalWindow::new(&events, &fonts, &config, &tab)?; diff --git a/src/main.rs b/src/main.rs index 44ace3eb0..01bd981c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,10 +15,11 @@ mod frontend; mod mux; mod opengl; mod server; -use crate::frontend::guicommon::localtab::LocalTab; use crate::frontend::{FrontEnd, FrontEndSelection}; +use crate::mux::domain::{Domain, LocalDomain}; use crate::mux::tab::Tab; use crate::mux::Mux; +use portable_pty::cmdbuilder::CommandBuilder; mod font; use crate::font::{FontConfiguration, FontSystemSelection}; @@ -118,7 +119,10 @@ fn run_terminal_gui(config: Arc, opts: &StartCommand) -> Result< let fontconfig = Rc::new(FontConfiguration::new(Arc::clone(&config), font_system)); let cmd = if !opts.prog.is_empty() { - Some(opts.prog.iter().map(|x| x.as_os_str()).collect()) + let argv: Vec<&std::ffi::OsStr> = opts.prog.iter().map(|x| x.as_os_str()).collect(); + let mut builder = CommandBuilder::new(&argv[0]); + builder.args(&argv[1..]); + Some(builder) } else { None }; @@ -129,7 +133,9 @@ fn run_terminal_gui(config: Arc, opts: &StartCommand) -> Result< let front_end = opts.front_end.unwrap_or(config.front_end); let gui = front_end.try_new(&mux)?; - spawn_window(&mux, &*gui, cmd, &fontconfig)?; + let domain = LocalDomain::new(&config)?; + + spawn_window(&mux, &domain, &*gui, cmd, &fontconfig)?; gui.run_forever() } @@ -185,45 +191,19 @@ fn main() -> Result<(), Error> { } } -fn spawn_tab( - config: &Arc, - cmd: Option>, -) -> Result, Error> { - let cmd = config.build_prog(cmd)?; - - let initial_cols = 80u16; - let initial_rows = 24u16; - let initial_pixel_width = 0; - let initial_pixel_height = 0; - - let pty_sys = config.pty.get()?; - let (master, slave) = pty_sys.openpty(PtySize { - rows: initial_rows, - cols: initial_cols, - pixel_width: initial_pixel_width, - pixel_height: initial_pixel_height, - })?; - - let child = slave.spawn_command(cmd)?; - eprintln!("spawned: {:?}", child); - - let terminal = term::Terminal::new( - initial_rows as usize, - initial_cols as usize, - config.scrollback_lines.unwrap_or(3500), - config.hyperlink_rules.clone(), - ); - - Ok(Rc::new(LocalTab::new(terminal, child, master))) +fn spawn_tab(config: &Arc) -> Result, Error> { + let domain = LocalDomain::new(config)?; + domain.spawn(PtySize::default(), None) } fn spawn_window( mux: &Rc, + domain: &Domain, gui: &FrontEnd, - cmd: Option>, + cmd: Option, fontconfig: &Rc, ) -> Result<(), Error> { - let tab = spawn_tab(mux.config(), cmd)?; + let tab = domain.spawn(PtySize::default(), cmd)?; mux.add_tab(gui.gui_executor(), &tab)?; gui.spawn_new_window(mux.config(), &fontconfig, &tab) diff --git a/src/mux/domain.rs b/src/mux/domain.rs new file mode 100644 index 000000000..e4fbdc3f3 --- /dev/null +++ b/src/mux/domain.rs @@ -0,0 +1,54 @@ +//! A Domain represents an instance of a multiplexer. +//! For example, the gui frontend has its own domain, +//! and we can connect to a domain hosted by a mux server +//! that may be local, running "remotely" inside a WSL +//! container or actually remote, running on the other end +//! of an ssh session somewhere. + +use crate::config::Config; +use crate::frontend::guicommon::localtab::LocalTab; +use crate::mux::tab::Tab; +use failure::Error; +use portable_pty::cmdbuilder::CommandBuilder; +use portable_pty::{PtySize, PtySystem}; +use std::rc::Rc; +use std::sync::Arc; + +pub trait Domain { + /// Spawn a new command within this domain + fn spawn(&self, size: PtySize, command: Option) -> Result, Error>; +} + +pub struct LocalDomain { + pty_system: Box, + config: Arc, +} + +impl LocalDomain { + pub fn new(config: &Arc) -> Result { + let config = Arc::clone(config); + let pty_system = config.pty.get()?; + Ok(Self { pty_system, config }) + } +} + +impl Domain for LocalDomain { + fn spawn(&self, size: PtySize, command: Option) -> Result, Error> { + let cmd = match command { + Some(c) => c, + None => self.config.build_prog(None)?, + }; + let (master, slave) = self.pty_system.openpty(size)?; + let child = slave.spawn_command(cmd)?; + eprintln!("spawned: {:?}", child); + + let terminal = term::Terminal::new( + size.rows as usize, + size.cols as usize, + self.config.scrollback_lines.unwrap_or(3500), + self.config.hyperlink_rules.clone(), + ); + + Ok(Rc::new(LocalTab::new(terminal, child, master))) + } +} diff --git a/src/mux/mod.rs b/src/mux/mod.rs index 2e8e88c8c..9eef680dd 100644 --- a/src/mux/mod.rs +++ b/src/mux/mod.rs @@ -12,6 +12,7 @@ use std::thread; use term::TerminalHost; use termwiz::hyperlink::Hyperlink; +pub mod domain; pub mod renderable; pub mod tab; pub mod window;