mirror of
https://github.com/wez/wezterm.git
synced 2024-12-25 14:22:37 +03:00
Allow deferred attach of domains
This adds some plumbing so that a domain can indicate whether it is attached or not, but is not yet smart enough to detect a closed connection and mark itself as detached.
This commit is contained in:
parent
b5266078a9
commit
c9489d391b
32
src/main.rs
32
src/main.rs
@ -16,10 +16,10 @@ mod opengl;
|
||||
mod ratelim;
|
||||
mod server;
|
||||
use crate::frontend::FrontEndSelection;
|
||||
use crate::mux::domain::{alloc_domain_id, Domain, LocalDomain};
|
||||
use crate::mux::domain::{Domain, LocalDomain};
|
||||
use crate::mux::Mux;
|
||||
use crate::server::client::Client;
|
||||
use crate::server::domain::ClientDomain;
|
||||
use crate::server::domain::{ClientDomain, ClientDomainConfig};
|
||||
use portable_pty::cmdbuilder::CommandBuilder;
|
||||
|
||||
mod font;
|
||||
@ -171,30 +171,30 @@ fn run_terminal_gui(config: Arc<config::Config>, opts: &StartCommand) -> Fallibl
|
||||
let gui = front_end.try_new(&mux)?;
|
||||
domain.attach()?;
|
||||
|
||||
fn attach_client(mux: &Rc<Mux>, client: ClientDomain) -> Fallible<()> {
|
||||
fn record_domain(mux: &Rc<Mux>, client: ClientDomain) -> Fallible<Arc<dyn Domain>> {
|
||||
let domain: Arc<dyn Domain> = Arc::new(client);
|
||||
mux.add_domain(&domain);
|
||||
domain.attach()
|
||||
Ok(domain)
|
||||
}
|
||||
|
||||
if front_end != FrontEndSelection::MuxServer && !opts.no_auto_connect {
|
||||
for unix_dom in &config.unix_domains {
|
||||
let dom = record_domain(
|
||||
&mux,
|
||||
ClientDomain::new(ClientDomainConfig::Unix(unix_dom.clone())),
|
||||
)?;
|
||||
if unix_dom.connect_automatically {
|
||||
let domain_id = alloc_domain_id();
|
||||
attach_client(
|
||||
&mux,
|
||||
ClientDomain::new(Client::new_unix_domain(domain_id, &config, unix_dom)?),
|
||||
)?;
|
||||
dom.attach()?;
|
||||
}
|
||||
}
|
||||
|
||||
for tls_client in &config.tls_clients {
|
||||
let dom = record_domain(
|
||||
&mux,
|
||||
ClientDomain::new(ClientDomainConfig::Tls(tls_client.clone())),
|
||||
)?;
|
||||
if tls_client.connect_automatically {
|
||||
let domain_id = alloc_domain_id();
|
||||
attach_client(
|
||||
&mux,
|
||||
ClientDomain::new(Client::new_tls(domain_id, &config, tls_client)?),
|
||||
)?;
|
||||
dom.attach()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -207,6 +207,10 @@ fn run_terminal_gui(config: Arc<config::Config>, opts: &StartCommand) -> Fallibl
|
||||
gui.spawn_new_window(mux.config(), &fontconfig, &tab, window_id)?;
|
||||
}
|
||||
|
||||
for dom in mux.iter_domains() {
|
||||
log::error!("domain {} state {:?}", dom.domain_id(), dom.state());
|
||||
}
|
||||
|
||||
gui.run_forever()
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,12 @@ use std::sync::Arc;
|
||||
static DOMAIN_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
|
||||
pub type DomainId = usize;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DomainState {
|
||||
Detached,
|
||||
Attached,
|
||||
}
|
||||
|
||||
pub fn alloc_domain_id() -> DomainId {
|
||||
DOMAIN_ID.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
@ -40,6 +46,12 @@ pub trait Domain: Downcast {
|
||||
|
||||
/// Re-attach to any tabs that might be pre-existing in this domain
|
||||
fn attach(&self) -> Fallible<()>;
|
||||
|
||||
/// Detach all tabs
|
||||
fn detach(&self) -> Fallible<()>;
|
||||
|
||||
/// Indicates the state of the domain
|
||||
fn state(&self) -> DomainState;
|
||||
}
|
||||
impl_downcast!(Domain);
|
||||
|
||||
@ -105,4 +117,12 @@ impl Domain for LocalDomain {
|
||||
fn attach(&self) -> Fallible<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn detach(&self) -> Fallible<()> {
|
||||
failure::bail!("detach not implemented");
|
||||
}
|
||||
|
||||
fn state(&self) -> DomainState {
|
||||
DomainState::Attached
|
||||
}
|
||||
}
|
||||
|
@ -269,6 +269,10 @@ impl Mux {
|
||||
pub fn iter_windows(&self) -> Vec<WindowId> {
|
||||
self.windows.borrow().keys().cloned().collect()
|
||||
}
|
||||
|
||||
pub fn iter_domains(&self) -> Vec<Arc<dyn Domain>> {
|
||||
self.domains.borrow().values().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
|
@ -1,14 +1,16 @@
|
||||
use crate::config::{TlsDomainClient, UnixDomain};
|
||||
use crate::font::{FontConfiguration, FontSystemSelection};
|
||||
use crate::frontend::front_end;
|
||||
use crate::mux::domain::{Domain, DomainId};
|
||||
use crate::mux::domain::{alloc_domain_id, Domain, DomainId, DomainState};
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
use crate::server::client::Client;
|
||||
use crate::server::codec::Spawn;
|
||||
use crate::server::tab::ClientTab;
|
||||
use failure::Fallible;
|
||||
use failure::{err_msg, Fallible};
|
||||
use portable_pty::{CommandBuilder, PtySize};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -52,13 +54,13 @@ impl ClientInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientDomain {
|
||||
inner: Arc<ClientInner>,
|
||||
pub enum ClientDomainConfig {
|
||||
Unix(UnixDomain),
|
||||
Tls(TlsDomainClient),
|
||||
}
|
||||
|
||||
impl ClientInner {
|
||||
pub fn new(client: Client) -> Self {
|
||||
let local_domain_id = client.local_domain_id();
|
||||
pub fn new(local_domain_id: DomainId, client: Client) -> Self {
|
||||
// Assumption: that the domain id on the other end is
|
||||
// always the first created default domain. In the future
|
||||
// we'll add a way to discover/enumerate domains to populate
|
||||
@ -74,14 +76,29 @@ impl ClientInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientDomain {
|
||||
config: ClientDomainConfig,
|
||||
inner: RefCell<Option<Arc<ClientInner>>>,
|
||||
local_domain_id: DomainId,
|
||||
}
|
||||
|
||||
impl ClientDomain {
|
||||
pub fn new(client: Client) -> Self {
|
||||
let inner = Arc::new(ClientInner::new(client));
|
||||
Self { inner }
|
||||
pub fn new(config: ClientDomainConfig) -> Self {
|
||||
let local_domain_id = alloc_domain_id();
|
||||
Self {
|
||||
config,
|
||||
inner: RefCell::new(None),
|
||||
local_domain_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn inner(&self) -> Option<Arc<ClientInner>> {
|
||||
self.inner.borrow().as_ref().map(|i| Arc::clone(i))
|
||||
}
|
||||
|
||||
pub fn remote_to_local_tab_id(&self, remote_tab_id: TabId) -> Option<TabId> {
|
||||
let mut tab_map = self.inner.remote_to_local_tab.lock().unwrap();
|
||||
let inner = self.inner()?;
|
||||
let mut tab_map = inner.remote_to_local_tab.lock().unwrap();
|
||||
|
||||
if let Some(id) = tab_map.get(&remote_tab_id) {
|
||||
return Some(*id);
|
||||
@ -104,7 +121,7 @@ impl ClientDomain {
|
||||
|
||||
impl Domain for ClientDomain {
|
||||
fn domain_id(&self) -> DomainId {
|
||||
self.inner.local_domain_id
|
||||
self.local_domain_id
|
||||
}
|
||||
|
||||
fn spawn(
|
||||
@ -113,24 +130,25 @@ impl Domain for ClientDomain {
|
||||
command: Option<CommandBuilder>,
|
||||
window: WindowId,
|
||||
) -> Fallible<Rc<dyn Tab>> {
|
||||
let inner = self
|
||||
.inner()
|
||||
.ok_or_else(|| err_msg("domain is not attached"))?;
|
||||
let remote_tab_id = {
|
||||
let result = self
|
||||
.inner
|
||||
let result = inner
|
||||
.client
|
||||
.spawn(Spawn {
|
||||
domain_id: self.inner.remote_domain_id,
|
||||
window_id: self.inner.local_to_remote_window(window),
|
||||
domain_id: inner.remote_domain_id,
|
||||
window_id: inner.local_to_remote_window(window),
|
||||
size,
|
||||
command,
|
||||
})
|
||||
.wait()?;
|
||||
|
||||
self.inner
|
||||
.record_remote_to_local_window_mapping(result.window_id, window);
|
||||
inner.record_remote_to_local_window_mapping(result.window_id, window);
|
||||
|
||||
result.tab_id
|
||||
};
|
||||
let tab: Rc<dyn Tab> = Rc::new(ClientTab::new(&self.inner, remote_tab_id, size));
|
||||
let tab: Rc<dyn Tab> = Rc::new(ClientTab::new(&inner, remote_tab_id, size));
|
||||
let mux = Mux::get().unwrap();
|
||||
mux.add_tab(&tab)?;
|
||||
mux.add_tab_to_window(&tab, window)?;
|
||||
@ -140,7 +158,19 @@ impl Domain for ClientDomain {
|
||||
|
||||
fn attach(&self) -> Fallible<()> {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tabs = self.inner.client.list_tabs().wait()?;
|
||||
let client = match &self.config {
|
||||
ClientDomainConfig::Unix(unix) => {
|
||||
Client::new_unix_domain(self.local_domain_id, mux.config(), unix)?
|
||||
}
|
||||
ClientDomainConfig::Tls(tls) => {
|
||||
Client::new_tls(self.local_domain_id, mux.config(), tls)?
|
||||
}
|
||||
};
|
||||
|
||||
let inner = Arc::new(ClientInner::new(self.local_domain_id, client));
|
||||
*self.inner.borrow_mut() = Some(Arc::clone(&inner));
|
||||
|
||||
let tabs = inner.client.list_tabs().wait()?;
|
||||
log::error!("ListTabs result {:#?}", tabs);
|
||||
|
||||
for entry in tabs.tabs.iter() {
|
||||
@ -150,10 +180,10 @@ impl Domain for ClientDomain {
|
||||
entry.window_id,
|
||||
entry.title
|
||||
);
|
||||
let tab: Rc<dyn Tab> = Rc::new(ClientTab::new(&self.inner, entry.tab_id, entry.size));
|
||||
let tab: Rc<dyn Tab> = Rc::new(ClientTab::new(&inner, entry.tab_id, entry.size));
|
||||
mux.add_tab(&tab)?;
|
||||
|
||||
if let Some(local_window_id) = self.inner.remote_to_local_window(entry.window_id) {
|
||||
if let Some(local_window_id) = inner.remote_to_local_window(entry.window_id) {
|
||||
let mut window = mux
|
||||
.get_window_mut(local_window_id)
|
||||
.expect("no such window!?");
|
||||
@ -166,8 +196,7 @@ impl Domain for ClientDomain {
|
||||
FontSystemSelection::get_default(),
|
||||
));
|
||||
let local_window_id = mux.new_empty_window();
|
||||
self.inner
|
||||
.record_remote_to_local_window_mapping(entry.window_id, local_window_id);
|
||||
inner.record_remote_to_local_window_mapping(entry.window_id, local_window_id);
|
||||
mux.add_tab_to_window(&tab, local_window_id)?;
|
||||
|
||||
front_end()
|
||||
@ -176,6 +205,19 @@ impl Domain for ClientDomain {
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn detach(&self) -> Fallible<()> {
|
||||
failure::bail!("detach not implemented");
|
||||
}
|
||||
|
||||
fn state(&self) -> DomainState {
|
||||
if self.inner.borrow().is_some() {
|
||||
DomainState::Attached
|
||||
} else {
|
||||
DomainState::Detached
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user