mirror of
https://github.com/wez/wezterm.git
synced 2024-11-25 21:07:39 +03:00
mux: Pane is now required to be Send+Sync. Use Arc<dyn Pane>
This commit is contained in:
parent
758a09f55f
commit
6e06b9af02
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2918,6 +2918,7 @@ dependencies = [
|
|||||||
"names",
|
"names",
|
||||||
"nix 0.25.1",
|
"nix 0.25.1",
|
||||||
"ntapi",
|
"ntapi",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"portable-pty",
|
"portable-pty",
|
||||||
"procinfo",
|
"procinfo",
|
||||||
@ -5781,6 +5782,7 @@ dependencies = [
|
|||||||
"metrics",
|
"metrics",
|
||||||
"mux",
|
"mux",
|
||||||
"openssl",
|
"openssl",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
"portable-pty",
|
"portable-pty",
|
||||||
"promise",
|
"promise",
|
||||||
"rangeset",
|
"rangeset",
|
||||||
@ -5918,6 +5920,7 @@ dependencies = [
|
|||||||
"mux-lua",
|
"mux-lua",
|
||||||
"open",
|
"open",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
|
"parking_lot 0.12.1",
|
||||||
"portable-pty",
|
"portable-pty",
|
||||||
"promise",
|
"promise",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use luahelper::dynamic_to_lua_value;
|
use luahelper::dynamic_to_lua_value;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct MuxPane(pub PaneId);
|
pub struct MuxPane(pub PaneId);
|
||||||
|
|
||||||
impl MuxPane {
|
impl MuxPane {
|
||||||
pub fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Rc<dyn Pane>> {
|
pub fn resolve<'a>(&self, mux: &'a Rc<Mux>) -> mlua::Result<Arc<dyn Pane>> {
|
||||||
mux.get_pane(self.0)
|
mux.get_pane(self.0)
|
||||||
.ok_or_else(|| mlua::Error::external(format!("pane id {} not found in mux", self.0)))
|
.ok_or_else(|| mlua::Error::external(format!("pane id {} not found in mux", self.0)))
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ metrics = { version="0.17", features=["std"]}
|
|||||||
mlua = "0.8.3"
|
mlua = "0.8.3"
|
||||||
names = { version = "0.12", default-features = false }
|
names = { version = "0.12", default-features = false }
|
||||||
nix = {version="0.25", features=["term"]}
|
nix = {version="0.25", features=["term"]}
|
||||||
|
parking_lot = "0.12"
|
||||||
percent-encoding = "2"
|
percent-encoding = "2"
|
||||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||||
procinfo = { path = "../procinfo" }
|
procinfo = { path = "../procinfo" }
|
||||||
|
@ -74,7 +74,7 @@ pub trait Domain: Downcast {
|
|||||||
tab: TabId,
|
tab: TabId,
|
||||||
pane_id: PaneId,
|
pane_id: PaneId,
|
||||||
split_request: SplitRequest,
|
split_request: SplitRequest,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
let tab = match mux.get_tab(tab) {
|
let tab = match mux.get_tab(tab) {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
@ -124,7 +124,7 @@ pub trait Domain: Downcast {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tab.split_and_insert(pane_index, split_request, Rc::clone(&pane))?;
|
tab.split_and_insert(pane_index, split_request, Arc::clone(&pane))?;
|
||||||
Ok(pane)
|
Ok(pane)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ pub trait Domain: Downcast {
|
|||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
command: Option<CommandBuilder>,
|
command: Option<CommandBuilder>,
|
||||||
command_dir: Option<String>,
|
command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>>;
|
) -> anyhow::Result<Arc<dyn Pane>>;
|
||||||
|
|
||||||
/// Returns false if the `spawn` method will never succeed.
|
/// Returns false if the `spawn` method will never succeed.
|
||||||
/// There are some internal placeholder domains that are
|
/// There are some internal placeholder domains that are
|
||||||
@ -475,7 +475,7 @@ impl Domain for LocalDomain {
|
|||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
command: Option<CommandBuilder>,
|
command: Option<CommandBuilder>,
|
||||||
command_dir: Option<String>,
|
command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
let pane_id = alloc_pane_id();
|
let pane_id = alloc_pane_id();
|
||||||
let cmd = self.build_command(command, command_dir, pane_id).await?;
|
let cmd = self.build_command(command, command_dir, pane_id).await?;
|
||||||
let pair = self
|
let pair = self
|
||||||
@ -510,7 +510,7 @@ impl Domain for LocalDomain {
|
|||||||
terminal.enable_conpty_quirks();
|
terminal.enable_conpty_quirks();
|
||||||
}
|
}
|
||||||
|
|
||||||
let pane: Rc<dyn Pane> = Rc::new(LocalPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(LocalPane::new(
|
||||||
pane_id,
|
pane_id,
|
||||||
terminal,
|
terminal,
|
||||||
child,
|
child,
|
||||||
|
@ -82,7 +82,7 @@ static SUB_ID: AtomicUsize = AtomicUsize::new(0);
|
|||||||
|
|
||||||
pub struct Mux {
|
pub struct Mux {
|
||||||
tabs: RefCell<HashMap<TabId, Rc<Tab>>>,
|
tabs: RefCell<HashMap<TabId, Rc<Tab>>>,
|
||||||
panes: RefCell<HashMap<PaneId, Rc<dyn Pane>>>,
|
panes: RefCell<HashMap<PaneId, Arc<dyn Pane>>>,
|
||||||
windows: RefCell<HashMap<WindowId, Window>>,
|
windows: RefCell<HashMap<WindowId, Window>>,
|
||||||
default_domain: RefCell<Option<Arc<dyn Domain>>>,
|
default_domain: RefCell<Option<Arc<dyn Domain>>>,
|
||||||
domains: RefCell<HashMap<DomainId, Arc<dyn Domain>>>,
|
domains: RefCell<HashMap<DomainId, Arc<dyn Domain>>>,
|
||||||
@ -616,15 +616,15 @@ impl Mux {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pane(&self, pane_id: PaneId) -> Option<Rc<dyn Pane>> {
|
pub fn get_pane(&self, pane_id: PaneId) -> Option<Arc<dyn Pane>> {
|
||||||
self.panes.borrow().get(&pane_id).map(Rc::clone)
|
self.panes.borrow().get(&pane_id).map(Arc::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_tab(&self, tab_id: TabId) -> Option<Rc<Tab>> {
|
pub fn get_tab(&self, tab_id: TabId) -> Option<Rc<Tab>> {
|
||||||
self.tabs.borrow().get(&tab_id).map(Rc::clone)
|
self.tabs.borrow().get(&tab_id).map(Rc::clone)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_pane(&self, pane: &Rc<dyn Pane>) -> Result<(), Error> {
|
pub fn add_pane(&self, pane: &Arc<dyn Pane>) -> Result<(), Error> {
|
||||||
if self.panes.borrow().contains_key(&pane.pane_id()) {
|
if self.panes.borrow().contains_key(&pane.pane_id()) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -639,7 +639,7 @@ impl Mux {
|
|||||||
|
|
||||||
self.panes
|
self.panes
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(pane.pane_id(), Rc::clone(pane));
|
.insert(pane.pane_id(), Arc::clone(pane));
|
||||||
let pane_id = pane.pane_id();
|
let pane_id = pane.pane_id();
|
||||||
if let Some(reader) = pane.reader()? {
|
if let Some(reader) = pane.reader()? {
|
||||||
let banner = self.banner.borrow().clone();
|
let banner = self.banner.borrow().clone();
|
||||||
@ -857,11 +857,11 @@ impl Mux {
|
|||||||
self.is_workspace_empty(&workspace)
|
self.is_workspace_empty(&workspace)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_panes(&self) -> Vec<Rc<dyn Pane>> {
|
pub fn iter_panes(&self) -> Vec<Arc<dyn Pane>> {
|
||||||
self.panes
|
self.panes
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, v)| Rc::clone(v))
|
.map(|(_, v)| Arc::clone(v))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -965,7 +965,7 @@ impl Mux {
|
|||||||
fn resolve_cwd(
|
fn resolve_cwd(
|
||||||
&self,
|
&self,
|
||||||
command_dir: Option<String>,
|
command_dir: Option<String>,
|
||||||
pane: Option<Rc<dyn Pane>>,
|
pane: Option<Arc<dyn Pane>>,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
command_dir.or_else(|| {
|
command_dir.or_else(|| {
|
||||||
match pane {
|
match pane {
|
||||||
@ -1000,7 +1000,7 @@ impl Mux {
|
|||||||
request: SplitRequest,
|
request: SplitRequest,
|
||||||
source: SplitSource,
|
source: SplitSource,
|
||||||
domain: config::keyassignment::SpawnTabDomain,
|
domain: config::keyassignment::SpawnTabDomain,
|
||||||
) -> anyhow::Result<(Rc<dyn Pane>, TerminalSize)> {
|
) -> anyhow::Result<(Arc<dyn Pane>, TerminalSize)> {
|
||||||
let (_pane_domain_id, window_id, tab_id) = self
|
let (_pane_domain_id, window_id, tab_id) = self
|
||||||
.resolve_pane_id(pane_id)
|
.resolve_pane_id(pane_id)
|
||||||
.ok_or_else(|| anyhow!("pane_id {} invalid", pane_id))?;
|
.ok_or_else(|| anyhow!("pane_id {} invalid", pane_id))?;
|
||||||
@ -1024,7 +1024,7 @@ impl Mux {
|
|||||||
command_dir,
|
command_dir,
|
||||||
} => SplitSource::Spawn {
|
} => SplitSource::Spawn {
|
||||||
command,
|
command,
|
||||||
command_dir: self.resolve_cwd(command_dir, Some(Rc::clone(¤t_pane))),
|
command_dir: self.resolve_cwd(command_dir, Some(Arc::clone(¤t_pane))),
|
||||||
},
|
},
|
||||||
other => other,
|
other => other,
|
||||||
};
|
};
|
||||||
@ -1105,7 +1105,7 @@ impl Mux {
|
|||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
current_pane_id: Option<PaneId>,
|
current_pane_id: Option<PaneId>,
|
||||||
workspace_for_new_window: String,
|
workspace_for_new_window: String,
|
||||||
) -> anyhow::Result<(Rc<Tab>, Rc<dyn Pane>, WindowId)> {
|
) -> anyhow::Result<(Rc<Tab>, Arc<dyn Pane>, WindowId)> {
|
||||||
let domain = self
|
let domain = self
|
||||||
.resolve_spawn_tab_domain(current_pane_id, &domain)
|
.resolve_spawn_tab_domain(current_pane_id, &domain)
|
||||||
.context("resolve_spawn_tab_domain")?;
|
.context("resolve_spawn_tab_domain")?;
|
||||||
|
@ -10,12 +10,12 @@ use anyhow::Error;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use config::keyassignment::ScrollbackEraseMode;
|
use config::keyassignment::ScrollbackEraseMode;
|
||||||
use config::{configuration, ExitBehavior};
|
use config::{configuration, ExitBehavior};
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||||
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty, PtySize};
|
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty, PtySize};
|
||||||
use procinfo::LocalProcessInfo;
|
use procinfo::LocalProcessInfo;
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use smol::channel::{bounded, Receiver, TryRecvError};
|
use smol::channel::{bounded, Receiver, TryRecvError};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::{RefCell, RefMut};
|
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::io::{Result as IoResult, Write};
|
use std::io::{Result as IoResult, Write};
|
||||||
@ -39,7 +39,7 @@ enum ProcessState {
|
|||||||
Running {
|
Running {
|
||||||
child_waiter: Receiver<IoResult<ExitStatus>>,
|
child_waiter: Receiver<IoResult<ExitStatus>>,
|
||||||
pid: Option<u32>,
|
pid: Option<u32>,
|
||||||
signaller: Box<dyn ChildKiller>,
|
signaller: Box<dyn ChildKiller + Send + Sync>,
|
||||||
// Whether we've explicitly killed the child
|
// Whether we've explicitly killed the child
|
||||||
killed: bool,
|
killed: bool,
|
||||||
},
|
},
|
||||||
@ -57,13 +57,13 @@ struct CachedProcInfo {
|
|||||||
|
|
||||||
pub struct LocalPane {
|
pub struct LocalPane {
|
||||||
pane_id: PaneId,
|
pane_id: PaneId,
|
||||||
terminal: RefCell<Terminal>,
|
terminal: Mutex<Terminal>,
|
||||||
process: RefCell<ProcessState>,
|
process: Mutex<ProcessState>,
|
||||||
pty: RefCell<Box<dyn MasterPty>>,
|
pty: Mutex<Box<dyn MasterPty + Send>>,
|
||||||
writer: RefCell<Box<dyn Write>>,
|
writer: Mutex<Box<dyn Write + Send>>,
|
||||||
domain_id: DomainId,
|
domain_id: DomainId,
|
||||||
tmux_domain: RefCell<Option<Arc<TmuxDomainState>>>,
|
tmux_domain: Mutex<Option<Arc<TmuxDomainState>>>,
|
||||||
proc_list: RefCell<Option<CachedProcInfo>>,
|
proc_list: Mutex<Option<CachedProcInfo>>,
|
||||||
command_description: String,
|
command_description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ impl Pane for LocalPane {
|
|||||||
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
|
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(tio) = self.pty.borrow().get_termios() {
|
if let Some(tio) = self.pty.lock().get_termios() {
|
||||||
use nix::sys::termios::LocalFlags;
|
use nix::sys::termios::LocalFlags;
|
||||||
// Detect whether we might be in password input mode.
|
// Detect whether we might be in password input mode.
|
||||||
// If local echo is disabled and canonical input mode
|
// If local echo is disabled and canonical input mode
|
||||||
@ -96,19 +96,19 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||||
let mut cursor = terminal_get_cursor_position(&mut self.terminal.borrow_mut());
|
let mut cursor = terminal_get_cursor_position(&mut self.terminal.lock());
|
||||||
if self.tmux_domain.borrow().is_some() {
|
if self.tmux_domain.lock().is_some() {
|
||||||
cursor.visibility = termwiz::surface::CursorVisibility::Hidden;
|
cursor.visibility = termwiz::surface::CursorVisibility::Hidden;
|
||||||
}
|
}
|
||||||
cursor
|
cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_keyboard_encoding(&self) -> KeyboardEncoding {
|
fn get_keyboard_encoding(&self) -> KeyboardEncoding {
|
||||||
self.terminal.borrow().get_keyboard_encoding()
|
self.terminal.lock().get_keyboard_encoding()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_seqno(&self) -> SequenceNo {
|
fn get_current_seqno(&self) -> SequenceNo {
|
||||||
self.terminal.borrow().current_seqno()
|
self.terminal.lock().current_seqno()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_changed_since(
|
fn get_changed_since(
|
||||||
@ -116,7 +116,7 @@ impl Pane for LocalPane {
|
|||||||
lines: Range<StableRowIndex>,
|
lines: Range<StableRowIndex>,
|
||||||
seqno: SequenceNo,
|
seqno: SequenceNo,
|
||||||
) -> RangeSet<StableRowIndex> {
|
) -> RangeSet<StableRowIndex> {
|
||||||
terminal_get_dirty_lines(&mut self.terminal.borrow_mut(), lines, seqno)
|
terminal_get_dirty_lines(&mut self.terminal.lock(), lines, seqno)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_each_logical_line_in_stable_range_mut(
|
fn for_each_logical_line_in_stable_range_mut(
|
||||||
@ -125,14 +125,14 @@ impl Pane for LocalPane {
|
|||||||
for_line: &mut dyn ForEachPaneLogicalLine,
|
for_line: &mut dyn ForEachPaneLogicalLine,
|
||||||
) {
|
) {
|
||||||
terminal_for_each_logical_line_in_stable_range_mut(
|
terminal_for_each_logical_line_in_stable_range_mut(
|
||||||
&mut self.terminal.borrow_mut(),
|
&mut self.terminal.lock(),
|
||||||
lines,
|
lines,
|
||||||
for_line,
|
for_line,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
||||||
terminal_with_lines_mut(&mut self.terminal.borrow_mut(), lines, with_lines)
|
terminal_with_lines_mut(&mut self.terminal.lock(), lines, with_lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
||||||
@ -144,15 +144,15 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_dimensions(&self) -> RenderableDimensions {
|
fn get_dimensions(&self) -> RenderableDimensions {
|
||||||
terminal_get_dimensions(&mut self.terminal.borrow_mut())
|
terminal_get_dimensions(&mut self.terminal.lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_user_vars(&self) -> HashMap<String, String> {
|
fn copy_user_vars(&self) -> HashMap<String, String> {
|
||||||
self.terminal.borrow().user_vars().clone()
|
self.terminal.lock().user_vars().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill(&self) {
|
fn kill(&self) {
|
||||||
let mut proc = self.process.borrow_mut();
|
let mut proc = self.process.lock();
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"killing process in pane {}, state is {:?}",
|
"killing process in pane {}, state is {:?}",
|
||||||
self.pane_id,
|
self.pane_id,
|
||||||
@ -173,7 +173,7 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
fn is_dead(&self) -> bool {
|
||||||
let mut proc = self.process.borrow_mut();
|
let mut proc = self.process.lock();
|
||||||
let mut notify = None;
|
let mut notify = None;
|
||||||
|
|
||||||
const EXIT_BEHAVIOR: &str = "This message is shown because \
|
const EXIT_BEHAVIOR: &str = "This message is shown because \
|
||||||
@ -255,79 +255,82 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_clipboard(&self, clipboard: &Arc<dyn Clipboard>) {
|
fn set_clipboard(&self, clipboard: &Arc<dyn Clipboard>) {
|
||||||
self.terminal.borrow_mut().set_clipboard(clipboard);
|
self.terminal.lock().set_clipboard(clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_download_handler(&self, handler: &Arc<dyn DownloadHandler>) {
|
fn set_download_handler(&self, handler: &Arc<dyn DownloadHandler>) {
|
||||||
self.terminal.borrow_mut().set_download_handler(handler);
|
self.terminal.lock().set_download_handler(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_config(&self, config: Arc<dyn TerminalConfiguration>) {
|
fn set_config(&self, config: Arc<dyn TerminalConfiguration>) {
|
||||||
self.terminal.borrow_mut().set_config(config);
|
self.terminal.lock().set_config(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config(&self) -> Option<Arc<dyn TerminalConfiguration>> {
|
fn get_config(&self) -> Option<Arc<dyn TerminalConfiguration>> {
|
||||||
Some(self.terminal.borrow().get_config())
|
Some(self.terminal.lock().get_config())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_actions(&self, actions: Vec<termwiz::escape::Action>) {
|
fn perform_actions(&self, actions: Vec<termwiz::escape::Action>) {
|
||||||
self.terminal.borrow_mut().perform_actions(actions)
|
self.terminal.lock().perform_actions(actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_event(&self, event: MouseEvent) -> Result<(), Error> {
|
fn mouse_event(&self, event: MouseEvent) -> Result<(), Error> {
|
||||||
Mux::get().unwrap().record_input_for_current_identity();
|
Mux::get().unwrap().record_input_for_current_identity();
|
||||||
self.terminal.borrow_mut().mouse_event(event)
|
self.terminal.lock().mouse_event(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> Result<(), Error> {
|
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> Result<(), Error> {
|
||||||
Mux::get().unwrap().record_input_for_current_identity();
|
Mux::get().unwrap().record_input_for_current_identity();
|
||||||
if self.tmux_domain.borrow().is_some() {
|
if self.tmux_domain.lock().is_some() {
|
||||||
log::error!("key: {:?}", key);
|
log::error!("key: {:?}", key);
|
||||||
if key == KeyCode::Char('q') {
|
if key == KeyCode::Char('q') {
|
||||||
self.terminal.borrow_mut().send_paste("detach\n")?;
|
self.terminal.lock().send_paste("detach\n")?;
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
self.terminal.borrow_mut().key_down(key, mods)
|
self.terminal.lock().key_down(key, mods)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_up(&self, key: KeyCode, mods: KeyModifiers) -> Result<(), Error> {
|
fn key_up(&self, key: KeyCode, mods: KeyModifiers) -> Result<(), Error> {
|
||||||
Mux::get().unwrap().record_input_for_current_identity();
|
Mux::get().unwrap().record_input_for_current_identity();
|
||||||
self.terminal.borrow_mut().key_up(key, mods)
|
self.terminal.lock().key_up(key, mods)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, size: TerminalSize) -> Result<(), Error> {
|
fn resize(&self, size: TerminalSize) -> Result<(), Error> {
|
||||||
self.pty.borrow_mut().resize(PtySize {
|
self.pty.lock().resize(PtySize {
|
||||||
rows: size.rows.try_into()?,
|
rows: size.rows.try_into()?,
|
||||||
cols: size.cols.try_into()?,
|
cols: size.cols.try_into()?,
|
||||||
pixel_width: size.pixel_width.try_into()?,
|
pixel_width: size.pixel_width.try_into()?,
|
||||||
pixel_height: size.pixel_height.try_into()?,
|
pixel_height: size.pixel_height.try_into()?,
|
||||||
})?;
|
})?;
|
||||||
self.terminal.borrow_mut().resize(size);
|
self.terminal.lock().resize(size);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
Mux::get().unwrap().record_input_for_current_identity();
|
Mux::get().unwrap().record_input_for_current_identity();
|
||||||
self.writer.borrow_mut()
|
MutexGuard::map(self.writer.lock(), |writer| {
|
||||||
|
let w: &mut dyn std::io::Write = writer;
|
||||||
|
w
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
||||||
Ok(Some(self.pty.borrow_mut().try_clone_reader()?))
|
Ok(Some(self.pty.lock().try_clone_reader()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_paste(&self, text: &str) -> Result<(), Error> {
|
fn send_paste(&self, text: &str) -> Result<(), Error> {
|
||||||
Mux::get().unwrap().record_input_for_current_identity();
|
Mux::get().unwrap().record_input_for_current_identity();
|
||||||
if self.tmux_domain.borrow().is_some() {
|
if self.tmux_domain.lock().is_some() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
self.terminal.borrow_mut().send_paste(text)
|
self.terminal.lock().send_paste(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_title(&self) -> String {
|
fn get_title(&self) -> String {
|
||||||
let title = self.terminal.borrow_mut().get_title().to_string();
|
let title = self.terminal.lock().get_title().to_string();
|
||||||
// If the title is the default pane title, then try to spice
|
// If the title is the default pane title, then try to spice
|
||||||
// things up a bit by returning the process basename instead
|
// things up a bit by returning the process basename instead
|
||||||
if title == "wezterm" {
|
if title == "wezterm" {
|
||||||
@ -343,7 +346,7 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn palette(&self) -> ColorPalette {
|
fn palette(&self) -> ColorPalette {
|
||||||
self.terminal.borrow().palette()
|
self.terminal.lock().palette()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_id(&self) -> DomainId {
|
fn domain_id(&self) -> DomainId {
|
||||||
@ -353,41 +356,41 @@ impl Pane for LocalPane {
|
|||||||
fn erase_scrollback(&self, erase_mode: ScrollbackEraseMode) {
|
fn erase_scrollback(&self, erase_mode: ScrollbackEraseMode) {
|
||||||
match erase_mode {
|
match erase_mode {
|
||||||
ScrollbackEraseMode::ScrollbackOnly => {
|
ScrollbackEraseMode::ScrollbackOnly => {
|
||||||
self.terminal.borrow_mut().erase_scrollback();
|
self.terminal.lock().erase_scrollback();
|
||||||
}
|
}
|
||||||
ScrollbackEraseMode::ScrollbackAndViewport => {
|
ScrollbackEraseMode::ScrollbackAndViewport => {
|
||||||
self.terminal.borrow_mut().erase_scrollback_and_viewport();
|
self.terminal.lock().erase_scrollback_and_viewport();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_changed(&self, focused: bool) {
|
fn focus_changed(&self, focused: bool) {
|
||||||
self.terminal.borrow_mut().focus_changed(focused);
|
self.terminal.lock().focus_changed(focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_unseen_output(&self) -> bool {
|
fn has_unseen_output(&self) -> bool {
|
||||||
self.terminal.borrow().has_unseen_output()
|
self.terminal.lock().has_unseen_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_mouse_grabbed(&self) -> bool {
|
fn is_mouse_grabbed(&self) -> bool {
|
||||||
if self.tmux_domain.borrow().is_some() {
|
if self.tmux_domain.lock().is_some() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
self.terminal.borrow().is_mouse_grabbed()
|
self.terminal.lock().is_mouse_grabbed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_alt_screen_active(&self) -> bool {
|
fn is_alt_screen_active(&self) -> bool {
|
||||||
if self.tmux_domain.borrow().is_some() {
|
if self.tmux_domain.lock().is_some() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
self.terminal.borrow().is_alt_screen_active()
|
self.terminal.lock().is_alt_screen_active()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_working_dir(&self) -> Option<Url> {
|
fn get_current_working_dir(&self) -> Option<Url> {
|
||||||
self.terminal
|
self.terminal
|
||||||
.borrow()
|
.lock()
|
||||||
.get_current_dir()
|
.get_current_dir()
|
||||||
.cloned()
|
.cloned()
|
||||||
.or_else(|| self.divine_current_working_dir())
|
.or_else(|| self.divine_current_working_dir())
|
||||||
@ -395,7 +398,7 @@ impl Pane for LocalPane {
|
|||||||
|
|
||||||
fn get_foreground_process_info(&self) -> Option<LocalProcessInfo> {
|
fn get_foreground_process_info(&self) -> Option<LocalProcessInfo> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(pid) = self.pty.borrow().process_group_leader() {
|
if let Some(pid) = self.pty.lock().process_group_leader() {
|
||||||
return LocalProcessInfo::with_root_pid(pid as u32);
|
return LocalProcessInfo::with_root_pid(pid as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +407,7 @@ impl Pane for LocalPane {
|
|||||||
|
|
||||||
fn get_foreground_process_name(&self) -> Option<String> {
|
fn get_foreground_process_name(&self) -> Option<String> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(pid) = self.pty.borrow().process_group_leader() {
|
if let Some(pid) = self.pty.lock().process_group_leader() {
|
||||||
if let Some(path) = LocalProcessInfo::executable_path(pid as u32) {
|
if let Some(path) = LocalProcessInfo::executable_path(pid as u32) {
|
||||||
return Some(path.to_string_lossy().to_string());
|
return Some(path.to_string_lossy().to_string());
|
||||||
}
|
}
|
||||||
@ -478,7 +481,7 @@ impl Pane for LocalPane {
|
|||||||
// If the process is dead but exit_behavior is holding the
|
// If the process is dead but exit_behavior is holding the
|
||||||
// window, we don't need to prompt to confirm closing.
|
// window, we don't need to prompt to confirm closing.
|
||||||
// That is detectable as no longer having a process group leader.
|
// That is detectable as no longer having a process group leader.
|
||||||
if self.pty.borrow().process_group_leader().is_none() {
|
if self.pty.lock().process_group_leader().is_none() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,7 +491,7 @@ impl Pane for LocalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_semantic_zones(&self) -> anyhow::Result<Vec<SemanticZone>> {
|
fn get_semantic_zones(&self) -> anyhow::Result<Vec<SemanticZone>> {
|
||||||
let mut term = self.terminal.borrow_mut();
|
let mut term = self.terminal.lock();
|
||||||
term.get_semantic_zones()
|
term.get_semantic_zones()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +501,7 @@ impl Pane for LocalPane {
|
|||||||
range: Range<StableRowIndex>,
|
range: Range<StableRowIndex>,
|
||||||
limit: Option<u32>,
|
limit: Option<u32>,
|
||||||
) -> anyhow::Result<Vec<SearchResult>> {
|
) -> anyhow::Result<Vec<SearchResult>> {
|
||||||
let term = self.terminal.borrow();
|
let term = self.terminal.lock();
|
||||||
let screen = term.screen();
|
let screen = term.screen();
|
||||||
|
|
||||||
enum CompiledPattern {
|
enum CompiledPattern {
|
||||||
@ -713,9 +716,7 @@ impl wezterm_term::DeviceControlHandler for LocalPaneDCSHandler {
|
|||||||
|
|
||||||
if let Some(pane) = mux.get_pane(self.pane_id) {
|
if let Some(pane) = mux.get_pane(self.pane_id) {
|
||||||
let pane = pane.downcast_ref::<LocalPane>().unwrap();
|
let pane = pane.downcast_ref::<LocalPane>().unwrap();
|
||||||
pane.tmux_domain
|
pane.tmux_domain.lock().replace(Arc::clone(&tmux_domain));
|
||||||
.borrow_mut()
|
|
||||||
.replace(Arc::clone(&tmux_domain));
|
|
||||||
|
|
||||||
emit_output_for_pane(
|
emit_output_for_pane(
|
||||||
self.pane_id,
|
self.pane_id,
|
||||||
@ -737,7 +738,7 @@ impl wezterm_term::DeviceControlHandler for LocalPaneDCSHandler {
|
|||||||
let mux = Mux::get().expect("to be called on main thread");
|
let mux = Mux::get().expect("to be called on main thread");
|
||||||
if let Some(pane) = mux.get_pane(self.pane_id) {
|
if let Some(pane) = mux.get_pane(self.pane_id) {
|
||||||
let pane = pane.downcast_ref::<LocalPane>().unwrap();
|
let pane = pane.downcast_ref::<LocalPane>().unwrap();
|
||||||
pane.tmux_domain.borrow_mut().take();
|
pane.tmux_domain.lock().take();
|
||||||
}
|
}
|
||||||
mux.domain_was_detached(tmux.domain_id);
|
mux.domain_was_detached(tmux.domain_id);
|
||||||
}
|
}
|
||||||
@ -808,7 +809,7 @@ fn split_child(
|
|||||||
mut process: Box<dyn Child + Send>,
|
mut process: Box<dyn Child + Send>,
|
||||||
) -> (
|
) -> (
|
||||||
Receiver<IoResult<ExitStatus>>,
|
Receiver<IoResult<ExitStatus>>,
|
||||||
Box<dyn ChildKiller>,
|
Box<dyn ChildKiller + Send + Sync>,
|
||||||
Option<u32>,
|
Option<u32>,
|
||||||
) {
|
) {
|
||||||
let pid = process.process_id();
|
let pid = process.process_id();
|
||||||
@ -834,8 +835,8 @@ impl LocalPane {
|
|||||||
pane_id: PaneId,
|
pane_id: PaneId,
|
||||||
mut terminal: Terminal,
|
mut terminal: Terminal,
|
||||||
process: Box<dyn Child + Send>,
|
process: Box<dyn Child + Send>,
|
||||||
pty: Box<dyn MasterPty>,
|
pty: Box<dyn MasterPty + Send>,
|
||||||
writer: Box<dyn Write>,
|
writer: Box<dyn Write + Send>,
|
||||||
domain_id: DomainId,
|
domain_id: DomainId,
|
||||||
command_description: String,
|
command_description: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -849,25 +850,25 @@ impl LocalPane {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
pane_id,
|
pane_id,
|
||||||
terminal: RefCell::new(terminal),
|
terminal: Mutex::new(terminal),
|
||||||
process: RefCell::new(ProcessState::Running {
|
process: Mutex::new(ProcessState::Running {
|
||||||
child_waiter: process,
|
child_waiter: process,
|
||||||
pid,
|
pid,
|
||||||
signaller,
|
signaller,
|
||||||
killed: false,
|
killed: false,
|
||||||
}),
|
}),
|
||||||
pty: RefCell::new(pty),
|
pty: Mutex::new(pty),
|
||||||
writer: RefCell::new(writer),
|
writer: Mutex::new(writer),
|
||||||
domain_id,
|
domain_id,
|
||||||
tmux_domain: RefCell::new(None),
|
tmux_domain: Mutex::new(None),
|
||||||
proc_list: RefCell::new(None),
|
proc_list: Mutex::new(None),
|
||||||
command_description,
|
command_description,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divine_current_working_dir(&self) -> Option<Url> {
|
fn divine_current_working_dir(&self) -> Option<Url> {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(pid) = self.pty.borrow().process_group_leader() {
|
if let Some(pid) = self.pty.lock().process_group_leader() {
|
||||||
if let Some(path) = LocalProcessInfo::current_working_dir(pid as u32) {
|
if let Some(path) = LocalProcessInfo::current_working_dir(pid as u32) {
|
||||||
return Url::parse(&format!("file://localhost{}", path.display())).ok();
|
return Url::parse(&format!("file://localhost{}", path.display())).ok();
|
||||||
}
|
}
|
||||||
@ -885,9 +886,9 @@ impl LocalPane {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divine_process_list(&self, force_refresh: bool) -> Option<RefMut<CachedProcInfo>> {
|
fn divine_process_list(&self, force_refresh: bool) -> Option<MappedMutexGuard<CachedProcInfo>> {
|
||||||
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
|
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.lock() {
|
||||||
let mut proc_list = self.proc_list.borrow_mut();
|
let mut proc_list = self.proc_list.lock();
|
||||||
|
|
||||||
let expired = force_refresh
|
let expired = force_refresh
|
||||||
|| proc_list
|
|| proc_list
|
||||||
@ -934,7 +935,7 @@ impl LocalPane {
|
|||||||
log::trace!("CachedProcInfo updated");
|
log::trace!("CachedProcInfo updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(RefMut::map(proc_list, |info| info.as_mut().unwrap()));
|
return Some(MutexGuard::map(proc_list, |info| info.as_mut().unwrap()));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -953,7 +954,7 @@ impl Drop for LocalPane {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Avoid lingering zombies if we can, but don't block forever.
|
// Avoid lingering zombies if we can, but don't block forever.
|
||||||
// <https://github.com/wez/wezterm/issues/558>
|
// <https://github.com/wez/wezterm/issues/558>
|
||||||
if let ProcessState::Running { signaller, .. } = &mut *self.process.borrow_mut() {
|
if let ProcessState::Running { signaller, .. } = &mut *self.process.lock() {
|
||||||
let _ = signaller.kill();
|
let _ = signaller.kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@ use crate::Mux;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use config::keyassignment::{KeyAssignment, ScrollbackEraseMode};
|
use config::keyassignment::{KeyAssignment, ScrollbackEraseMode};
|
||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex};
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::RefMut;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Arc;
|
||||||
use termwiz::hyperlink::Rule;
|
use termwiz::hyperlink::Rule;
|
||||||
use termwiz::input::KeyboardEncoding;
|
use termwiz::input::KeyboardEncoding;
|
||||||
use termwiz::surface::{Line, SequenceNo};
|
use termwiz::surface::{Line, SequenceNo};
|
||||||
@ -107,7 +107,7 @@ struct Paste {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn paste_next_chunk(paste: &Arc<Mutex<Paste>>) {
|
fn paste_next_chunk(paste: &Arc<Mutex<Paste>>) {
|
||||||
let mut locked = paste.lock().unwrap();
|
let mut locked = paste.lock();
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
let pane = mux.get_pane(locked.pane_id).unwrap();
|
let pane = mux.get_pane(locked.pane_id).unwrap();
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ impl LogicalLine {
|
|||||||
|
|
||||||
/// A Pane represents a view on a terminal
|
/// A Pane represents a view on a terminal
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
pub trait Pane: Downcast {
|
pub trait Pane: Downcast + Send + Sync {
|
||||||
fn pane_id(&self) -> PaneId;
|
fn pane_id(&self) -> PaneId;
|
||||||
|
|
||||||
/// Returns the 0-based cursor position relative to the top left of
|
/// Returns the 0-based cursor position relative to the top left of
|
||||||
@ -256,7 +256,7 @@ pub trait Pane: Downcast {
|
|||||||
fn get_title(&self) -> String;
|
fn get_title(&self) -> String;
|
||||||
fn send_paste(&self, text: &str) -> anyhow::Result<()>;
|
fn send_paste(&self, text: &str) -> anyhow::Result<()>;
|
||||||
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>>;
|
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>>;
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write>;
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write>;
|
||||||
fn resize(&self, size: TerminalSize) -> anyhow::Result<()>;
|
fn resize(&self, size: TerminalSize) -> anyhow::Result<()>;
|
||||||
/// Called as a hint that the pane is being resized as part of
|
/// Called as a hint that the pane is being resized as part of
|
||||||
/// a zoom-to-fill-all-the-tab-space operation.
|
/// a zoom-to-fill-all-the-tab-space operation.
|
||||||
@ -562,12 +562,12 @@ pub fn impl_get_lines_via_with_lines<P: Pane + ?Sized>(
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use k9::snapshot;
|
use k9::snapshot;
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
|
||||||
use termwiz::surface::SEQ_ZERO;
|
use termwiz::surface::SEQ_ZERO;
|
||||||
|
|
||||||
struct FakePane {
|
struct FakePane {
|
||||||
lines: RefCell<Vec<Line>>,
|
lines: Mutex<Vec<Line>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pane for FakePane {
|
impl Pane for FakePane {
|
||||||
@ -596,7 +596,7 @@ mod test {
|
|||||||
with_lines: &mut dyn WithPaneLines,
|
with_lines: &mut dyn WithPaneLines,
|
||||||
) {
|
) {
|
||||||
let mut line_refs = vec![];
|
let mut line_refs = vec![];
|
||||||
let mut lines = self.lines.borrow_mut();
|
let mut lines = self.lines.lock();
|
||||||
for line in lines
|
for line in lines
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.skip(stable_range.start as usize)
|
.skip(stable_range.start as usize)
|
||||||
@ -624,7 +624,7 @@ mod test {
|
|||||||
(
|
(
|
||||||
first,
|
first,
|
||||||
self.lines
|
self.lines
|
||||||
.borrow()
|
.lock()
|
||||||
.iter()
|
.iter()
|
||||||
.skip(lines.start as usize)
|
.skip(lines.start as usize)
|
||||||
.take((lines.end - lines.start) as usize)
|
.take((lines.end - lines.start) as usize)
|
||||||
@ -645,7 +645,7 @@ mod test {
|
|||||||
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn resize(&self, _: TerminalSize) -> anyhow::Result<()> {
|
fn resize(&self, _: TerminalSize) -> anyhow::Result<()> {
|
||||||
@ -739,7 +739,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pane = FakePane {
|
let pane = FakePane {
|
||||||
lines: RefCell::new(physical_lines),
|
lines: Mutex::new(physical_lines),
|
||||||
};
|
};
|
||||||
|
|
||||||
let logical = pane.get_logical_lines(0..30);
|
let logical = pane.get_logical_lines(0..30);
|
||||||
|
@ -13,7 +13,6 @@ use smol::channel::{bounded, Receiver as AsyncReceiver};
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::io::{BufWriter, Read, Write};
|
use std::io::{BufWriter, Read, Write};
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
|
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@ -560,12 +559,12 @@ impl Domain for RemoteSshDomain {
|
|||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
command: Option<CommandBuilder>,
|
command: Option<CommandBuilder>,
|
||||||
command_dir: Option<String>,
|
command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
let pane_id = alloc_pane_id();
|
let pane_id = alloc_pane_id();
|
||||||
|
|
||||||
let (command_line, env) = self.build_command(pane_id, command, command_dir)?;
|
let (command_line, env) = self.build_command(pane_id, command, command_dir)?;
|
||||||
|
|
||||||
let pty: Box<dyn portable_pty::MasterPty>;
|
let pty: Box<dyn portable_pty::MasterPty + Send>;
|
||||||
let child: Box<dyn portable_pty::Child + Send>;
|
let child: Box<dyn portable_pty::Child + Send>;
|
||||||
let writer: BoxedWriter;
|
let writer: BoxedWriter;
|
||||||
|
|
||||||
@ -677,7 +676,7 @@ impl Domain for RemoteSshDomain {
|
|||||||
Box::new(writer.clone()),
|
Box::new(writer.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let pane: Rc<dyn Pane> = Rc::new(LocalPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(LocalPane::new(
|
||||||
pane_id,
|
pane_id,
|
||||||
terminal,
|
terminal,
|
||||||
child,
|
child,
|
||||||
|
@ -10,12 +10,12 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use wezterm_term::{StableRowIndex, TerminalSize};
|
use wezterm_term::{StableRowIndex, TerminalSize};
|
||||||
|
|
||||||
pub type Tree = bintree::Tree<Rc<dyn Pane>, SplitDirectionAndSize>;
|
pub type Tree = bintree::Tree<Arc<dyn Pane>, SplitDirectionAndSize>;
|
||||||
pub type Cursor = bintree::Cursor<Rc<dyn Pane>, SplitDirectionAndSize>;
|
pub type Cursor = bintree::Cursor<Arc<dyn Pane>, SplitDirectionAndSize>;
|
||||||
|
|
||||||
static TAB_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
|
static TAB_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::AtomicUsize::new(0);
|
||||||
pub type TabId = usize;
|
pub type TabId = usize;
|
||||||
@ -43,7 +43,7 @@ pub struct Tab {
|
|||||||
pane: RefCell<Option<Tree>>,
|
pane: RefCell<Option<Tree>>,
|
||||||
size: RefCell<TerminalSize>,
|
size: RefCell<TerminalSize>,
|
||||||
active: RefCell<usize>,
|
active: RefCell<usize>,
|
||||||
zoomed: RefCell<Option<Rc<dyn Pane>>>,
|
zoomed: RefCell<Option<Arc<dyn Pane>>>,
|
||||||
title: RefCell<String>,
|
title: RefCell<String>,
|
||||||
recency: RefCell<Recency>,
|
recency: RefCell<Recency>,
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ pub struct PositionedPane {
|
|||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub pixel_height: usize,
|
pub pixel_height: usize,
|
||||||
/// The pane instance
|
/// The pane instance
|
||||||
pub pane: Rc<dyn Pane>,
|
pub pane: Arc<dyn Pane>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for PositionedPane {
|
impl std::fmt::Debug for PositionedPane {
|
||||||
@ -199,7 +199,7 @@ pub struct PositionedSplit {
|
|||||||
pub size: usize,
|
pub size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_pane(pane: &Rc<dyn Pane>, other: &Option<&Rc<dyn Pane>>) -> bool {
|
fn is_pane(pane: &Arc<dyn Pane>, other: &Option<&Arc<dyn Pane>>) -> bool {
|
||||||
if let Some(other) = other {
|
if let Some(other) = other {
|
||||||
other.pane_id() == pane.pane_id()
|
other.pane_id() == pane.pane_id()
|
||||||
} else {
|
} else {
|
||||||
@ -211,8 +211,8 @@ fn pane_tree(
|
|||||||
tree: &Tree,
|
tree: &Tree,
|
||||||
tab_id: TabId,
|
tab_id: TabId,
|
||||||
window_id: WindowId,
|
window_id: WindowId,
|
||||||
active: Option<&Rc<dyn Pane>>,
|
active: Option<&Arc<dyn Pane>>,
|
||||||
zoomed: Option<&Rc<dyn Pane>>,
|
zoomed: Option<&Arc<dyn Pane>>,
|
||||||
workspace: &str,
|
workspace: &str,
|
||||||
left_col: usize,
|
left_col: usize,
|
||||||
top_row: usize,
|
top_row: usize,
|
||||||
@ -278,12 +278,12 @@ fn pane_tree(
|
|||||||
|
|
||||||
fn build_from_pane_tree<F>(
|
fn build_from_pane_tree<F>(
|
||||||
tree: bintree::Tree<PaneEntry, SplitDirectionAndSize>,
|
tree: bintree::Tree<PaneEntry, SplitDirectionAndSize>,
|
||||||
active: &mut Option<Rc<dyn Pane>>,
|
active: &mut Option<Arc<dyn Pane>>,
|
||||||
zoomed: &mut Option<Rc<dyn Pane>>,
|
zoomed: &mut Option<Arc<dyn Pane>>,
|
||||||
make_pane: &mut F,
|
make_pane: &mut F,
|
||||||
) -> Tree
|
) -> Tree
|
||||||
where
|
where
|
||||||
F: FnMut(PaneEntry) -> Rc<dyn Pane>,
|
F: FnMut(PaneEntry) -> Arc<dyn Pane>,
|
||||||
{
|
{
|
||||||
match tree {
|
match tree {
|
||||||
bintree::Tree::Empty => Tree::Empty,
|
bintree::Tree::Empty => Tree::Empty,
|
||||||
@ -297,10 +297,10 @@ where
|
|||||||
let is_active_pane = entry.is_active_pane;
|
let is_active_pane = entry.is_active_pane;
|
||||||
let pane = make_pane(entry);
|
let pane = make_pane(entry);
|
||||||
if is_zoomed_pane {
|
if is_zoomed_pane {
|
||||||
zoomed.replace(Rc::clone(&pane));
|
zoomed.replace(Arc::clone(&pane));
|
||||||
}
|
}
|
||||||
if is_active_pane {
|
if is_active_pane {
|
||||||
active.replace(Rc::clone(&pane));
|
active.replace(Arc::clone(&pane));
|
||||||
}
|
}
|
||||||
Tree::Leaf(pane)
|
Tree::Leaf(pane)
|
||||||
}
|
}
|
||||||
@ -533,7 +533,7 @@ impl Tab {
|
|||||||
/// a new pane, otherwise the pane won't poll/update in the GUI.
|
/// a new pane, otherwise the pane won't poll/update in the GUI.
|
||||||
pub fn sync_with_pane_tree<F>(&self, size: TerminalSize, root: PaneNode, mut make_pane: F)
|
pub fn sync_with_pane_tree<F>(&self, size: TerminalSize, root: PaneNode, mut make_pane: F)
|
||||||
where
|
where
|
||||||
F: FnMut(PaneEntry) -> Rc<dyn Pane>,
|
F: FnMut(PaneEntry) -> Arc<dyn Pane>,
|
||||||
{
|
{
|
||||||
let mut active = None;
|
let mut active = None;
|
||||||
let mut zoomed = None;
|
let mut zoomed = None;
|
||||||
@ -781,7 +781,7 @@ impl Tab {
|
|||||||
pixel_width: size.pixel_width.into(),
|
pixel_width: size.pixel_width.into(),
|
||||||
height: size.rows.into(),
|
height: size.rows.into(),
|
||||||
pixel_height: size.pixel_height.into(),
|
pixel_height: size.pixel_height.into(),
|
||||||
pane: Rc::clone(zoomed),
|
pane: Arc::clone(zoomed),
|
||||||
});
|
});
|
||||||
return panes;
|
return panes;
|
||||||
}
|
}
|
||||||
@ -813,7 +813,7 @@ impl Tab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pane = Rc::clone(cursor.leaf_mut().unwrap());
|
let pane = Arc::clone(cursor.leaf_mut().unwrap());
|
||||||
let dims = parent_size.unwrap_or_else(|| *self.size.borrow());
|
let dims = parent_size.unwrap_or_else(|| *self.size.borrow());
|
||||||
|
|
||||||
panes.push(PositionedPane {
|
panes.push(PositionedPane {
|
||||||
@ -1366,7 +1366,7 @@ impl Tab {
|
|||||||
/// Remove pane from tab.
|
/// Remove pane from tab.
|
||||||
/// The pane is still live in the mux; the intent is for the pane to
|
/// The pane is still live in the mux; the intent is for the pane to
|
||||||
/// be added to a different tab.
|
/// be added to a different tab.
|
||||||
pub fn remove_pane(&self, pane_id: PaneId) -> Option<Rc<dyn Pane>> {
|
pub fn remove_pane(&self, pane_id: PaneId) -> Option<Arc<dyn Pane>> {
|
||||||
let panes = self.remove_pane_if(|_, pane| pane.pane_id() == pane_id, false);
|
let panes = self.remove_pane_if(|_, pane| pane.pane_id() == pane_id, false);
|
||||||
for pane in panes {
|
for pane in panes {
|
||||||
return Some(pane);
|
return Some(pane);
|
||||||
@ -1374,9 +1374,9 @@ impl Tab {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_pane_if<F>(&self, f: F, kill: bool) -> Vec<Rc<dyn Pane>>
|
fn remove_pane_if<F>(&self, f: F, kill: bool) -> Vec<Arc<dyn Pane>>
|
||||||
where
|
where
|
||||||
F: Fn(usize, &Rc<dyn Pane>) -> bool,
|
F: Fn(usize, &Arc<dyn Pane>) -> bool,
|
||||||
{
|
{
|
||||||
let mut dead_panes = vec![];
|
let mut dead_panes = vec![];
|
||||||
let zoomed_pane = self.zoomed.borrow().as_ref().map(|p| p.pane_id());
|
let zoomed_pane = self.zoomed.borrow().as_ref().map(|p| p.pane_id());
|
||||||
@ -1403,7 +1403,7 @@ impl Tab {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if cursor.is_leaf() {
|
if cursor.is_leaf() {
|
||||||
let pane = Rc::clone(cursor.leaf_mut().unwrap());
|
let pane = Arc::clone(cursor.leaf_mut().unwrap());
|
||||||
if f(pane_index, &pane) {
|
if f(pane_index, &pane) {
|
||||||
removed_indices.push(pane_index);
|
removed_indices.push(pane_index);
|
||||||
if Some(pane.pane_id()) == zoomed_pane {
|
if Some(pane.pane_id()) == zoomed_pane {
|
||||||
@ -1506,15 +1506,15 @@ impl Tab {
|
|||||||
dead_count == panes.len()
|
dead_count == panes.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_active_pane(&self) -> Option<Rc<dyn Pane>> {
|
pub fn get_active_pane(&self) -> Option<Arc<dyn Pane>> {
|
||||||
if let Some(zoomed) = self.zoomed.borrow().as_ref() {
|
if let Some(zoomed) = self.zoomed.borrow().as_ref() {
|
||||||
return Some(Rc::clone(zoomed));
|
return Some(Arc::clone(zoomed));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.iter_panes_ignoring_zoom()
|
self.iter_panes_ignoring_zoom()
|
||||||
.iter()
|
.iter()
|
||||||
.nth(*self.active.borrow())
|
.nth(*self.active.borrow())
|
||||||
.map(|p| Rc::clone(&p.pane))
|
.map(|p| Arc::clone(&p.pane))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@ -1522,7 +1522,7 @@ impl Tab {
|
|||||||
*self.active.borrow()
|
*self.active.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_active_pane(&self, pane: &Rc<dyn Pane>) {
|
pub fn set_active_pane(&self, pane: &Arc<dyn Pane>) {
|
||||||
if let Some(item) = self
|
if let Some(item) = self
|
||||||
.iter_panes_ignoring_zoom()
|
.iter_panes_ignoring_zoom()
|
||||||
.iter()
|
.iter()
|
||||||
@ -1535,7 +1535,7 @@ impl Tab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advise_focus_change(&self, prior: Option<Rc<dyn Pane>>) {
|
fn advise_focus_change(&self, prior: Option<Arc<dyn Pane>>) {
|
||||||
let current = self.get_active_pane();
|
let current = self.get_active_pane();
|
||||||
match (prior, current) {
|
match (prior, current) {
|
||||||
(Some(prior), Some(current)) if prior.pane_id() != current.pane_id() => {
|
(Some(prior), Some(current)) if prior.pane_id() != current.pane_id() => {
|
||||||
@ -1564,8 +1564,8 @@ impl Tab {
|
|||||||
/// Assigns the root pane.
|
/// Assigns the root pane.
|
||||||
/// This is suitable when creating a new tab and then assigning
|
/// This is suitable when creating a new tab and then assigning
|
||||||
/// the initial pane
|
/// the initial pane
|
||||||
pub fn assign_pane(&self, pane: &Rc<dyn Pane>) {
|
pub fn assign_pane(&self, pane: &Arc<dyn Pane>) {
|
||||||
match Tree::new().cursor().assign_top(Rc::clone(pane)) {
|
match Tree::new().cursor().assign_top(Arc::clone(pane)) {
|
||||||
Ok(c) => *self.pane.borrow_mut() = Some(c.tree()),
|
Ok(c) => *self.pane.borrow_mut() = Some(c.tree()),
|
||||||
Err(_) => panic!("tried to assign root pane to non-empty tree"),
|
Err(_) => panic!("tried to assign root pane to non-empty tree"),
|
||||||
}
|
}
|
||||||
@ -1731,7 +1731,7 @@ impl Tab {
|
|||||||
&self,
|
&self,
|
||||||
pane_index: usize,
|
pane_index: usize,
|
||||||
request: SplitRequest,
|
request: SplitRequest,
|
||||||
pane: Rc<dyn Pane>,
|
pane: Arc<dyn Pane>,
|
||||||
) -> anyhow::Result<usize> {
|
) -> anyhow::Result<usize> {
|
||||||
if self.zoomed.borrow().is_some() {
|
if self.zoomed.borrow().is_some() {
|
||||||
anyhow::bail!("cannot split while zoomed");
|
anyhow::bail!("cannot split while zoomed");
|
||||||
@ -1786,9 +1786,9 @@ impl Tab {
|
|||||||
|
|
||||||
if request.top_level && !cursor.is_leaf() {
|
if request.top_level && !cursor.is_leaf() {
|
||||||
let result = if request.target_is_second {
|
let result = if request.target_is_second {
|
||||||
cursor.split_node_and_insert_right(Rc::clone(&pane))
|
cursor.split_node_and_insert_right(Arc::clone(&pane))
|
||||||
} else {
|
} else {
|
||||||
cursor.split_node_and_insert_left(Rc::clone(&pane))
|
cursor.split_node_and_insert_left(Arc::clone(&pane))
|
||||||
};
|
};
|
||||||
cursor = match result {
|
cursor = match result {
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
@ -1820,7 +1820,7 @@ impl Tab {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let existing_pane = Rc::clone(cursor.leaf_mut().unwrap());
|
let existing_pane = Arc::clone(cursor.leaf_mut().unwrap());
|
||||||
|
|
||||||
let (pane1, pane2) = if request.target_is_second {
|
let (pane1, pane2) = if request.target_is_second {
|
||||||
(existing_pane, pane)
|
(existing_pane, pane)
|
||||||
@ -1965,6 +1965,7 @@ impl Into<String> for SerdeUrl {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::renderable::*;
|
use crate::renderable::*;
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex};
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use termwiz::surface::SequenceNo;
|
use termwiz::surface::SequenceNo;
|
||||||
@ -1974,14 +1975,14 @@ mod test {
|
|||||||
|
|
||||||
struct FakePane {
|
struct FakePane {
|
||||||
id: PaneId,
|
id: PaneId,
|
||||||
size: RefCell<TerminalSize>,
|
size: Mutex<TerminalSize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FakePane {
|
impl FakePane {
|
||||||
fn new(id: PaneId, size: TerminalSize) -> Rc<dyn Pane> {
|
fn new(id: PaneId, size: TerminalSize) -> Arc<dyn Pane> {
|
||||||
Rc::new(Self {
|
Arc::new(Self {
|
||||||
id,
|
id,
|
||||||
size: RefCell::new(size),
|
size: Mutex::new(size),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2044,11 +2045,11 @@ mod test {
|
|||||||
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
fn reader(&self) -> anyhow::Result<Option<Box<dyn std::io::Read + Send>>> {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
||||||
*self.size.borrow_mut() = size;
|
*self.size.lock() = size;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ use async_trait::async_trait;
|
|||||||
use config::keyassignment::ScrollbackEraseMode;
|
use config::keyassignment::ScrollbackEraseMode;
|
||||||
use crossbeam::channel::{unbounded as channel, Receiver, Sender};
|
use crossbeam::channel::{unbounded as channel, Receiver, Sender};
|
||||||
use filedescriptor::{FileDescriptor, Pipe};
|
use filedescriptor::{FileDescriptor, Pipe};
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||||
use portable_pty::*;
|
use portable_pty::*;
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use std::cell::{RefCell, RefMut};
|
|
||||||
use std::io::{BufWriter, Write};
|
use std::io::{BufWriter, Write};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -53,7 +53,7 @@ impl Domain for TermWizTerminalDomain {
|
|||||||
_size: TerminalSize,
|
_size: TerminalSize,
|
||||||
_command: Option<CommandBuilder>,
|
_command: Option<CommandBuilder>,
|
||||||
_command_dir: Option<String>,
|
_command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
bail!("cannot spawn panes in a TermWizTerminalPane");
|
bail!("cannot spawn panes in a TermWizTerminalPane");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +84,10 @@ impl Domain for TermWizTerminalDomain {
|
|||||||
pub struct TermWizTerminalPane {
|
pub struct TermWizTerminalPane {
|
||||||
pane_id: PaneId,
|
pane_id: PaneId,
|
||||||
domain_id: DomainId,
|
domain_id: DomainId,
|
||||||
terminal: RefCell<wezterm_term::Terminal>,
|
terminal: Mutex<wezterm_term::Terminal>,
|
||||||
input_tx: Sender<InputEvent>,
|
input_tx: Sender<InputEvent>,
|
||||||
dead: RefCell<bool>,
|
dead: Mutex<bool>,
|
||||||
writer: RefCell<Vec<u8>>,
|
writer: Mutex<Vec<u8>>,
|
||||||
render_rx: FileDescriptor,
|
render_rx: FileDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ impl TermWizTerminalPane {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let pane_id = alloc_pane_id();
|
let pane_id = alloc_pane_id();
|
||||||
|
|
||||||
let terminal = RefCell::new(wezterm_term::Terminal::new(
|
let terminal = Mutex::new(wezterm_term::Terminal::new(
|
||||||
size,
|
size,
|
||||||
term_config.unwrap_or_else(|| Arc::new(config::TermConfig::new())),
|
term_config.unwrap_or_else(|| Arc::new(config::TermConfig::new())),
|
||||||
"WezTerm",
|
"WezTerm",
|
||||||
@ -113,10 +113,10 @@ impl TermWizTerminalPane {
|
|||||||
pane_id,
|
pane_id,
|
||||||
domain_id,
|
domain_id,
|
||||||
terminal,
|
terminal,
|
||||||
writer: RefCell::new(Vec::new()),
|
writer: Mutex::new(Vec::new()),
|
||||||
render_rx,
|
render_rx,
|
||||||
input_tx,
|
input_tx,
|
||||||
dead: RefCell::new(false),
|
dead: Mutex::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,11 +127,11 @@ impl Pane for TermWizTerminalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||||
terminal_get_cursor_position(&mut self.terminal.borrow_mut())
|
terminal_get_cursor_position(&mut self.terminal.lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_seqno(&self) -> SequenceNo {
|
fn get_current_seqno(&self) -> SequenceNo {
|
||||||
self.terminal.borrow().current_seqno()
|
self.terminal.lock().current_seqno()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_changed_since(
|
fn get_changed_since(
|
||||||
@ -139,7 +139,7 @@ impl Pane for TermWizTerminalPane {
|
|||||||
lines: Range<StableRowIndex>,
|
lines: Range<StableRowIndex>,
|
||||||
seqno: SequenceNo,
|
seqno: SequenceNo,
|
||||||
) -> RangeSet<StableRowIndex> {
|
) -> RangeSet<StableRowIndex> {
|
||||||
terminal_get_dirty_lines(&mut self.terminal.borrow_mut(), lines, seqno)
|
terminal_get_dirty_lines(&mut self.terminal.lock(), lines, seqno)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_each_logical_line_in_stable_range_mut(
|
fn for_each_logical_line_in_stable_range_mut(
|
||||||
@ -148,7 +148,7 @@ impl Pane for TermWizTerminalPane {
|
|||||||
for_line: &mut dyn ForEachPaneLogicalLine,
|
for_line: &mut dyn ForEachPaneLogicalLine,
|
||||||
) {
|
) {
|
||||||
terminal_for_each_logical_line_in_stable_range_mut(
|
terminal_for_each_logical_line_in_stable_range_mut(
|
||||||
&mut self.terminal.borrow_mut(),
|
&mut self.terminal.lock(),
|
||||||
lines,
|
lines,
|
||||||
for_line,
|
for_line,
|
||||||
);
|
);
|
||||||
@ -159,19 +159,19 @@ impl Pane for TermWizTerminalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
||||||
terminal_with_lines_mut(&mut self.terminal.borrow_mut(), lines, with_lines)
|
terminal_with_lines_mut(&mut self.terminal.lock(), lines, with_lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
||||||
terminal_get_lines(&mut self.terminal.borrow_mut(), lines)
|
terminal_get_lines(&mut self.terminal.lock(), lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dimensions(&self) -> RenderableDimensions {
|
fn get_dimensions(&self) -> RenderableDimensions {
|
||||||
terminal_get_dimensions(&mut self.terminal.borrow_mut())
|
terminal_get_dimensions(&mut self.terminal.lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_title(&self) -> String {
|
fn get_title(&self) -> String {
|
||||||
self.terminal.borrow_mut().get_title().to_string()
|
self.terminal.lock().get_title().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_close_without_prompting(&self, _reason: CloseReason) -> bool {
|
fn can_close_without_prompting(&self, _reason: CloseReason) -> bool {
|
||||||
@ -188,8 +188,11 @@ impl Pane for TermWizTerminalPane {
|
|||||||
Ok(Some(Box::new(self.render_rx.try_clone()?)))
|
Ok(Some(Box::new(self.render_rx.try_clone()?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
self.writer.borrow_mut()
|
MutexGuard::map(self.writer.lock(), |writer| {
|
||||||
|
let w: &mut dyn std::io::Write = writer;
|
||||||
|
w
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
||||||
@ -198,7 +201,7 @@ impl Pane for TermWizTerminalPane {
|
|||||||
cols: size.cols as usize,
|
cols: size.cols as usize,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.terminal.borrow_mut().resize(size);
|
self.terminal.lock().resize(size);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -206,7 +209,7 @@ impl Pane for TermWizTerminalPane {
|
|||||||
fn key_down(&self, key: KeyCode, modifiers: KeyModifiers) -> anyhow::Result<()> {
|
fn key_down(&self, key: KeyCode, modifiers: KeyModifiers) -> anyhow::Result<()> {
|
||||||
let event = InputEvent::Key(KeyEvent { key, modifiers });
|
let event = InputEvent::Key(KeyEvent { key, modifiers });
|
||||||
if let Err(e) = self.input_tx.send(event) {
|
if let Err(e) = self.input_tx.send(event) {
|
||||||
*self.dead.borrow_mut() = true;
|
*self.dead.lock() = true;
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -236,34 +239,34 @@ impl Pane for TermWizTerminalPane {
|
|||||||
modifiers: event.modifiers,
|
modifiers: event.modifiers,
|
||||||
});
|
});
|
||||||
if let Err(e) = self.input_tx.send(event) {
|
if let Err(e) = self.input_tx.send(event) {
|
||||||
*self.dead.borrow_mut() = true;
|
*self.dead.lock() = true;
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_config(&self, config: Arc<dyn TerminalConfiguration>) {
|
fn set_config(&self, config: Arc<dyn TerminalConfiguration>) {
|
||||||
self.terminal.borrow_mut().set_config(config);
|
self.terminal.lock().set_config(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config(&self) -> Option<Arc<dyn TerminalConfiguration>> {
|
fn get_config(&self) -> Option<Arc<dyn TerminalConfiguration>> {
|
||||||
Some(self.terminal.borrow().get_config())
|
Some(self.terminal.lock().get_config())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_actions(&self, actions: Vec<termwiz::escape::Action>) {
|
fn perform_actions(&self, actions: Vec<termwiz::escape::Action>) {
|
||||||
self.terminal.borrow_mut().perform_actions(actions)
|
self.terminal.lock().perform_actions(actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kill(&self) {
|
fn kill(&self) {
|
||||||
*self.dead.borrow_mut() = true;
|
*self.dead.lock() = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
fn is_dead(&self) -> bool {
|
||||||
*self.dead.borrow()
|
*self.dead.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn palette(&self) -> ColorPalette {
|
fn palette(&self) -> ColorPalette {
|
||||||
self.terminal.borrow().palette()
|
self.terminal.lock().palette()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_id(&self) -> DomainId {
|
fn domain_id(&self) -> DomainId {
|
||||||
@ -271,24 +274,24 @@ impl Pane for TermWizTerminalPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_mouse_grabbed(&self) -> bool {
|
fn is_mouse_grabbed(&self) -> bool {
|
||||||
self.terminal.borrow().is_mouse_grabbed()
|
self.terminal.lock().is_mouse_grabbed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_alt_screen_active(&self) -> bool {
|
fn is_alt_screen_active(&self) -> bool {
|
||||||
self.terminal.borrow().is_alt_screen_active()
|
self.terminal.lock().is_alt_screen_active()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_working_dir(&self) -> Option<Url> {
|
fn get_current_working_dir(&self) -> Option<Url> {
|
||||||
self.terminal.borrow().get_current_dir().cloned()
|
self.terminal.lock().get_current_dir().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn erase_scrollback(&self, erase_mode: ScrollbackEraseMode) {
|
fn erase_scrollback(&self, erase_mode: ScrollbackEraseMode) {
|
||||||
match erase_mode {
|
match erase_mode {
|
||||||
ScrollbackEraseMode::ScrollbackOnly => {
|
ScrollbackEraseMode::ScrollbackOnly => {
|
||||||
self.terminal.borrow_mut().erase_scrollback();
|
self.terminal.lock().erase_scrollback();
|
||||||
}
|
}
|
||||||
ScrollbackEraseMode::ScrollbackAndViewport => {
|
ScrollbackEraseMode::ScrollbackAndViewport => {
|
||||||
self.terminal.borrow_mut().erase_scrollback_and_viewport();
|
self.terminal.lock().erase_scrollback_and_viewport();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,7 +438,7 @@ impl termwiz::terminal::Terminal for TermWizTerminal {
|
|||||||
pub fn allocate(
|
pub fn allocate(
|
||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
config: Arc<dyn TerminalConfiguration + Send + Sync>,
|
config: Arc<dyn TerminalConfiguration + Send + Sync>,
|
||||||
) -> (TermWizTerminal, Rc<dyn Pane>) {
|
) -> (TermWizTerminal, Arc<dyn Pane>) {
|
||||||
let render_pipe = Pipe::new().expect("Pipe creation not to fail");
|
let render_pipe = Pipe::new().expect("Pipe creation not to fail");
|
||||||
|
|
||||||
let (input_tx, input_rx) = channel();
|
let (input_tx, input_rx) = channel();
|
||||||
@ -461,7 +464,7 @@ pub fn allocate(
|
|||||||
let pane = TermWizTerminalPane::new(domain_id, size, input_tx, render_pipe.read, Some(config));
|
let pane = TermWizTerminalPane::new(domain_id, size, input_tx, render_pipe.read, Some(config));
|
||||||
|
|
||||||
// Add the tab to the mux so that the output is processed
|
// Add the tab to the mux so that the output is processed
|
||||||
let pane: Rc<dyn Pane> = Rc::new(pane);
|
let pane: Arc<dyn Pane> = Arc::new(pane);
|
||||||
|
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
mux.add_pane(&pane).expect("to be able to add pane to mux");
|
mux.add_pane(&pane).expect("to be able to add pane to mux");
|
||||||
@ -530,7 +533,7 @@ pub async fn run<
|
|||||||
|
|
||||||
let pane =
|
let pane =
|
||||||
TermWizTerminalPane::new(domain.domain_id(), size, input_tx, render_rx, term_config);
|
TermWizTerminalPane::new(domain.domain_id(), size, input_tx, render_rx, term_config);
|
||||||
let pane: Rc<dyn Pane> = Rc::new(pane);
|
let pane: Arc<dyn Pane> = Arc::new(pane);
|
||||||
|
|
||||||
let tab = Rc::new(Tab::new(&size));
|
let tab = Rc::new(Tab::new(&size));
|
||||||
tab.assign_pane(&pane);
|
tab.assign_pane(&pane);
|
||||||
|
@ -5,12 +5,11 @@ use crate::tmux_commands::{ListAllPanes, TmuxCommand};
|
|||||||
use crate::{Mux, MuxWindowBuilder};
|
use crate::{Mux, MuxWindowBuilder};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use filedescriptor::FileDescriptor;
|
use filedescriptor::FileDescriptor;
|
||||||
|
use parking_lot::{Condvar, Mutex};
|
||||||
use portable_pty::CommandBuilder;
|
use portable_pty::CommandBuilder;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
|
||||||
use termwiz::tmux_cc::*;
|
use termwiz::tmux_cc::*;
|
||||||
use wezterm_term::TerminalSize;
|
use wezterm_term::TerminalSize;
|
||||||
|
|
||||||
@ -55,12 +54,12 @@ pub(crate) type TmuxCmdQueue = VecDeque<Box<dyn TmuxCommand>>;
|
|||||||
pub(crate) struct TmuxDomainState {
|
pub(crate) struct TmuxDomainState {
|
||||||
pub pane_id: PaneId, // ID of the original pane
|
pub pane_id: PaneId, // ID of the original pane
|
||||||
pub domain_id: DomainId, // ID of TmuxDomain
|
pub domain_id: DomainId, // ID of TmuxDomain
|
||||||
state: RefCell<State>,
|
state: Mutex<State>,
|
||||||
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
|
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
|
||||||
pub gui_window: RefCell<Option<MuxWindowBuilder>>,
|
pub gui_window: Mutex<Option<MuxWindowBuilder>>,
|
||||||
pub gui_tabs: RefCell<Vec<TmuxTab>>,
|
pub gui_tabs: Mutex<Vec<TmuxTab>>,
|
||||||
pub remote_panes: RefCell<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
|
pub remote_panes: Mutex<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
|
||||||
pub tmux_session: RefCell<Option<TmuxSessionId>>,
|
pub tmux_session: Mutex<Option<TmuxSessionId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TmuxDomain {
|
pub struct TmuxDomain {
|
||||||
@ -70,18 +69,18 @@ pub struct TmuxDomain {
|
|||||||
impl TmuxDomainState {
|
impl TmuxDomainState {
|
||||||
pub fn advance(&self, events: Box<Vec<Event>>) {
|
pub fn advance(&self, events: Box<Vec<Event>>) {
|
||||||
for event in events.iter() {
|
for event in events.iter() {
|
||||||
let state = *self.state.borrow();
|
let state = *self.state.lock();
|
||||||
log::info!("tmux: {:?} in state {:?}", event, state);
|
log::info!("tmux: {:?} in state {:?}", event, state);
|
||||||
match event {
|
match event {
|
||||||
Event::Guarded(response) => match state {
|
Event::Guarded(response) => match state {
|
||||||
State::WaitForInitialGuard => {
|
State::WaitForInitialGuard => {
|
||||||
*self.state.borrow_mut() = State::Idle;
|
*self.state.lock() = State::Idle;
|
||||||
}
|
}
|
||||||
State::WaitingForResponse => {
|
State::WaitingForResponse => {
|
||||||
let mut cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
let mut cmd_queue = self.cmd_queue.as_ref().lock();
|
||||||
let cmd = cmd_queue.pop_front().unwrap();
|
let cmd = cmd_queue.pop_front().unwrap();
|
||||||
let domain_id = self.domain_id;
|
let domain_id = self.domain_id;
|
||||||
*self.state.borrow_mut() = State::Idle;
|
*self.state.lock() = State::Idle;
|
||||||
let resp = response.clone();
|
let resp = response.clone();
|
||||||
promise::spawn::spawn(async move {
|
promise::spawn::spawn(async move {
|
||||||
if let Err(err) = cmd.process_result(domain_id, &resp) {
|
if let Err(err) = cmd.process_result(domain_id, &resp) {
|
||||||
@ -93,9 +92,9 @@ impl TmuxDomainState {
|
|||||||
State::Idle => {}
|
State::Idle => {}
|
||||||
},
|
},
|
||||||
Event::Output { pane, text } => {
|
Event::Output { pane, text } => {
|
||||||
let pane_map = self.remote_panes.borrow_mut();
|
let pane_map = self.remote_panes.lock();
|
||||||
if let Some(ref_pane) = pane_map.get(pane) {
|
if let Some(ref_pane) = pane_map.get(pane) {
|
||||||
let mut tmux_pane = ref_pane.lock().unwrap();
|
let mut tmux_pane = ref_pane.lock();
|
||||||
if let Err(err) = tmux_pane.output_write.write_all(text.as_bytes()) {
|
if let Err(err) = tmux_pane.output_write.write_all(text.as_bytes()) {
|
||||||
log::error!("Failed to write tmux data to output: {:#}", err);
|
log::error!("Failed to write tmux data to output: {:#}", err);
|
||||||
}
|
}
|
||||||
@ -107,15 +106,15 @@ impl TmuxDomainState {
|
|||||||
self.create_gui_window();
|
self.create_gui_window();
|
||||||
}
|
}
|
||||||
Event::SessionChanged { session, name: _ } => {
|
Event::SessionChanged { session, name: _ } => {
|
||||||
*self.tmux_session.borrow_mut() = Some(*session);
|
*self.tmux_session.lock() = Some(*session);
|
||||||
log::info!("tmux session changed:{}", session);
|
log::info!("tmux session changed:{}", session);
|
||||||
}
|
}
|
||||||
Event::Exit { reason: _ } => {
|
Event::Exit { reason: _ } => {
|
||||||
let mut pane_map = self.remote_panes.borrow_mut();
|
let mut pane_map = self.remote_panes.lock();
|
||||||
for (_, v) in pane_map.iter_mut() {
|
for (_, v) in pane_map.iter_mut() {
|
||||||
let remote_pane = v.lock().unwrap();
|
let remote_pane = v.lock();
|
||||||
let (lock, condvar) = &*remote_pane.active_lock;
|
let (lock, condvar) = &*remote_pane.active_lock;
|
||||||
let mut released = lock.lock().unwrap();
|
let mut released = lock.lock();
|
||||||
*released = true;
|
*released = true;
|
||||||
condvar.notify_all();
|
condvar.notify_all();
|
||||||
}
|
}
|
||||||
@ -125,8 +124,8 @@ impl TmuxDomainState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send pending commands to tmux
|
// send pending commands to tmux
|
||||||
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
let cmd_queue = self.cmd_queue.as_ref().lock();
|
||||||
if *self.state.borrow() == State::Idle && !cmd_queue.is_empty() {
|
if *self.state.lock() == State::Idle && !cmd_queue.is_empty() {
|
||||||
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,10 +133,10 @@ impl TmuxDomainState {
|
|||||||
/// send next command at the front of cmd_queue.
|
/// send next command at the front of cmd_queue.
|
||||||
/// must be called inside main thread
|
/// must be called inside main thread
|
||||||
fn send_next_command(&self) {
|
fn send_next_command(&self) {
|
||||||
if *self.state.borrow() != State::Idle {
|
if *self.state.lock() != State::Idle {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
let cmd_queue = self.cmd_queue.as_ref().lock();
|
||||||
if let Some(first) = cmd_queue.front() {
|
if let Some(first) = cmd_queue.front() {
|
||||||
let cmd = first.get_command();
|
let cmd = first.get_command();
|
||||||
log::info!("sending cmd {:?}", cmd);
|
log::info!("sending cmd {:?}", cmd);
|
||||||
@ -146,7 +145,7 @@ impl TmuxDomainState {
|
|||||||
let mut writer = pane.writer();
|
let mut writer = pane.writer();
|
||||||
let _ = write!(writer, "{}", cmd);
|
let _ = write!(writer, "{}", cmd);
|
||||||
}
|
}
|
||||||
*self.state.borrow_mut() = State::WaitingForResponse;
|
*self.state.lock() = State::WaitingForResponse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,12 +164,12 @@ impl TmuxDomainState {
|
|||||||
|
|
||||||
/// create a standalone window for tmux tabs
|
/// create a standalone window for tmux tabs
|
||||||
pub fn create_gui_window(&self) {
|
pub fn create_gui_window(&self) {
|
||||||
if self.gui_window.borrow().is_none() {
|
if self.gui_window.lock().is_none() {
|
||||||
let mux = Mux::get().expect("should be call at main thread");
|
let mux = Mux::get().expect("should be call at main thread");
|
||||||
let window_builder = mux.new_empty_window(None /* TODO: pass session here */);
|
let window_builder = mux.new_empty_window(None /* TODO: pass session here */);
|
||||||
log::info!("Tmux create window id {}", window_builder.window_id);
|
log::info!("Tmux create window id {}", window_builder.window_id);
|
||||||
{
|
{
|
||||||
let mut window_id = self.gui_window.borrow_mut();
|
let mut window_id = self.gui_window.lock();
|
||||||
*window_id = Some(window_builder); // keep the builder so it won't be purged
|
*window_id = Some(window_builder); // keep the builder so it won't be purged
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -180,19 +179,18 @@ impl TmuxDomainState {
|
|||||||
impl TmuxDomain {
|
impl TmuxDomain {
|
||||||
pub fn new(pane_id: PaneId) -> Self {
|
pub fn new(pane_id: PaneId) -> Self {
|
||||||
let domain_id = alloc_domain_id();
|
let domain_id = alloc_domain_id();
|
||||||
// let parser = RefCell::new(Parser::new());
|
|
||||||
let mut cmd_queue = VecDeque::<Box<dyn TmuxCommand>>::new();
|
let mut cmd_queue = VecDeque::<Box<dyn TmuxCommand>>::new();
|
||||||
cmd_queue.push_back(Box::new(ListAllPanes));
|
cmd_queue.push_back(Box::new(ListAllPanes));
|
||||||
let inner = Arc::new(TmuxDomainState {
|
let inner = Arc::new(TmuxDomainState {
|
||||||
domain_id,
|
domain_id,
|
||||||
pane_id,
|
pane_id,
|
||||||
// parser,
|
// parser,
|
||||||
state: RefCell::new(State::WaitForInitialGuard),
|
state: Mutex::new(State::WaitForInitialGuard),
|
||||||
cmd_queue: Arc::new(Mutex::new(cmd_queue)),
|
cmd_queue: Arc::new(Mutex::new(cmd_queue)),
|
||||||
gui_window: RefCell::new(None),
|
gui_window: Mutex::new(None),
|
||||||
gui_tabs: RefCell::new(Vec::default()),
|
gui_tabs: Mutex::new(Vec::default()),
|
||||||
remote_panes: RefCell::new(HashMap::default()),
|
remote_panes: Mutex::new(HashMap::default()),
|
||||||
tmux_session: RefCell::new(None),
|
tmux_session: Mutex::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
Self { inner }
|
Self { inner }
|
||||||
@ -210,7 +208,7 @@ impl Domain for TmuxDomain {
|
|||||||
_size: TerminalSize,
|
_size: TerminalSize,
|
||||||
_command: Option<CommandBuilder>,
|
_command: Option<CommandBuilder>,
|
||||||
_command_dir: Option<String>,
|
_command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
anyhow::bail!("Spawn_pane not yet implemented for TmuxDomain");
|
anyhow::bail!("Spawn_pane not yet implemented for TmuxDomain");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,13 @@ use crate::tmux::{TmuxDomain, TmuxDomainState, TmuxRemotePane, TmuxTab};
|
|||||||
use crate::tmux_pty::{TmuxChild, TmuxPty};
|
use crate::tmux_pty::{TmuxChild, TmuxPty};
|
||||||
use crate::{Mux, Pane};
|
use crate::{Mux, Pane};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
|
use parking_lot::{Condvar, Mutex};
|
||||||
use portable_pty::{MasterPty, PtySize};
|
use portable_pty::{MasterPty, PtySize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::{Debug, Write};
|
use std::fmt::{Debug, Write};
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::Arc;
|
||||||
use termwiz::tmux_cc::*;
|
use termwiz::tmux_cc::*;
|
||||||
use wezterm_term::TerminalSize;
|
use wezterm_term::TerminalSize;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ pub(crate) struct PaneItem {
|
|||||||
impl TmuxDomainState {
|
impl TmuxDomainState {
|
||||||
/// check if a PaneItem received from ListAllPanes has been attached
|
/// check if a PaneItem received from ListAllPanes has been attached
|
||||||
fn check_pane_attached(&self, target: &PaneItem) -> bool {
|
fn check_pane_attached(&self, target: &PaneItem) -> bool {
|
||||||
let pane_list = self.gui_tabs.borrow();
|
let pane_list = self.gui_tabs.lock();
|
||||||
let local_tab = match pane_list
|
let local_tab = match pane_list
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&x| x.tmux_window_id == target.window_id)
|
.find(|&x| x.tmux_window_id == target.window_id)
|
||||||
@ -60,7 +61,7 @@ impl TmuxDomainState {
|
|||||||
/// after we create a tab for a remote pane, save its ID into the
|
/// after we create a tab for a remote pane, save its ID into the
|
||||||
/// TmuxPane-TmuxPane tree, so we can ref it later.
|
/// TmuxPane-TmuxPane tree, so we can ref it later.
|
||||||
fn add_attached_pane(&self, target: &PaneItem, tab_id: &TabId) -> anyhow::Result<()> {
|
fn add_attached_pane(&self, target: &PaneItem, tab_id: &TabId) -> anyhow::Result<()> {
|
||||||
let mut pane_list = self.gui_tabs.borrow_mut();
|
let mut pane_list = self.gui_tabs.lock();
|
||||||
let local_tab = match pane_list
|
let local_tab = match pane_list
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|x| x.tmux_window_id == target.window_id)
|
.find(|x| x.tmux_window_id == target.window_id)
|
||||||
@ -92,7 +93,7 @@ impl TmuxDomainState {
|
|||||||
// 2) create pane if not exist
|
// 2) create pane if not exist
|
||||||
// 3) fetch scroll buffer if new created
|
// 3) fetch scroll buffer if new created
|
||||||
// 4) update pane state if exist
|
// 4) update pane state if exist
|
||||||
let current_session = self.tmux_session.borrow().unwrap_or(0);
|
let current_session = self.tmux_session.lock().unwrap_or(0);
|
||||||
for pane in panes.iter() {
|
for pane in panes.iter() {
|
||||||
if pane.session_id != current_session || self.check_pane_attached(&pane) {
|
if pane.session_id != current_session || self.check_pane_attached(&pane) {
|
||||||
continue;
|
continue;
|
||||||
@ -118,7 +119,7 @@ impl TmuxDomainState {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut pane_map = self.remote_panes.borrow_mut();
|
let mut pane_map = self.remote_panes.lock();
|
||||||
pane_map.insert(pane.pane_id, ref_pane.clone());
|
pane_map.insert(pane.pane_id, ref_pane.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +151,7 @@ impl TmuxDomainState {
|
|||||||
Box::new(writer.clone()),
|
Box::new(writer.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let local_pane: Rc<dyn Pane> = Rc::new(LocalPane::new(
|
let local_pane: Arc<dyn Pane> = Arc::new(LocalPane::new(
|
||||||
local_pane_id,
|
local_pane_id,
|
||||||
terminal,
|
terminal,
|
||||||
Box::new(child),
|
Box::new(child),
|
||||||
@ -164,7 +165,7 @@ impl TmuxDomainState {
|
|||||||
tab.assign_pane(&local_pane);
|
tab.assign_pane(&local_pane);
|
||||||
|
|
||||||
self.create_gui_window();
|
self.create_gui_window();
|
||||||
let mut gui_window = self.gui_window.borrow_mut();
|
let mut gui_window = self.gui_window.lock();
|
||||||
let gui_window_id = match gui_window.as_mut() {
|
let gui_window_id = match gui_window.as_mut() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => {
|
None => {
|
||||||
@ -178,7 +179,6 @@ impl TmuxDomainState {
|
|||||||
|
|
||||||
self.cmd_queue
|
self.cmd_queue
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
|
||||||
.push_back(Box::new(CapturePane(pane.pane_id)));
|
.push_back(Box::new(CapturePane(pane.pane_id)));
|
||||||
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
||||||
|
|
||||||
@ -314,9 +314,9 @@ impl TmuxCommand for CapturePane {
|
|||||||
// capturep contents returned from guarded lines which always contain a tailing '\n'
|
// capturep contents returned from guarded lines which always contain a tailing '\n'
|
||||||
let unescaped = &unescaped[0..unescaped.len().saturating_sub(1)].replace("\n", "\r\n");
|
let unescaped = &unescaped[0..unescaped.len().saturating_sub(1)].replace("\n", "\r\n");
|
||||||
|
|
||||||
let pane_map = tmux_domain.inner.remote_panes.borrow();
|
let pane_map = tmux_domain.inner.remote_panes.lock();
|
||||||
if let Some(pane) = pane_map.get(&self.0) {
|
if let Some(pane) = pane_map.get(&self.0) {
|
||||||
let mut pane = pane.lock().expect("Grant lock of tmux cmd queue failed");
|
let mut pane = pane.lock();
|
||||||
pane.output_write
|
pane.output_write
|
||||||
.write_all(unescaped.as_bytes())
|
.write_all(unescaped.as_bytes())
|
||||||
.context("writing capture pane result to output")?;
|
.context("writing capture pane result to output")?;
|
||||||
|
@ -2,9 +2,10 @@ use crate::tmux::{RefTmuxRemotePane, TmuxCmdQueue, TmuxDomainState};
|
|||||||
use crate::tmux_commands::{Resize, SendKeys};
|
use crate::tmux_commands::{Resize, SendKeys};
|
||||||
use crate::DomainId;
|
use crate::DomainId;
|
||||||
use filedescriptor::FileDescriptor;
|
use filedescriptor::FileDescriptor;
|
||||||
|
use parking_lot::{Condvar, Mutex};
|
||||||
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty};
|
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A local tmux pane(tab) based on a tmux pty
|
/// A local tmux pane(tab) based on a tmux pty
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -24,11 +25,11 @@ struct TmuxPtyWriter {
|
|||||||
impl Write for TmuxPtyWriter {
|
impl Write for TmuxPtyWriter {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
let pane_id = {
|
let pane_id = {
|
||||||
let pane_lock = self.master_pane.lock().unwrap();
|
let pane_lock = self.master_pane.lock();
|
||||||
pane_lock.pane_id
|
pane_lock.pane_id
|
||||||
};
|
};
|
||||||
log::trace!("pane:{}, content:{:?}", &pane_id, buf);
|
log::trace!("pane:{}, content:{:?}", &pane_id, buf);
|
||||||
let mut cmd_queue = self.cmd_queue.lock().unwrap();
|
let mut cmd_queue = self.cmd_queue.lock();
|
||||||
cmd_queue.push_back(Box::new(SendKeys {
|
cmd_queue.push_back(Box::new(SendKeys {
|
||||||
pane: pane_id,
|
pane: pane_id,
|
||||||
keys: buf.to_vec(),
|
keys: buf.to_vec(),
|
||||||
@ -45,11 +46,11 @@ impl Write for TmuxPtyWriter {
|
|||||||
impl Write for TmuxPty {
|
impl Write for TmuxPty {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
let pane_id = {
|
let pane_id = {
|
||||||
let pane_lock = self.master_pane.lock().unwrap();
|
let pane_lock = self.master_pane.lock();
|
||||||
pane_lock.pane_id
|
pane_lock.pane_id
|
||||||
};
|
};
|
||||||
log::trace!("pane:{}, content:{:?}", &pane_id, buf);
|
log::trace!("pane:{}, content:{:?}", &pane_id, buf);
|
||||||
let mut cmd_queue = self.cmd_queue.lock().unwrap();
|
let mut cmd_queue = self.cmd_queue.lock();
|
||||||
cmd_queue.push_back(Box::new(SendKeys {
|
cmd_queue.push_back(Box::new(SendKeys {
|
||||||
pane: pane_id,
|
pane: pane_id,
|
||||||
keys: buf.to_vec(),
|
keys: buf.to_vec(),
|
||||||
@ -74,10 +75,10 @@ impl Child for TmuxChild {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn wait(&mut self) -> std::io::Result<portable_pty::ExitStatus> {
|
fn wait(&mut self) -> std::io::Result<portable_pty::ExitStatus> {
|
||||||
let (lock, var) = &*self.active_lock;
|
let &(ref lock, ref var) = &*self.active_lock;
|
||||||
let mut released = lock.lock().unwrap();
|
let mut released = lock.lock();
|
||||||
while !*released {
|
while !*released {
|
||||||
released = var.wait(released).unwrap();
|
var.wait(&mut released);
|
||||||
}
|
}
|
||||||
return Ok(ExitStatus::with_exit_code(0));
|
return Ok(ExitStatus::with_exit_code(0));
|
||||||
}
|
}
|
||||||
@ -123,14 +124,14 @@ impl ChildKiller for TmuxChild {
|
|||||||
|
|
||||||
impl MasterPty for TmuxPty {
|
impl MasterPty for TmuxPty {
|
||||||
fn resize(&self, size: portable_pty::PtySize) -> Result<(), anyhow::Error> {
|
fn resize(&self, size: portable_pty::PtySize) -> Result<(), anyhow::Error> {
|
||||||
let mut cmd_queue = self.cmd_queue.lock().unwrap();
|
let mut cmd_queue = self.cmd_queue.lock();
|
||||||
cmd_queue.push_back(Box::new(Resize { size }));
|
cmd_queue.push_back(Box::new(Resize { size }));
|
||||||
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
TmuxDomainState::schedule_send_next_command(self.domain_id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_size(&self) -> Result<portable_pty::PtySize, anyhow::Error> {
|
fn get_size(&self) -> Result<portable_pty::PtySize, anyhow::Error> {
|
||||||
let pane = self.master_pane.lock().unwrap();
|
let pane = self.master_pane.lock();
|
||||||
Ok(portable_pty::PtySize {
|
Ok(portable_pty::PtySize {
|
||||||
rows: pane.pane_height as u16,
|
rows: pane.pane_height as u16,
|
||||||
cols: pane.pane_width as u16,
|
cols: pane.pane_width as u16,
|
||||||
|
@ -131,7 +131,7 @@ impl Default for NewlineCanon {
|
|||||||
/// The configuration can be changed at runtime; provided that the implementation
|
/// The configuration can be changed at runtime; provided that the implementation
|
||||||
/// increments the generation counter appropriately, the changes will be detected
|
/// increments the generation counter appropriately, the changes will be detected
|
||||||
/// and applied at the next appropriate opportunity.
|
/// and applied at the next appropriate opportunity.
|
||||||
pub trait TerminalConfiguration: std::fmt::Debug {
|
pub trait TerminalConfiguration: std::fmt::Debug + Send + Sync {
|
||||||
/// Returns a generation counter for the active
|
/// Returns a generation counter for the active
|
||||||
/// configuration. If the implementation may be
|
/// configuration. If the implementation may be
|
||||||
/// changed at runtime, it must increment the generation
|
/// changed at runtime, it must increment the generation
|
||||||
|
@ -10,7 +10,7 @@ pub enum ClipboardSelection {
|
|||||||
PrimarySelection,
|
PrimarySelection,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Clipboard {
|
pub trait Clipboard: Send + Sync {
|
||||||
fn set_contents(
|
fn set_contents(
|
||||||
&self,
|
&self,
|
||||||
selection: ClipboardSelection,
|
selection: ClipboardSelection,
|
||||||
@ -28,7 +28,7 @@ impl Clipboard for Box<dyn Clipboard> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DeviceControlHandler {
|
pub trait DeviceControlHandler: Send + Sync {
|
||||||
fn handle_device_control(&mut self, _control: termwiz::escape::DeviceControlMode);
|
fn handle_device_control(&mut self, _control: termwiz::escape::DeviceControlMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,11 +61,11 @@ pub enum Alert {
|
|||||||
OutputSinceFocusLost,
|
OutputSinceFocusLost,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait AlertHandler {
|
pub trait AlertHandler: Send + Sync {
|
||||||
fn alert(&mut self, alert: Alert);
|
fn alert(&mut self, alert: Alert);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DownloadHandler {
|
pub trait DownloadHandler: Send + Sync {
|
||||||
fn save_to_downloads(&self, name: Option<String>, data: Vec<u8>);
|
fn save_to_downloads(&self, name: Option<String>, data: Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ impl Terminal {
|
|||||||
/// are answerback responses to a number of escape sequences.
|
/// are answerback responses to a number of escape sequences.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
size: TerminalSize,
|
size: TerminalSize,
|
||||||
config: Arc<dyn TerminalConfiguration>,
|
config: Arc<dyn TerminalConfiguration + Send + Sync>,
|
||||||
term_program: &str,
|
term_program: &str,
|
||||||
term_version: &str,
|
term_version: &str,
|
||||||
// writing to the writer sends data to input of the pty
|
// writing to the writer sends data to input of the pty
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::input::*;
|
use crate::input::*;
|
||||||
use crate::TerminalState;
|
use crate::TerminalState;
|
||||||
|
use std::io::Write;
|
||||||
use termwiz::input::{KeyCodeEncodeModes, KeyboardEncoding};
|
use termwiz::input::{KeyCodeEncodeModes, KeyboardEncoding};
|
||||||
|
|
||||||
impl TerminalState {
|
impl TerminalState {
|
||||||
|
@ -6,6 +6,7 @@ use ::image::{
|
|||||||
};
|
};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use termwiz::escape::apc::{
|
use termwiz::escape::apc::{
|
||||||
|
@ -7,6 +7,7 @@ use crate::config::{BidiMode, NewlineCanon};
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::io::{BufWriter, Write};
|
||||||
use std::sync::mpsc::{channel, Sender};
|
use std::sync::mpsc::{channel, Sender};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use terminfo::{Database, Value};
|
use terminfo::{Database, Value};
|
||||||
@ -350,7 +351,7 @@ pub struct TerminalState {
|
|||||||
term_program: String,
|
term_program: String,
|
||||||
term_version: String,
|
term_version: String,
|
||||||
|
|
||||||
writer: Box<dyn std::io::Write>,
|
writer: BufWriter<ThreadedWriter>,
|
||||||
|
|
||||||
image_cache: lru::LruCache<[u8; 32], Arc<ImageData>>,
|
image_cache: lru::LruCache<[u8; 32], Arc<ImageData>>,
|
||||||
sixel_scrolls_right: bool,
|
sixel_scrolls_right: bool,
|
||||||
@ -498,7 +499,7 @@ impl TerminalState {
|
|||||||
term_version: &str,
|
term_version: &str,
|
||||||
writer: Box<dyn std::io::Write + Send>,
|
writer: Box<dyn std::io::Write + Send>,
|
||||||
) -> TerminalState {
|
) -> TerminalState {
|
||||||
let writer = Box::new(ThreadedWriter::new(writer));
|
let writer = BufWriter::new(ThreadedWriter::new(writer));
|
||||||
let seqno = 1;
|
let seqno = 1;
|
||||||
let screen = ScreenOrAlt::new(size, &config, seqno, config.bidi_mode());
|
let screen = ScreenOrAlt::new(size, &config, seqno, config.bidi_mode());
|
||||||
|
|
||||||
@ -559,7 +560,7 @@ impl TerminalState {
|
|||||||
current_dir: None,
|
current_dir: None,
|
||||||
term_program: term_program.to_string(),
|
term_program: term_program.to_string(),
|
||||||
term_version: term_version.to_string(),
|
term_version: term_version.to_string(),
|
||||||
writer: Box::new(std::io::BufWriter::new(writer)),
|
writer,
|
||||||
image_cache: lru::LruCache::new(16),
|
image_cache: lru::LruCache::new(16),
|
||||||
user_vars: HashMap::new(),
|
user_vars: HashMap::new(),
|
||||||
kitty_img: Default::default(),
|
kitty_img: Default::default(),
|
||||||
|
@ -2,6 +2,7 @@ use crate::input::*;
|
|||||||
use crate::terminalstate::MouseEncoding;
|
use crate::terminalstate::MouseEncoding;
|
||||||
use crate::TerminalState;
|
use crate::TerminalState;
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
impl TerminalState {
|
impl TerminalState {
|
||||||
/// Encode a coordinate value using X10 encoding or Utf8 encoding.
|
/// Encode a coordinate value using X10 encoding or Utf8 encoding.
|
||||||
|
@ -8,6 +8,7 @@ use log::{debug, error};
|
|||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::io::Write as _;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use termwiz::cell::{grapheme_column_width, Cell, CellAttributes, SemanticType};
|
use termwiz::cell::{grapheme_column_width, Cell, CellAttributes, SemanticType};
|
||||||
use termwiz::escape::csi::{
|
use termwiz::escape::csi::{
|
||||||
|
@ -9,21 +9,20 @@ mod csi;
|
|||||||
// mod selection; FIXME: port to render layer
|
// mod selection; FIXME: port to render layer
|
||||||
use crate::color::ColorPalette;
|
use crate::color::ColorPalette;
|
||||||
use k9::assert_equal as assert_eq;
|
use k9::assert_equal as assert_eq;
|
||||||
use std::cell::RefCell;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::Arc;
|
|
||||||
use termwiz::escape::csi::{Edit, EraseInDisplay, EraseInLine};
|
use termwiz::escape::csi::{Edit, EraseInDisplay, EraseInLine};
|
||||||
use termwiz::escape::{OneBased, OperatingSystemCommand, CSI};
|
use termwiz::escape::{OneBased, OperatingSystemCommand, CSI};
|
||||||
use termwiz::surface::{CursorShape, CursorVisibility, SequenceNo, SEQ_ZERO};
|
use termwiz::surface::{CursorShape, CursorVisibility, SequenceNo, SEQ_ZERO};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct LocalClip {
|
struct LocalClip {
|
||||||
clip: RefCell<Option<String>>,
|
clip: Mutex<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalClip {
|
impl LocalClip {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
clip: RefCell::new(None),
|
clip: Mutex::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ impl Clipboard for LocalClip {
|
|||||||
_selection: ClipboardSelection,
|
_selection: ClipboardSelection,
|
||||||
clip: Option<String>,
|
clip: Option<String>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
*self.clip.borrow_mut() = clip;
|
*self.clip.lock().unwrap() = clip;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ mux = { path = "../mux" }
|
|||||||
# https://github.com/sfackler/rust-openssl/pull/1578
|
# https://github.com/sfackler/rust-openssl/pull/1578
|
||||||
# https://github.com/wez/libssh-rs/blob/main/libssh-rs-sys/Cargo.toml
|
# https://github.com/wez/libssh-rs/blob/main/libssh-rs-sys/Cargo.toml
|
||||||
openssl = "=0.10.38"
|
openssl = "=0.10.38"
|
||||||
|
parking_lot = "0.12"
|
||||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||||
promise = { path = "../promise" }
|
promise = { path = "../promise" }
|
||||||
rangeset = { path = "../rangeset" }
|
rangeset = { path = "../rangeset" }
|
||||||
|
@ -460,7 +460,7 @@ impl ClientDomain {
|
|||||||
// removed it from the mux. Let's add it back, but
|
// removed it from the mux. Let's add it back, but
|
||||||
// with a new id.
|
// with a new id.
|
||||||
inner.remove_old_pane_mapping(entry.pane_id);
|
inner.remove_old_pane_mapping(entry.pane_id);
|
||||||
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
|
||||||
&inner,
|
&inner,
|
||||||
entry.tab_id,
|
entry.tab_id,
|
||||||
entry.pane_id,
|
entry.pane_id,
|
||||||
@ -472,7 +472,7 @@ impl ClientDomain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
|
||||||
&inner,
|
&inner,
|
||||||
entry.tab_id,
|
entry.tab_id,
|
||||||
entry.pane_id,
|
entry.pane_id,
|
||||||
@ -592,7 +592,7 @@ impl Domain for ClientDomain {
|
|||||||
_size: TerminalSize,
|
_size: TerminalSize,
|
||||||
_command: Option<CommandBuilder>,
|
_command: Option<CommandBuilder>,
|
||||||
_command_dir: Option<String>,
|
_command_dir: Option<String>,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
anyhow::bail!("spawn_pane not implemented for ClientDomain")
|
anyhow::bail!("spawn_pane not implemented for ClientDomain")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +623,7 @@ impl Domain for ClientDomain {
|
|||||||
|
|
||||||
inner.record_remote_to_local_window_mapping(result.window_id, window);
|
inner.record_remote_to_local_window_mapping(result.window_id, window);
|
||||||
|
|
||||||
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
|
||||||
&inner,
|
&inner,
|
||||||
result.tab_id,
|
result.tab_id,
|
||||||
result.pane_id,
|
result.pane_id,
|
||||||
@ -648,7 +648,7 @@ impl Domain for ClientDomain {
|
|||||||
tab_id: TabId,
|
tab_id: TabId,
|
||||||
pane_id: PaneId,
|
pane_id: PaneId,
|
||||||
split_request: SplitRequest,
|
split_request: SplitRequest,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
let inner = self
|
let inner = self
|
||||||
.inner()
|
.inner()
|
||||||
.ok_or_else(|| anyhow!("domain is not attached"))?;
|
.ok_or_else(|| anyhow!("domain is not attached"))?;
|
||||||
@ -685,7 +685,7 @@ impl Domain for ClientDomain {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
|
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
|
||||||
&inner,
|
&inner,
|
||||||
result.tab_id,
|
result.tab_id,
|
||||||
result.pane_id,
|
result.pane_id,
|
||||||
@ -702,7 +702,7 @@ impl Domain for ClientDomain {
|
|||||||
None => anyhow::bail!("invalid pane id {}", pane_id),
|
None => anyhow::bail!("invalid pane id {}", pane_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
tab.split_and_insert(pane_index, split_request, Rc::clone(&pane))
|
tab.split_and_insert(pane_index, split_request, Arc::clone(&pane))
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
mux.add_pane(&pane)?;
|
mux.add_pane(&pane)?;
|
||||||
|
@ -13,12 +13,12 @@ use mux::pane::{
|
|||||||
use mux::renderable::{RenderableDimensions, StableCursorPosition};
|
use mux::renderable::{RenderableDimensions, StableCursorPosition};
|
||||||
use mux::tab::TabId;
|
use mux::tab::TabId;
|
||||||
use mux::{Mux, MuxNotification};
|
use mux::{Mux, MuxNotification};
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use ratelim::RateLimiter;
|
use ratelim::RateLimiter;
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::RefCell;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use termwiz::input::KeyEvent;
|
use termwiz::input::KeyEvent;
|
||||||
use termwiz::surface::SequenceNo;
|
use termwiz::surface::SequenceNo;
|
||||||
@ -34,14 +34,14 @@ pub struct ClientPane {
|
|||||||
local_pane_id: PaneId,
|
local_pane_id: PaneId,
|
||||||
pub remote_pane_id: PaneId,
|
pub remote_pane_id: PaneId,
|
||||||
pub remote_tab_id: TabId,
|
pub remote_tab_id: TabId,
|
||||||
pub renderable: RefCell<RenderableState>,
|
pub renderable: Mutex<RenderableState>,
|
||||||
palette: RefCell<ColorPalette>,
|
palette: Mutex<ColorPalette>,
|
||||||
writer: RefCell<PaneWriter>,
|
writer: Mutex<PaneWriter>,
|
||||||
mouse: Rc<RefCell<MouseState>>,
|
mouse: Arc<Mutex<MouseState>>,
|
||||||
clipboard: RefCell<Option<Arc<dyn Clipboard>>>,
|
clipboard: Mutex<Option<Arc<dyn Clipboard>>>,
|
||||||
mouse_grabbed: RefCell<bool>,
|
mouse_grabbed: Mutex<bool>,
|
||||||
ignore_next_kill: RefCell<bool>,
|
ignore_next_kill: Mutex<bool>,
|
||||||
user_vars: RefCell<HashMap<String, String>>,
|
user_vars: Mutex<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientPane {
|
impl ClientPane {
|
||||||
@ -58,7 +58,7 @@ impl ClientPane {
|
|||||||
remote_pane_id,
|
remote_pane_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mouse = Rc::new(RefCell::new(MouseState::new(
|
let mouse = Arc::new(Mutex::new(MouseState::new(
|
||||||
remote_pane_id,
|
remote_pane_id,
|
||||||
client.client.clone(),
|
client.client.clone(),
|
||||||
)));
|
)));
|
||||||
@ -96,27 +96,27 @@ impl ClientPane {
|
|||||||
remote_pane_id,
|
remote_pane_id,
|
||||||
local_pane_id,
|
local_pane_id,
|
||||||
remote_tab_id,
|
remote_tab_id,
|
||||||
renderable: RefCell::new(render),
|
renderable: Mutex::new(render),
|
||||||
writer: RefCell::new(writer),
|
writer: Mutex::new(writer),
|
||||||
palette: RefCell::new(palette),
|
palette: Mutex::new(palette),
|
||||||
clipboard: RefCell::new(None),
|
clipboard: Mutex::new(None),
|
||||||
mouse_grabbed: RefCell::new(false),
|
mouse_grabbed: Mutex::new(false),
|
||||||
ignore_next_kill: RefCell::new(false),
|
ignore_next_kill: Mutex::new(false),
|
||||||
user_vars: RefCell::new(HashMap::new()),
|
user_vars: Mutex::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn process_unilateral(&self, pdu: Pdu) -> anyhow::Result<()> {
|
pub async fn process_unilateral(&self, pdu: Pdu) -> anyhow::Result<()> {
|
||||||
match pdu {
|
match pdu {
|
||||||
Pdu::GetPaneRenderChangesResponse(mut delta) => {
|
Pdu::GetPaneRenderChangesResponse(mut delta) => {
|
||||||
*self.mouse_grabbed.borrow_mut() = delta.mouse_grabbed;
|
*self.mouse_grabbed.lock() = delta.mouse_grabbed;
|
||||||
|
|
||||||
let bonus_lines = std::mem::take(&mut delta.bonus_lines);
|
let bonus_lines = std::mem::take(&mut delta.bonus_lines);
|
||||||
let client = { Arc::clone(&self.renderable.borrow().inner.borrow().client) };
|
let client = { Arc::clone(&self.renderable.lock().inner.borrow().client) };
|
||||||
let bonus_lines = hydrate_lines(client, delta.pane_id, bonus_lines).await;
|
let bonus_lines = hydrate_lines(client, delta.pane_id, bonus_lines).await;
|
||||||
|
|
||||||
self.renderable
|
self.renderable
|
||||||
.borrow()
|
.lock()
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.apply_changes_to_surface(delta, bonus_lines);
|
.apply_changes_to_surface(delta, bonus_lines);
|
||||||
@ -125,7 +125,7 @@ impl ClientPane {
|
|||||||
clipboard,
|
clipboard,
|
||||||
selection,
|
selection,
|
||||||
..
|
..
|
||||||
}) => match self.clipboard.borrow().as_ref() {
|
}) => match self.clipboard.lock().as_ref() {
|
||||||
Some(clip) => {
|
Some(clip) => {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Pdu::SetClipboard pane={} remote={} {:?} {:?}",
|
"Pdu::SetClipboard pane={} remote={} {:?} {:?}",
|
||||||
@ -141,7 +141,7 @@ impl ClientPane {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Pdu::SetPalette(SetPalette { palette, .. }) => {
|
Pdu::SetPalette(SetPalette { palette, .. }) => {
|
||||||
*self.palette.borrow_mut() = palette;
|
*self.palette.lock() = palette;
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
mux.notify(MuxNotification::Alert {
|
mux.notify(MuxNotification::Alert {
|
||||||
pane_id: self.local_pane_id,
|
pane_id: self.local_pane_id,
|
||||||
@ -152,9 +152,7 @@ impl ClientPane {
|
|||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
match &alert {
|
match &alert {
|
||||||
Alert::SetUserVar { name, value } => {
|
Alert::SetUserVar { name, value } => {
|
||||||
self.user_vars
|
self.user_vars.lock().insert(name.clone(), value.clone());
|
||||||
.borrow_mut()
|
|
||||||
.insert(name.clone(), value.clone());
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -165,7 +163,7 @@ impl ClientPane {
|
|||||||
}
|
}
|
||||||
Pdu::PaneRemoved(PaneRemoved { pane_id }) => {
|
Pdu::PaneRemoved(PaneRemoved { pane_id }) => {
|
||||||
log::trace!("remote pane {} has been removed", pane_id);
|
log::trace!("remote pane {} has been removed", pane_id);
|
||||||
self.renderable.borrow().inner.borrow_mut().dead = true;
|
self.renderable.lock().inner.borrow_mut().dead = true;
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
mux.prune_dead_windows();
|
mux.prune_dead_windows();
|
||||||
|
|
||||||
@ -188,7 +186,7 @@ impl ClientPane {
|
|||||||
/// from where they left off.
|
/// from where they left off.
|
||||||
/// It isn't perfect.
|
/// It isn't perfect.
|
||||||
pub fn ignore_next_kill(&self) {
|
pub fn ignore_next_kill(&self) {
|
||||||
*self.ignore_next_kill.borrow_mut() = true;
|
*self.ignore_next_kill.lock() = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +197,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_metadata(&self) -> Value {
|
fn get_metadata(&self) -> Value {
|
||||||
let renderable = self.renderable.borrow();
|
let renderable = self.renderable.lock();
|
||||||
let inner = renderable.inner.borrow();
|
let inner = renderable.inner.borrow();
|
||||||
|
|
||||||
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
|
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
|
||||||
@ -216,11 +214,11 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||||
self.renderable.borrow().get_cursor_position()
|
self.renderable.lock().get_cursor_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dimensions(&self) -> RenderableDimensions {
|
fn get_dimensions(&self) -> RenderableDimensions {
|
||||||
self.renderable.borrow().get_dimensions()
|
self.renderable.lock().get_dimensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
||||||
@ -236,7 +234,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
||||||
self.renderable.borrow().get_lines(lines)
|
self.renderable.lock().get_lines(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_logical_lines(&self, lines: Range<StableRowIndex>) -> Vec<LogicalLine> {
|
fn get_logical_lines(&self, lines: Range<StableRowIndex>) -> Vec<LogicalLine> {
|
||||||
@ -244,7 +242,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_seqno(&self) -> SequenceNo {
|
fn get_current_seqno(&self) -> SequenceNo {
|
||||||
self.renderable.borrow().get_current_seqno()
|
self.renderable.lock().get_current_seqno()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_changed_since(
|
fn get_changed_since(
|
||||||
@ -252,15 +250,15 @@ impl Pane for ClientPane {
|
|||||||
lines: Range<StableRowIndex>,
|
lines: Range<StableRowIndex>,
|
||||||
seqno: SequenceNo,
|
seqno: SequenceNo,
|
||||||
) -> RangeSet<StableRowIndex> {
|
) -> RangeSet<StableRowIndex> {
|
||||||
self.renderable.borrow().get_changed_since(lines, seqno)
|
self.renderable.lock().get_changed_since(lines, seqno)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clipboard(&self, clipboard: &Arc<dyn Clipboard>) {
|
fn set_clipboard(&self, clipboard: &Arc<dyn Clipboard>) {
|
||||||
self.clipboard.borrow_mut().replace(Arc::clone(clipboard));
|
self.clipboard.lock().replace(Arc::clone(clipboard));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_title(&self) -> String {
|
fn get_title(&self) -> String {
|
||||||
let renderable = self.renderable.borrow();
|
let renderable = self.renderable.lock();
|
||||||
let inner = renderable.inner.borrow();
|
let inner = renderable.inner.borrow();
|
||||||
inner.title.clone()
|
inner.title.clone()
|
||||||
}
|
}
|
||||||
@ -269,7 +267,7 @@ impl Pane for ClientPane {
|
|||||||
let client = Arc::clone(&self.client);
|
let client = Arc::clone(&self.client);
|
||||||
let remote_pane_id = self.remote_pane_id;
|
let remote_pane_id = self.remote_pane_id;
|
||||||
self.renderable
|
self.renderable
|
||||||
.borrow()
|
.lock()
|
||||||
.inner
|
.inner
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.predict_from_paste(text);
|
.predict_from_paste(text);
|
||||||
@ -285,11 +283,7 @@ impl Pane for ClientPane {
|
|||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
self.renderable
|
self.renderable.lock().inner.borrow_mut().update_last_send();
|
||||||
.borrow()
|
|
||||||
.inner
|
|
||||||
.borrow_mut()
|
|
||||||
.update_last_send();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,12 +291,15 @@ impl Pane for ClientPane {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
self.writer.borrow_mut()
|
MutexGuard::map(self.writer.lock(), |writer| {
|
||||||
|
let w: &mut dyn std::io::Write = writer;
|
||||||
|
w
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_zoomed(&self, zoomed: bool) {
|
fn set_zoomed(&self, zoomed: bool) {
|
||||||
let render = self.renderable.borrow();
|
let render = self.renderable.lock();
|
||||||
let mut inner = render.inner.borrow_mut();
|
let mut inner = render.inner.borrow_mut();
|
||||||
let client = Arc::clone(&self.client);
|
let client = Arc::clone(&self.client);
|
||||||
let remote_pane_id = self.remote_pane_id;
|
let remote_pane_id = self.remote_pane_id;
|
||||||
@ -324,7 +321,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
|
||||||
let render = self.renderable.borrow();
|
let render = self.renderable.lock();
|
||||||
let mut inner = render.inner.borrow_mut();
|
let mut inner = render.inner.borrow_mut();
|
||||||
|
|
||||||
let cols = size.cols as usize;
|
let cols = size.cols as usize;
|
||||||
@ -381,7 +378,7 @@ impl Pane for ClientPane {
|
|||||||
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
||||||
let input_serial;
|
let input_serial;
|
||||||
{
|
{
|
||||||
let renderable = self.renderable.borrow();
|
let renderable = self.renderable.lock();
|
||||||
let mut inner = renderable.inner.borrow_mut();
|
let mut inner = renderable.inner.borrow_mut();
|
||||||
inner.input_serial = InputSerial::now();
|
inner.input_serial = InputSerial::now();
|
||||||
input_serial = inner.input_serial;
|
input_serial = inner.input_serial;
|
||||||
@ -403,11 +400,7 @@ impl Pane for ClientPane {
|
|||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
self.renderable
|
self.renderable.lock().inner.borrow_mut().update_last_send();
|
||||||
.borrow()
|
|
||||||
.inner
|
|
||||||
.borrow_mut()
|
|
||||||
.update_last_send();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,7 +410,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn kill(&self) {
|
fn kill(&self) {
|
||||||
let mut ignore = self.ignore_next_kill.borrow_mut();
|
let mut ignore = self.ignore_next_kill.lock();
|
||||||
if *ignore {
|
if *ignore {
|
||||||
*ignore = false;
|
*ignore = false;
|
||||||
return;
|
return;
|
||||||
@ -482,27 +475,23 @@ impl Pane for ClientPane {
|
|||||||
// status, but killing the pane prevents the server
|
// status, but killing the pane prevents the server
|
||||||
// side from sending us further data.
|
// side from sending us further data.
|
||||||
// <https://github.com/wez/wezterm/issues/1752>
|
// <https://github.com/wez/wezterm/issues/1752>
|
||||||
self.renderable.borrow().inner.borrow_mut().dead = true;
|
self.renderable.lock().inner.borrow_mut().dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_event(&self, event: MouseEvent) -> anyhow::Result<()> {
|
fn mouse_event(&self, event: MouseEvent) -> anyhow::Result<()> {
|
||||||
self.mouse.borrow_mut().append(event);
|
self.mouse.lock().append(event);
|
||||||
if MouseState::next(Rc::clone(&self.mouse)) {
|
if MouseState::next(Arc::clone(&self.mouse)) {
|
||||||
self.renderable
|
self.renderable.lock().inner.borrow_mut().update_last_send();
|
||||||
.borrow()
|
|
||||||
.inner
|
|
||||||
.borrow_mut()
|
|
||||||
.update_last_send();
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
fn is_dead(&self) -> bool {
|
||||||
self.renderable.borrow().inner.borrow().dead
|
self.renderable.lock().inner.borrow().dead
|
||||||
}
|
}
|
||||||
|
|
||||||
fn palette(&self) -> ColorPalette {
|
fn palette(&self) -> ColorPalette {
|
||||||
self.palette.borrow().clone()
|
self.palette.lock().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn domain_id(&self) -> DomainId {
|
fn domain_id(&self) -> DomainId {
|
||||||
@ -510,7 +499,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_mouse_grabbed(&self) -> bool {
|
fn is_mouse_grabbed(&self) -> bool {
|
||||||
*self.mouse_grabbed.borrow()
|
*self.mouse_grabbed.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_alt_screen_active(&self) -> bool {
|
fn is_alt_screen_active(&self) -> bool {
|
||||||
@ -519,7 +508,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_working_dir(&self) -> Option<Url> {
|
fn get_current_working_dir(&self) -> Option<Url> {
|
||||||
self.renderable.borrow().inner.borrow().working_dir.clone()
|
self.renderable.lock().inner.borrow().working_dir.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_changed(&self, focused: bool) {
|
fn focus_changed(&self, focused: bool) {
|
||||||
@ -555,7 +544,7 @@ impl Pane for ClientPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn copy_user_vars(&self) -> HashMap<String, String> {
|
fn copy_user_vars(&self) -> HashMap<String, String> {
|
||||||
self.user_vars.borrow().clone()
|
self.user_vars.lock().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
use codec::*;
|
use codec::*;
|
||||||
use mux::tab::TabId;
|
use mux::tab::TabId;
|
||||||
use std::cell::RefCell;
|
use parking_lot::Mutex;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
use wezterm_term::{MouseButton, MouseEvent, MouseEventKind};
|
use wezterm_term::{MouseButton, MouseEvent, MouseEventKind};
|
||||||
|
|
||||||
pub struct MouseState {
|
pub struct MouseState {
|
||||||
@ -64,12 +64,12 @@ impl MouseState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(state: Rc<RefCell<Self>>) -> bool {
|
pub fn next(state: Arc<Mutex<Self>>) -> bool {
|
||||||
let mut mouse = state.borrow_mut();
|
let mut mouse = state.lock();
|
||||||
if let Some(event) = mouse.pop() {
|
if let Some(event) = mouse.pop() {
|
||||||
let client = mouse.client.clone();
|
let client = mouse.client.clone();
|
||||||
|
|
||||||
let state = Rc::clone(&state);
|
let state = Arc::clone(&state);
|
||||||
mouse.pending.store(true, Ordering::SeqCst);
|
mouse.pending.store(true, Ordering::SeqCst);
|
||||||
let remote_pane_id = mouse.remote_pane_id;
|
let remote_pane_id = mouse.remote_pane_id;
|
||||||
|
|
||||||
@ -82,11 +82,11 @@ impl MouseState {
|
|||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let mouse = state.borrow_mut();
|
let mouse = state.lock();
|
||||||
mouse.pending.store(false, Ordering::SeqCst);
|
mouse.pending.store(false, Ordering::SeqCst);
|
||||||
drop(mouse);
|
drop(mouse);
|
||||||
|
|
||||||
Self::next(Rc::clone(&state));
|
Self::next(Arc::clone(&state));
|
||||||
Ok::<(), anyhow::Error>(())
|
Ok::<(), anyhow::Error>(())
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -540,7 +540,7 @@ impl RenderableInner {
|
|||||||
.get_pane(local_pane_id)
|
.get_pane(local_pane_id)
|
||||||
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
|
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
|
||||||
if let Some(client_tab) = pane.downcast_ref::<ClientPane>() {
|
if let Some(client_tab) = pane.downcast_ref::<ClientPane>() {
|
||||||
let renderable = client_tab.renderable.borrow_mut();
|
let renderable = client_tab.renderable.lock();
|
||||||
let mut inner = renderable.inner.borrow_mut();
|
let mut inner = renderable.inner.borrow_mut();
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
@ -621,7 +621,7 @@ impl RenderableInner {
|
|||||||
.get_pane(local_pane_id)
|
.get_pane(local_pane_id)
|
||||||
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
|
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
|
||||||
if let Some(client_tab) = tab.downcast_ref::<ClientPane>() {
|
if let Some(client_tab) = tab.downcast_ref::<ClientPane>() {
|
||||||
let renderable = client_tab.renderable.borrow_mut();
|
let renderable = client_tab.renderable.lock();
|
||||||
let mut inner = renderable.inner.borrow_mut();
|
let mut inner = renderable.inner.borrow_mut();
|
||||||
|
|
||||||
inner.dead = !alive;
|
inner.dead = !alive;
|
||||||
|
@ -67,6 +67,7 @@ mux = { path = "../mux" }
|
|||||||
mux-lua = { path = "../lua-api-crates/mux" }
|
mux-lua = { path = "../lua-api-crates/mux" }
|
||||||
open = "3.0"
|
open = "3.0"
|
||||||
ordered-float = "3.0"
|
ordered-float = "3.0"
|
||||||
|
parking_lot = "0.12"
|
||||||
portable-pty = { path = "../pty", features = ["serde_support"]}
|
portable-pty = { path = "../pty", features = ["serde_support"]}
|
||||||
promise = { path = "../promise" }
|
promise = { path = "../promise" }
|
||||||
pulldown-cmark = "0.9"
|
pulldown-cmark = "0.9"
|
||||||
|
@ -12,12 +12,11 @@ use mux::pane::{
|
|||||||
use mux::renderable::*;
|
use mux::renderable::*;
|
||||||
use mux::tab::TabId;
|
use mux::tab::TabId;
|
||||||
use ordered_float::NotNan;
|
use ordered_float::NotNan;
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex};
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use std::cell::{RefCell, RefMut};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use termwiz::cell::{Cell, CellAttributes};
|
use termwiz::cell::{Cell, CellAttributes};
|
||||||
use termwiz::color::AnsiColor;
|
use termwiz::color::AnsiColor;
|
||||||
@ -38,8 +37,8 @@ lazy_static::lazy_static! {
|
|||||||
const SEARCH_CHUNK_SIZE: StableRowIndex = 1000;
|
const SEARCH_CHUNK_SIZE: StableRowIndex = 1000;
|
||||||
|
|
||||||
pub struct CopyOverlay {
|
pub struct CopyOverlay {
|
||||||
delegate: Rc<dyn Pane>,
|
delegate: Arc<dyn Pane>,
|
||||||
render: RefCell<CopyRenderable>,
|
render: Mutex<CopyRenderable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -57,7 +56,7 @@ struct Jump {
|
|||||||
|
|
||||||
struct CopyRenderable {
|
struct CopyRenderable {
|
||||||
cursor: StableCursorPosition,
|
cursor: StableCursorPosition,
|
||||||
delegate: Rc<dyn Pane>,
|
delegate: Arc<dyn Pane>,
|
||||||
start: Option<SelectionCoordinate>,
|
start: Option<SelectionCoordinate>,
|
||||||
selection_mode: SelectionMode,
|
selection_mode: SelectionMode,
|
||||||
viewport: Option<StableRowIndex>,
|
viewport: Option<StableRowIndex>,
|
||||||
@ -109,9 +108,9 @@ pub struct CopyModeParams {
|
|||||||
impl CopyOverlay {
|
impl CopyOverlay {
|
||||||
pub fn with_pane(
|
pub fn with_pane(
|
||||||
term_window: &TermWindow,
|
term_window: &TermWindow,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
params: CopyModeParams,
|
params: CopyModeParams,
|
||||||
) -> anyhow::Result<Rc<dyn Pane>> {
|
) -> anyhow::Result<Arc<dyn Pane>> {
|
||||||
let mut cursor = pane.get_cursor_position();
|
let mut cursor = pane.get_cursor_position();
|
||||||
cursor.shape = termwiz::surface::CursorShape::SteadyBlock;
|
cursor.shape = termwiz::surface::CursorShape::SteadyBlock;
|
||||||
cursor.visibility = CursorVisibility::Visible;
|
cursor.visibility = CursorVisibility::Visible;
|
||||||
@ -129,7 +128,7 @@ impl CopyOverlay {
|
|||||||
let mut render = CopyRenderable {
|
let mut render = CopyRenderable {
|
||||||
cursor,
|
cursor,
|
||||||
window,
|
window,
|
||||||
delegate: Rc::clone(pane),
|
delegate: Arc::clone(pane),
|
||||||
start: None,
|
start: None,
|
||||||
viewport: term_window.get_viewport(pane.pane_id()),
|
viewport: term_window.get_viewport(pane.pane_id()),
|
||||||
results: vec![],
|
results: vec![],
|
||||||
@ -143,7 +142,6 @@ impl CopyOverlay {
|
|||||||
pattern: if params.pattern.is_empty() {
|
pattern: if params.pattern.is_empty() {
|
||||||
SAVED_PATTERN
|
SAVED_PATTERN
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
|
||||||
.get(&tab_id)
|
.get(&tab_id)
|
||||||
.map(|p| p.clone())
|
.map(|p| p.clone())
|
||||||
.unwrap_or(params.pattern)
|
.unwrap_or(params.pattern)
|
||||||
@ -163,14 +161,14 @@ impl CopyOverlay {
|
|||||||
render.dirty_results.add(search_row);
|
render.dirty_results.add(search_row);
|
||||||
render.update_search();
|
render.update_search();
|
||||||
|
|
||||||
Ok(Rc::new(CopyOverlay {
|
Ok(Arc::new(CopyOverlay {
|
||||||
delegate: Rc::clone(pane),
|
delegate: Arc::clone(pane),
|
||||||
render: RefCell::new(render),
|
render: Mutex::new(render),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_params(&self) -> CopyModeParams {
|
pub fn get_params(&self) -> CopyModeParams {
|
||||||
let render = self.render.borrow();
|
let render = self.render.lock();
|
||||||
CopyModeParams {
|
CopyModeParams {
|
||||||
pattern: render.pattern.clone(),
|
pattern: render.pattern.clone(),
|
||||||
editing_search: render.editing_search,
|
editing_search: render.editing_search,
|
||||||
@ -178,7 +176,7 @@ impl CopyOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_params(&self, params: CopyModeParams) {
|
pub fn apply_params(&self, params: CopyModeParams) {
|
||||||
let mut render = self.render.borrow_mut();
|
let mut render = self.render.lock();
|
||||||
render.editing_search = params.editing_search;
|
render.editing_search = params.editing_search;
|
||||||
if render.pattern != params.pattern {
|
if render.pattern != params.pattern {
|
||||||
render.pattern = params.pattern;
|
render.pattern = params.pattern;
|
||||||
@ -189,7 +187,7 @@ impl CopyOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn viewport_changed(&self, viewport: Option<StableRowIndex>) {
|
pub fn viewport_changed(&self, viewport: Option<StableRowIndex>) {
|
||||||
let mut render = self.render.borrow_mut();
|
let mut render = self.render.lock();
|
||||||
if render.viewport != viewport {
|
if render.viewport != viewport {
|
||||||
if let Some(last) = render.last_bar_pos.take() {
|
if let Some(last) = render.last_bar_pos.take() {
|
||||||
render.dirty_results.add(last);
|
render.dirty_results.add(last);
|
||||||
@ -271,7 +269,7 @@ impl CopyRenderable {
|
|||||||
let state = term_window.pane_state(pane_id);
|
let state = term_window.pane_state(pane_id);
|
||||||
if let Some(overlay) = state.overlay.as_ref() {
|
if let Some(overlay) = state.overlay.as_ref() {
|
||||||
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
||||||
let mut r = copy_overlay.render.borrow_mut();
|
let mut r = copy_overlay.render.lock();
|
||||||
if cookie == r.typing_cookie {
|
if cookie == r.typing_cookie {
|
||||||
r.update_search();
|
r.update_search();
|
||||||
}
|
}
|
||||||
@ -297,7 +295,6 @@ impl CopyRenderable {
|
|||||||
|
|
||||||
SAVED_PATTERN
|
SAVED_PATTERN
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
|
||||||
.insert(self.tab_id, self.pattern.clone());
|
.insert(self.tab_id, self.pattern.clone());
|
||||||
|
|
||||||
let bar_pos = self.compute_search_row();
|
let bar_pos = self.compute_search_row();
|
||||||
@ -305,7 +302,7 @@ impl CopyRenderable {
|
|||||||
self.last_result_seqno = self.delegate.get_current_seqno();
|
self.last_result_seqno = self.delegate.get_current_seqno();
|
||||||
|
|
||||||
if !self.pattern.is_empty() {
|
if !self.pattern.is_empty() {
|
||||||
let pane: Rc<dyn Pane> = self.delegate.clone();
|
let pane: Arc<dyn Pane> = self.delegate.clone();
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
let pattern = self.pattern.clone();
|
let pattern = self.pattern.clone();
|
||||||
let dims = pane.get_dimensions();
|
let dims = pane.get_dimensions();
|
||||||
@ -330,7 +327,7 @@ impl CopyRenderable {
|
|||||||
let state = term_window.pane_state(pane_id);
|
let state = term_window.pane_state(pane_id);
|
||||||
if let Some(overlay) = state.overlay.as_ref() {
|
if let Some(overlay) = state.overlay.as_ref() {
|
||||||
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
||||||
let mut r = copy_overlay.render.borrow_mut();
|
let mut r = copy_overlay.render.lock();
|
||||||
r.processed_search_chunk(pattern, results.take().unwrap(), range);
|
r.processed_search_chunk(pattern, results.take().unwrap(), range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +372,7 @@ impl CopyRenderable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search next chunk
|
// Search next chunk
|
||||||
let pane: Rc<dyn Pane> = self.delegate.clone();
|
let pane: Arc<dyn Pane> = self.delegate.clone();
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
let end = range.start;
|
let end = range.start;
|
||||||
let range = end
|
let range = end
|
||||||
@ -397,7 +394,7 @@ impl CopyRenderable {
|
|||||||
let state = term_window.pane_state(pane_id);
|
let state = term_window.pane_state(pane_id);
|
||||||
if let Some(overlay) = state.overlay.as_ref() {
|
if let Some(overlay) = state.overlay.as_ref() {
|
||||||
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
if let Some(copy_overlay) = overlay.pane.downcast_ref::<CopyOverlay>() {
|
||||||
let mut r = copy_overlay.render.borrow_mut();
|
let mut r = copy_overlay.render.lock();
|
||||||
r.processed_search_chunk(pattern, results.take().unwrap(), range);
|
r.processed_search_chunk(pattern, results.take().unwrap(), range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1025,7 +1022,7 @@ impl Pane for CopyOverlay {
|
|||||||
|
|
||||||
fn send_paste(&self, text: &str) -> anyhow::Result<()> {
|
fn send_paste(&self, text: &str) -> anyhow::Result<()> {
|
||||||
// paste into the search bar
|
// paste into the search bar
|
||||||
let mut r = self.render.borrow_mut();
|
let mut r = self.render.lock();
|
||||||
r.pattern.push_str(text);
|
r.pattern.push_str(text);
|
||||||
r.schedule_update_search();
|
r.schedule_update_search();
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1035,7 +1032,7 @@ impl Pane for CopyOverlay {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
self.delegate.writer()
|
self.delegate.writer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,7 +1045,7 @@ impl Pane for CopyOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
||||||
let mut render = self.render.borrow_mut();
|
let mut render = self.render.lock();
|
||||||
if let Some(jump) = render.pending_jump.take() {
|
if let Some(jump) = render.pending_jump.take() {
|
||||||
match (key, mods) {
|
match (key, mods) {
|
||||||
(KeyCode::Char(c), KeyModifiers::NONE)
|
(KeyCode::Char(c), KeyModifiers::NONE)
|
||||||
@ -1093,7 +1090,7 @@ impl Pane for CopyOverlay {
|
|||||||
|
|
||||||
fn perform_assignment(&self, assignment: &KeyAssignment) -> PerformAssignmentResult {
|
fn perform_assignment(&self, assignment: &KeyAssignment) -> PerformAssignmentResult {
|
||||||
use CopyModeAssignment::*;
|
use CopyModeAssignment::*;
|
||||||
let mut render = self.render.borrow_mut();
|
let mut render = self.render.lock();
|
||||||
if render.pending_jump.is_some() {
|
if render.pending_jump.is_some() {
|
||||||
// Block key assignments until key_down is called
|
// Block key assignments until key_down is called
|
||||||
// and resolves the next state
|
// and resolves the next state
|
||||||
@ -1190,7 +1187,7 @@ impl Pane for CopyOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||||
let renderer = self.render.borrow();
|
let renderer = self.render.lock();
|
||||||
if renderer.editing_search {
|
if renderer.editing_search {
|
||||||
// place in the search box
|
// place in the search box
|
||||||
StableCursorPosition {
|
StableCursorPosition {
|
||||||
@ -1232,8 +1229,8 @@ impl Pane for CopyOverlay {
|
|||||||
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
||||||
// Take care to access self.delegate methods here before we get into
|
// Take care to access self.delegate methods here before we get into
|
||||||
// calling into its own with_lines_mut to avoid a runtime
|
// calling into its own with_lines_mut to avoid a runtime
|
||||||
// borrow erro!
|
// lock erro!
|
||||||
let mut renderer = self.render.borrow_mut();
|
let mut renderer = self.render.lock();
|
||||||
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
|
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
|
||||||
renderer.update_search();
|
renderer.update_search();
|
||||||
}
|
}
|
||||||
@ -1351,7 +1348,7 @@ impl Pane for CopyOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
||||||
let mut renderer = self.render.borrow_mut();
|
let mut renderer = self.render.lock();
|
||||||
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
|
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
|
||||||
renderer.update_search();
|
renderer.update_search();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub fn start_overlay<T, F>(
|
|||||||
tab: &Rc<Tab>,
|
tab: &Rc<Tab>,
|
||||||
func: F,
|
func: F,
|
||||||
) -> (
|
) -> (
|
||||||
Rc<dyn Pane>,
|
Arc<dyn Pane>,
|
||||||
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
|
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@ -54,10 +54,10 @@ where
|
|||||||
|
|
||||||
pub fn start_overlay_pane<T, F>(
|
pub fn start_overlay_pane<T, F>(
|
||||||
term_window: &TermWindow,
|
term_window: &TermWindow,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
func: F,
|
func: F,
|
||||||
) -> (
|
) -> (
|
||||||
Rc<dyn Pane>,
|
Arc<dyn Pane>,
|
||||||
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
|
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -7,11 +7,10 @@ use mux::pane::{
|
|||||||
ForEachPaneLogicalLine, LogicalLine, Pane, PaneId, Pattern, SearchResult, WithPaneLines,
|
ForEachPaneLogicalLine, LogicalLine, Pane, PaneId, Pattern, SearchResult, WithPaneLines,
|
||||||
};
|
};
|
||||||
use mux::renderable::*;
|
use mux::renderable::*;
|
||||||
|
use parking_lot::{MappedMutexGuard, Mutex};
|
||||||
use rangeset::RangeSet;
|
use rangeset::RangeSet;
|
||||||
use std::cell::{RefCell, RefMut};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use termwiz::cell::{Cell, CellAttributes};
|
use termwiz::cell::{Cell, CellAttributes};
|
||||||
use termwiz::color::AnsiColor;
|
use termwiz::color::AnsiColor;
|
||||||
@ -148,8 +147,8 @@ mod alphabet_test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct QuickSelectOverlay {
|
pub struct QuickSelectOverlay {
|
||||||
renderer: RefCell<QuickSelectRenderable>,
|
renderer: Mutex<QuickSelectRenderable>,
|
||||||
delegate: Rc<dyn Pane>,
|
delegate: Arc<dyn Pane>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -159,7 +158,7 @@ struct MatchResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct QuickSelectRenderable {
|
struct QuickSelectRenderable {
|
||||||
delegate: Rc<dyn Pane>,
|
delegate: Arc<dyn Pane>,
|
||||||
/// The text that the user entered
|
/// The text that the user entered
|
||||||
pattern: Pattern,
|
pattern: Pattern,
|
||||||
/// The most recently queried set of matches
|
/// The most recently queried set of matches
|
||||||
@ -186,9 +185,9 @@ struct QuickSelectRenderable {
|
|||||||
impl QuickSelectOverlay {
|
impl QuickSelectOverlay {
|
||||||
pub fn with_pane(
|
pub fn with_pane(
|
||||||
term_window: &TermWindow,
|
term_window: &TermWindow,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
args: &QuickSelectArguments,
|
args: &QuickSelectArguments,
|
||||||
) -> Rc<dyn Pane> {
|
) -> Arc<dyn Pane> {
|
||||||
let viewport = term_window.get_viewport(pane.pane_id());
|
let viewport = term_window.get_viewport(pane.pane_id());
|
||||||
let dims = pane.get_dimensions();
|
let dims = pane.get_dimensions();
|
||||||
|
|
||||||
@ -228,7 +227,7 @@ impl QuickSelectOverlay {
|
|||||||
|
|
||||||
let window = term_window.window.clone().unwrap();
|
let window = term_window.window.clone().unwrap();
|
||||||
let mut renderer = QuickSelectRenderable {
|
let mut renderer = QuickSelectRenderable {
|
||||||
delegate: Rc::clone(pane),
|
delegate: Arc::clone(pane),
|
||||||
pattern,
|
pattern,
|
||||||
selection: "".to_string(),
|
selection: "".to_string(),
|
||||||
results: vec![],
|
results: vec![],
|
||||||
@ -249,14 +248,14 @@ impl QuickSelectOverlay {
|
|||||||
renderer.dirty_results.add(search_row);
|
renderer.dirty_results.add(search_row);
|
||||||
renderer.update_search(true);
|
renderer.update_search(true);
|
||||||
|
|
||||||
Rc::new(QuickSelectOverlay {
|
Arc::new(QuickSelectOverlay {
|
||||||
renderer: RefCell::new(renderer),
|
renderer: Mutex::new(renderer),
|
||||||
delegate: Rc::clone(pane),
|
delegate: Arc::clone(pane),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn viewport_changed(&self, viewport: Option<StableRowIndex>) {
|
pub fn viewport_changed(&self, viewport: Option<StableRowIndex>) {
|
||||||
let mut render = self.renderer.borrow_mut();
|
let mut render = self.renderer.lock();
|
||||||
if render.viewport != viewport {
|
if render.viewport != viewport {
|
||||||
if let Some(last) = render.last_bar_pos.take() {
|
if let Some(last) = render.last_bar_pos.take() {
|
||||||
render.dirty_results.add(last);
|
render.dirty_results.add(last);
|
||||||
@ -287,7 +286,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writer(&self) -> RefMut<dyn std::io::Write> {
|
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
|
||||||
self.delegate.writer()
|
self.delegate.writer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,12 +300,12 @@ impl Pane for QuickSelectOverlay {
|
|||||||
|
|
||||||
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
|
||||||
match (key, mods) {
|
match (key, mods) {
|
||||||
(KeyCode::Escape, KeyModifiers::NONE) => self.renderer.borrow().close(),
|
(KeyCode::Escape, KeyModifiers::NONE) => self.renderer.lock().close(),
|
||||||
(KeyCode::UpArrow, KeyModifiers::NONE)
|
(KeyCode::UpArrow, KeyModifiers::NONE)
|
||||||
| (KeyCode::Enter, KeyModifiers::NONE)
|
| (KeyCode::Enter, KeyModifiers::NONE)
|
||||||
| (KeyCode::Char('p'), KeyModifiers::CTRL) => {
|
| (KeyCode::Char('p'), KeyModifiers::CTRL) => {
|
||||||
// Move to prior match
|
// Move to prior match
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
if let Some(cur) = r.result_pos.as_ref() {
|
if let Some(cur) = r.result_pos.as_ref() {
|
||||||
let prior = if *cur > 0 {
|
let prior = if *cur > 0 {
|
||||||
cur - 1
|
cur - 1
|
||||||
@ -320,7 +319,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
// Skip this page of matches and move up to the first match from
|
// Skip this page of matches and move up to the first match from
|
||||||
// the prior page.
|
// the prior page.
|
||||||
let dims = self.delegate.get_dimensions();
|
let dims = self.delegate.get_dimensions();
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
if let Some(cur) = r.result_pos {
|
if let Some(cur) = r.result_pos {
|
||||||
let top = r.viewport.unwrap_or(dims.physical_top);
|
let top = r.viewport.unwrap_or(dims.physical_top);
|
||||||
let prior = top - dims.viewport_rows as isize;
|
let prior = top - dims.viewport_rows as isize;
|
||||||
@ -339,7 +338,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
// Skip this page of matches and move down to the first match from
|
// Skip this page of matches and move down to the first match from
|
||||||
// the next page.
|
// the next page.
|
||||||
let dims = self.delegate.get_dimensions();
|
let dims = self.delegate.get_dimensions();
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
if let Some(cur) = r.result_pos {
|
if let Some(cur) = r.result_pos {
|
||||||
let top = r.viewport.unwrap_or(dims.physical_top);
|
let top = r.viewport.unwrap_or(dims.physical_top);
|
||||||
let bottom = top + dims.viewport_rows as isize;
|
let bottom = top + dims.viewport_rows as isize;
|
||||||
@ -353,7 +352,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
}
|
}
|
||||||
(KeyCode::DownArrow, KeyModifiers::NONE) | (KeyCode::Char('n'), KeyModifiers::CTRL) => {
|
(KeyCode::DownArrow, KeyModifiers::NONE) | (KeyCode::Char('n'), KeyModifiers::CTRL) => {
|
||||||
// Move to next match
|
// Move to next match
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
if let Some(cur) = r.result_pos.as_ref() {
|
if let Some(cur) = r.result_pos.as_ref() {
|
||||||
let next = if *cur + 1 >= r.results.len() {
|
let next = if *cur + 1 >= r.results.len() {
|
||||||
0
|
0
|
||||||
@ -365,7 +364,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
}
|
}
|
||||||
(KeyCode::Char(c), KeyModifiers::NONE) | (KeyCode::Char(c), KeyModifiers::SHIFT) => {
|
(KeyCode::Char(c), KeyModifiers::NONE) | (KeyCode::Char(c), KeyModifiers::SHIFT) => {
|
||||||
// Type to add to the selection
|
// Type to add to the selection
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
r.selection.push(c);
|
r.selection.push(c);
|
||||||
let lowered = r.selection.to_lowercase();
|
let lowered = r.selection.to_lowercase();
|
||||||
let paste = lowered != r.selection;
|
let paste = lowered != r.selection;
|
||||||
@ -376,12 +375,12 @@ impl Pane for QuickSelectOverlay {
|
|||||||
}
|
}
|
||||||
(KeyCode::Backspace, KeyModifiers::NONE) => {
|
(KeyCode::Backspace, KeyModifiers::NONE) => {
|
||||||
// Backspace to edit the selection
|
// Backspace to edit the selection
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
r.selection.pop();
|
r.selection.pop();
|
||||||
}
|
}
|
||||||
(KeyCode::Char('u'), KeyModifiers::CTRL) => {
|
(KeyCode::Char('u'), KeyModifiers::CTRL) => {
|
||||||
// CTRL-u to clear the selection
|
// CTRL-u to clear the selection
|
||||||
let mut r = self.renderer.borrow_mut();
|
let mut r = self.renderer.lock();
|
||||||
r.selection.clear();
|
r.selection.clear();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -431,7 +430,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
|
|
||||||
fn get_cursor_position(&self) -> StableCursorPosition {
|
fn get_cursor_position(&self) -> StableCursorPosition {
|
||||||
// move to the search box
|
// move to the search box
|
||||||
let renderer = self.renderer.borrow();
|
let renderer = self.renderer.lock();
|
||||||
StableCursorPosition {
|
StableCursorPosition {
|
||||||
x: 8 + wezterm_term::unicode_column_width(&renderer.selection, None),
|
x: 8 + wezterm_term::unicode_column_width(&renderer.selection, None),
|
||||||
y: renderer.compute_search_row(),
|
y: renderer.compute_search_row(),
|
||||||
@ -450,7 +449,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
seqno: SequenceNo,
|
seqno: SequenceNo,
|
||||||
) -> RangeSet<StableRowIndex> {
|
) -> RangeSet<StableRowIndex> {
|
||||||
let mut dirty = self.delegate.get_changed_since(lines.clone(), seqno);
|
let mut dirty = self.delegate.get_changed_since(lines.clone(), seqno);
|
||||||
dirty.add_set(&self.renderer.borrow().dirty_results);
|
dirty.add_set(&self.renderer.lock().dirty_results);
|
||||||
dirty.intersection_with_range(lines)
|
dirty.intersection_with_range(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,7 +467,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
fn with_lines_mut(&self, lines: Range<StableRowIndex>, with_lines: &mut dyn WithPaneLines) {
|
||||||
let mut renderer = self.renderer.borrow_mut();
|
let mut renderer = self.renderer.lock();
|
||||||
// Take care to access self.delegate methods here before we get into
|
// Take care to access self.delegate methods here before we get into
|
||||||
// calling into its own with_lines_mut to avoid a runtime
|
// calling into its own with_lines_mut to avoid a runtime
|
||||||
// borrow erro!
|
// borrow erro!
|
||||||
@ -579,7 +578,7 @@ impl Pane for QuickSelectOverlay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
fn get_lines(&self, lines: Range<StableRowIndex>) -> (StableRowIndex, Vec<Line>) {
|
||||||
let mut renderer = self.renderer.borrow_mut();
|
let mut renderer = self.renderer.lock();
|
||||||
renderer.check_for_resize();
|
renderer.check_for_resize();
|
||||||
let dims = self.get_dimensions();
|
let dims = self.get_dimensions();
|
||||||
|
|
||||||
@ -791,7 +790,7 @@ impl QuickSelectRenderable {
|
|||||||
self.dirty_results.add(bar_pos);
|
self.dirty_results.add(bar_pos);
|
||||||
|
|
||||||
if !self.pattern.is_empty() {
|
if !self.pattern.is_empty() {
|
||||||
let pane: Rc<dyn Pane> = self.delegate.clone();
|
let pane: Arc<dyn Pane> = self.delegate.clone();
|
||||||
let window = self.window.clone();
|
let window = self.window.clone();
|
||||||
let pattern = self.pattern.clone();
|
let pattern = self.pattern.clone();
|
||||||
let scope = self.args.scope_lines;
|
let scope = self.args.scope_lines;
|
||||||
@ -814,7 +813,7 @@ impl QuickSelectRenderable {
|
|||||||
if let Some(search_overlay) =
|
if let Some(search_overlay) =
|
||||||
overlay.pane.downcast_ref::<QuickSelectOverlay>()
|
overlay.pane.downcast_ref::<QuickSelectOverlay>()
|
||||||
{
|
{
|
||||||
let mut r = search_overlay.renderer.borrow_mut();
|
let mut r = search_overlay.renderer.lock();
|
||||||
r.results = results.take().unwrap();
|
r.results = results.take().unwrap();
|
||||||
r.recompute_results();
|
r.recompute_results();
|
||||||
let num_results = r.results.len();
|
let num_results = r.results.len();
|
||||||
|
@ -3,7 +3,7 @@ use crate::TermWindow;
|
|||||||
use config::keyassignment::{ClipboardCopyDestination, ClipboardPasteSource};
|
use config::keyassignment::{ClipboardCopyDestination, ClipboardPasteSource};
|
||||||
use mux::pane::Pane;
|
use mux::pane::Pane;
|
||||||
use mux::Mux;
|
use mux::Mux;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use window::{Clipboard, WindowOps};
|
use window::{Clipboard, WindowOps};
|
||||||
|
|
||||||
impl TermWindow {
|
impl TermWindow {
|
||||||
@ -23,7 +23,7 @@ impl TermWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paste_from_clipboard(&mut self, pane: &Rc<dyn Pane>, clipboard: ClipboardPasteSource) {
|
pub fn paste_from_clipboard(&mut self, pane: &Arc<dyn Pane>, clipboard: ClipboardPasteSource) {
|
||||||
let pane_id = pane.pane_id();
|
let pane_id = pane.pane_id();
|
||||||
log::trace!(
|
log::trace!(
|
||||||
"paste_from_clipboard in pane {} {:?}",
|
"paste_from_clipboard in pane {} {:?}",
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::Context;
|
|||||||
use config::keyassignment::{KeyAssignment, KeyTableEntry};
|
use config::keyassignment::{KeyAssignment, KeyTableEntry};
|
||||||
use mux::pane::{Pane, PerformAssignmentResult};
|
use mux::pane::{Pane, PerformAssignmentResult};
|
||||||
use smol::Timer;
|
use smol::Timer;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use termwiz::input::KeyboardEncoding;
|
use termwiz::input::KeyboardEncoding;
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ enum OnlyKeyBindings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl super::TermWindow {
|
impl super::TermWindow {
|
||||||
fn encode_win32_input(&self, pane: &Rc<dyn Pane>, key: &KeyEvent) -> Option<String> {
|
fn encode_win32_input(&self, pane: &Arc<dyn Pane>, key: &KeyEvent) -> Option<String> {
|
||||||
if !self.config.allow_win32_input_mode
|
if !self.config.allow_win32_input_mode
|
||||||
|| pane.get_keyboard_encoding() != KeyboardEncoding::Win32
|
|| pane.get_keyboard_encoding() != KeyboardEncoding::Win32
|
||||||
{
|
{
|
||||||
@ -229,7 +229,7 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
fn lookup_key(
|
fn lookup_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
keycode: &KeyCode,
|
keycode: &KeyCode,
|
||||||
mods: Modifiers,
|
mods: Modifiers,
|
||||||
only_key_bindings: OnlyKeyBindings,
|
only_key_bindings: OnlyKeyBindings,
|
||||||
@ -257,7 +257,7 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
fn process_key(
|
fn process_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
keycode: &KeyCode,
|
keycode: &KeyCode,
|
||||||
raw_modifiers: Modifiers,
|
raw_modifiers: Modifiers,
|
||||||
|
@ -176,7 +176,7 @@ pub struct SemanticZoneCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct OverlayState {
|
pub struct OverlayState {
|
||||||
pub pane: Rc<dyn Pane>,
|
pub pane: Arc<dyn Pane>,
|
||||||
key_table_state: KeyTableState,
|
key_table_state: KeyTableState,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,7 +1466,7 @@ impl TermWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_dirty_lines_and_invalidate_selection(&mut self, pane: &Rc<dyn Pane>) {
|
fn check_for_dirty_lines_and_invalidate_selection(&mut self, pane: &Arc<dyn Pane>) {
|
||||||
let dims = pane.get_dimensions();
|
let dims = pane.get_dimensions();
|
||||||
let viewport = self
|
let viewport = self
|
||||||
.get_viewport(pane.pane_id())
|
.get_viewport(pane.pane_id())
|
||||||
@ -2095,7 +2095,7 @@ impl TermWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the Prompt semantic zones
|
/// Returns the Prompt semantic zones
|
||||||
fn get_semantic_prompt_zones(&mut self, pane: &Rc<dyn Pane>) -> &[StableRowIndex] {
|
fn get_semantic_prompt_zones(&mut self, pane: &Arc<dyn Pane>) -> &[StableRowIndex] {
|
||||||
let mut cache = self
|
let mut cache = self
|
||||||
.semantic_zones
|
.semantic_zones
|
||||||
.entry(pane.pane_id())
|
.entry(pane.pane_id())
|
||||||
@ -2222,7 +2222,7 @@ impl TermWindow {
|
|||||||
|
|
||||||
pub fn perform_key_assignment(
|
pub fn perform_key_assignment(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
assignment: &KeyAssignment,
|
assignment: &KeyAssignment,
|
||||||
) -> anyhow::Result<PerformAssignmentResult> {
|
) -> anyhow::Result<PerformAssignmentResult> {
|
||||||
use KeyAssignment::*;
|
use KeyAssignment::*;
|
||||||
@ -2764,7 +2764,7 @@ impl TermWindow {
|
|||||||
Ok(PerformAssignmentResult::Handled)
|
Ok(PerformAssignmentResult::Handled)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_open_link_at_mouse_cursor(&self, pane: &Rc<dyn Pane>) {
|
fn do_open_link_at_mouse_cursor(&self, pane: &Arc<dyn Pane>) {
|
||||||
// They clicked on a link, so let's open it!
|
// They clicked on a link, so let's open it!
|
||||||
// We need to ensure that we spawn the `open` call outside of the context
|
// We need to ensure that we spawn the `open` call outside of the context
|
||||||
// of our window loop; on Windows it can cause a panic due to
|
// of our window loop; on Windows it can cause a panic due to
|
||||||
@ -2967,22 +2967,22 @@ impl TermWindow {
|
|||||||
self.window.as_ref().unwrap().invalidate();
|
self.window.as_ref().unwrap().invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_scroll_to_bottom_for_input(&mut self, pane: &Rc<dyn Pane>) {
|
fn maybe_scroll_to_bottom_for_input(&mut self, pane: &Arc<dyn Pane>) {
|
||||||
if self.config.scroll_to_bottom_on_input {
|
if self.config.scroll_to_bottom_on_input {
|
||||||
self.scroll_to_bottom(pane);
|
self.scroll_to_bottom(pane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to_top(&mut self, pane: &Rc<dyn Pane>) {
|
fn scroll_to_top(&mut self, pane: &Arc<dyn Pane>) {
|
||||||
let dims = pane.get_dimensions();
|
let dims = pane.get_dimensions();
|
||||||
self.set_viewport(pane.pane_id(), Some(dims.scrollback_top), dims);
|
self.set_viewport(pane.pane_id(), Some(dims.scrollback_top), dims);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_to_bottom(&mut self, pane: &Rc<dyn Pane>) {
|
fn scroll_to_bottom(&mut self, pane: &Arc<dyn Pane>) {
|
||||||
self.pane_state(pane.pane_id()).viewport = None;
|
self.pane_state(pane.pane_id()).viewport = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_active_pane_no_overlay(&self) -> Option<Rc<dyn Pane>> {
|
fn get_active_pane_no_overlay(&self) -> Option<Arc<dyn Pane>> {
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
mux.get_active_tab_for_window(self.mux_window_id)
|
mux.get_active_tab_for_window(self.mux_window_id)
|
||||||
.and_then(|tab| tab.get_active_pane())
|
.and_then(|tab| tab.get_active_pane())
|
||||||
@ -2994,7 +2994,7 @@ impl TermWindow {
|
|||||||
/// then that will be returned instead. Otherwise, if the pane has
|
/// then that will be returned instead. Otherwise, if the pane has
|
||||||
/// an active overlay (such as search or copy mode) then that will
|
/// an active overlay (such as search or copy mode) then that will
|
||||||
/// be returned.
|
/// be returned.
|
||||||
pub fn get_active_pane_or_overlay(&self) -> Option<Rc<dyn Pane>> {
|
pub fn get_active_pane_or_overlay(&self) -> Option<Arc<dyn Pane>> {
|
||||||
let mux = Mux::get().unwrap();
|
let mux = Mux::get().unwrap();
|
||||||
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
|
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
|
||||||
Some(tab) => tab,
|
Some(tab) => tab,
|
||||||
@ -3116,7 +3116,7 @@ impl TermWindow {
|
|||||||
let mut panes = tab.iter_panes();
|
let mut panes = tab.iter_panes();
|
||||||
for p in &mut panes {
|
for p in &mut panes {
|
||||||
if let Some(overlay) = self.pane_state(p.pane.pane_id()).overlay.as_ref() {
|
if let Some(overlay) = self.pane_state(p.pane.pane_id()).overlay.as_ref() {
|
||||||
p.pane = Rc::clone(&overlay.pane);
|
p.pane = Arc::clone(&overlay.pane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panes
|
panes
|
||||||
@ -3177,7 +3177,7 @@ impl TermWindow {
|
|||||||
window.notify(TermWindowNotif::CancelOverlayForPane(pane_id));
|
window.notify(TermWindowNotif::CancelOverlayForPane(pane_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_overlay_for_pane(&mut self, pane_id: PaneId, pane: Rc<dyn Pane>) {
|
pub fn assign_overlay_for_pane(&mut self, pane_id: PaneId, pane: Arc<dyn Pane>) {
|
||||||
self.cancel_overlay_for_pane(pane_id);
|
self.cancel_overlay_for_pane(pane_id);
|
||||||
self.pane_state(pane_id).overlay.replace(OverlayState {
|
self.pane_state(pane_id).overlay.replace(OverlayState {
|
||||||
pane,
|
pane,
|
||||||
@ -3186,7 +3186,7 @@ impl TermWindow {
|
|||||||
self.update_title();
|
self.update_title();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_overlay(&mut self, tab_id: TabId, overlay: Rc<dyn Pane>) {
|
pub fn assign_overlay(&mut self, tab_id: TabId, overlay: Arc<dyn Pane>) {
|
||||||
self.cancel_overlay_for_tab(tab_id, None);
|
self.cancel_overlay_for_tab(tab_id, None);
|
||||||
self.tab_state(tab_id).overlay.replace(OverlayState {
|
self.tab_state(tab_id).overlay.replace(OverlayState {
|
||||||
pane: overlay,
|
pane: overlay,
|
||||||
@ -3195,7 +3195,7 @@ impl TermWindow {
|
|||||||
self.update_title();
|
self.update_title();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_search_pattern(&self, pattern: Pattern, pane: &Rc<dyn Pane>) -> MuxPattern {
|
fn resolve_search_pattern(&self, pattern: Pattern, pane: &Arc<dyn Pane>) -> MuxPattern {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::CaseSensitiveString(s) => MuxPattern::CaseSensitiveString(s),
|
Pattern::CaseSensitiveString(s) => MuxPattern::CaseSensitiveString(s),
|
||||||
Pattern::CaseInSensitiveString(s) => MuxPattern::CaseInSensitiveString(s),
|
Pattern::CaseInSensitiveString(s) => MuxPattern::CaseInSensitiveString(s),
|
||||||
|
@ -12,7 +12,6 @@ use mux::tab::SplitDirection;
|
|||||||
use mux::Mux;
|
use mux::Mux;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ops::Sub;
|
use std::ops::Sub;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use termwiz::hyperlink::Hyperlink;
|
use termwiz::hyperlink::Hyperlink;
|
||||||
@ -347,7 +346,7 @@ impl super::TermWindow {
|
|||||||
fn mouse_event_ui_item(
|
fn mouse_event_ui_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: UIItem,
|
item: UIItem,
|
||||||
pane: Rc<dyn Pane>,
|
pane: Arc<dyn Pane>,
|
||||||
_y: i64,
|
_y: i64,
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
@ -453,7 +452,7 @@ impl super::TermWindow {
|
|||||||
pub fn mouse_event_above_scroll_thumb(
|
pub fn mouse_event_above_scroll_thumb(
|
||||||
&mut self,
|
&mut self,
|
||||||
_item: UIItem,
|
_item: UIItem,
|
||||||
pane: Rc<dyn Pane>,
|
pane: Arc<dyn Pane>,
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
) {
|
) {
|
||||||
@ -478,7 +477,7 @@ impl super::TermWindow {
|
|||||||
pub fn mouse_event_below_scroll_thumb(
|
pub fn mouse_event_below_scroll_thumb(
|
||||||
&mut self,
|
&mut self,
|
||||||
_item: UIItem,
|
_item: UIItem,
|
||||||
pane: Rc<dyn Pane>,
|
pane: Arc<dyn Pane>,
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
) {
|
) {
|
||||||
@ -503,7 +502,7 @@ impl super::TermWindow {
|
|||||||
pub fn mouse_event_scroll_thumb(
|
pub fn mouse_event_scroll_thumb(
|
||||||
&mut self,
|
&mut self,
|
||||||
item: UIItem,
|
item: UIItem,
|
||||||
_pane: Rc<dyn Pane>,
|
_pane: Arc<dyn Pane>,
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
) {
|
) {
|
||||||
@ -534,7 +533,7 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
fn mouse_event_terminal(
|
fn mouse_event_terminal(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut pane: Rc<dyn Pane>,
|
mut pane: Arc<dyn Pane>,
|
||||||
position: ClickPosition,
|
position: ClickPosition,
|
||||||
event: MouseEvent,
|
event: MouseEvent,
|
||||||
context: &dyn WindowOps,
|
context: &dyn WindowOps,
|
||||||
@ -569,7 +568,7 @@ impl super::TermWindow {
|
|||||||
mux.get_active_tab_for_window(self.mux_window_id)
|
mux.get_active_tab_for_window(self.mux_window_id)
|
||||||
.map(|tab| tab.set_active_idx(pos.index));
|
.map(|tab| tab.set_active_idx(pos.index));
|
||||||
|
|
||||||
pane = Rc::clone(&pos.pane);
|
pane = Arc::clone(&pos.pane);
|
||||||
is_click_to_focus_pane = true;
|
is_click_to_focus_pane = true;
|
||||||
}
|
}
|
||||||
WMEK::Move => {
|
WMEK::Move => {
|
||||||
@ -578,7 +577,7 @@ impl super::TermWindow {
|
|||||||
mux.get_active_tab_for_window(self.mux_window_id)
|
mux.get_active_tab_for_window(self.mux_window_id)
|
||||||
.map(|tab| tab.set_active_idx(pos.index));
|
.map(|tab| tab.set_active_idx(pos.index));
|
||||||
|
|
||||||
pane = Rc::clone(&pos.pane);
|
pane = Arc::clone(&pos.pane);
|
||||||
context.invalidate();
|
context.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,7 +585,7 @@ impl super::TermWindow {
|
|||||||
WMEK::VertWheel(_) => {
|
WMEK::VertWheel(_) => {
|
||||||
// Let wheel events route to the hovered pane,
|
// Let wheel events route to the hovered pane,
|
||||||
// even if it doesn't have focus
|
// even if it doesn't have focus
|
||||||
pane = Rc::clone(&pos.pane);
|
pane = Arc::clone(&pos.pane);
|
||||||
context.invalidate();
|
context.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ pub struct RenderScreenLineOpenGLParams<'a> {
|
|||||||
pub palette: &'a ColorPalette,
|
pub palette: &'a ColorPalette,
|
||||||
pub dims: &'a RenderableDimensions,
|
pub dims: &'a RenderableDimensions,
|
||||||
pub config: &'a ConfigHandle,
|
pub config: &'a ConfigHandle,
|
||||||
pub pane: Option<&'a Rc<dyn Pane>>,
|
pub pane: Option<&'a Arc<dyn Pane>>,
|
||||||
|
|
||||||
pub white_space: TextureRect,
|
pub white_space: TextureRect,
|
||||||
pub filled_box: TextureRect,
|
pub filled_box: TextureRect,
|
||||||
@ -299,7 +299,7 @@ pub struct ComputeCellFgBgParams<'a> {
|
|||||||
pub cursor_bg: LinearRgba,
|
pub cursor_bg: LinearRgba,
|
||||||
pub cursor_is_default_color: bool,
|
pub cursor_is_default_color: bool,
|
||||||
pub cursor_border_color: LinearRgba,
|
pub cursor_border_color: LinearRgba,
|
||||||
pub pane: Option<&'a Rc<dyn Pane>>,
|
pub pane: Option<&'a Arc<dyn Pane>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -461,7 +461,7 @@ impl super::TermWindow {
|
|||||||
|
|
||||||
fn get_intensity_if_bell_target_ringing(
|
fn get_intensity_if_bell_target_ringing(
|
||||||
&self,
|
&self,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
config: &ConfigHandle,
|
config: &ConfigHandle,
|
||||||
target: VisualBellTarget,
|
target: VisualBellTarget,
|
||||||
) -> Option<f32> {
|
) -> Option<f32> {
|
||||||
@ -2183,7 +2183,7 @@ impl super::TermWindow {
|
|||||||
&mut self,
|
&mut self,
|
||||||
layers: &mut TripleLayerQuadAllocator,
|
layers: &mut TripleLayerQuadAllocator,
|
||||||
split: &PositionedSplit,
|
split: &PositionedSplit,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let palette = pane.palette();
|
let palette = pane.palette();
|
||||||
let foreground = palette.split.to_linear();
|
let foreground = palette.split.to_linear();
|
||||||
|
@ -2,7 +2,7 @@ use crate::selection::{Selection, SelectionCoordinate, SelectionMode, SelectionR
|
|||||||
use ::window::WindowOps;
|
use ::window::WindowOps;
|
||||||
use mux::pane::{Pane, PaneId};
|
use mux::pane::{Pane, PaneId};
|
||||||
use std::cell::RefMut;
|
use std::cell::RefMut;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
use termwiz::surface::Line;
|
use termwiz::surface::Line;
|
||||||
use wezterm_term::StableRowIndex;
|
use wezterm_term::StableRowIndex;
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ impl super::TermWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the selection region as a series of Line
|
/// Returns the selection region as a series of Line
|
||||||
pub fn selection_lines(&self, pane: &Rc<dyn Pane>) -> Vec<Line> {
|
pub fn selection_lines(&self, pane: &Arc<dyn Pane>) -> Vec<Line> {
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
|
|
||||||
let rectangular = self.selection(pane.pane_id()).rectangular;
|
let rectangular = self.selection(pane.pane_id()).rectangular;
|
||||||
@ -63,7 +63,7 @@ impl super::TermWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the selection text only
|
/// Returns the selection text only
|
||||||
pub fn selection_text(&self, pane: &Rc<dyn Pane>) -> String {
|
pub fn selection_text(&self, pane: &Arc<dyn Pane>) -> String {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
let rectangular = self.selection(pane.pane_id()).rectangular;
|
let rectangular = self.selection(pane.pane_id()).rectangular;
|
||||||
if let Some(sel) = self
|
if let Some(sel) = self
|
||||||
@ -109,14 +109,14 @@ impl super::TermWindow {
|
|||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_selection(&mut self, pane: &Rc<dyn Pane>) {
|
pub fn clear_selection(&mut self, pane: &Arc<dyn Pane>) {
|
||||||
let mut selection = self.selection(pane.pane_id());
|
let mut selection = self.selection(pane.pane_id());
|
||||||
selection.clear();
|
selection.clear();
|
||||||
selection.seqno = pane.get_current_seqno();
|
selection.seqno = pane.get_current_seqno();
|
||||||
self.window.as_ref().unwrap().invalidate();
|
self.window.as_ref().unwrap().invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend_selection_at_mouse_cursor(&mut self, mode: SelectionMode, pane: &Rc<dyn Pane>) {
|
pub fn extend_selection_at_mouse_cursor(&mut self, mode: SelectionMode, pane: &Arc<dyn Pane>) {
|
||||||
self.selection(pane.pane_id()).seqno = pane.get_current_seqno();
|
self.selection(pane.pane_id()).seqno = pane.get_current_seqno();
|
||||||
let (position, y) = match self.pane_state(pane.pane_id()).mouse_terminal_coords {
|
let (position, y) = match self.pane_state(pane.pane_id()).mouse_terminal_coords {
|
||||||
Some(coords) => coords,
|
Some(coords) => coords,
|
||||||
@ -240,7 +240,7 @@ impl super::TermWindow {
|
|||||||
self.window.as_ref().unwrap().invalidate();
|
self.window.as_ref().unwrap().invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_text_at_mouse_cursor(&mut self, mode: SelectionMode, pane: &Rc<dyn Pane>) {
|
pub fn select_text_at_mouse_cursor(&mut self, mode: SelectionMode, pane: &Arc<dyn Pane>) {
|
||||||
let (x, y) = match self.pane_state(pane.pane_id()).mouse_terminal_coords {
|
let (x, y) = match self.pane_state(pane.pane_id()).mouse_terminal_coords {
|
||||||
Some(coords) => (coords.0.column, coords.1),
|
Some(coords) => (coords.0.column, coords.1),
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -9,7 +9,6 @@ use mux::tab::TabId;
|
|||||||
use mux::Mux;
|
use mux::Mux;
|
||||||
use promise::spawn::spawn_into_main_thread;
|
use promise::spawn::spawn_into_main_thread;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use termwiz::surface::SequenceNo;
|
use termwiz::surface::SequenceNo;
|
||||||
@ -51,7 +50,7 @@ pub(crate) struct PerPane {
|
|||||||
impl PerPane {
|
impl PerPane {
|
||||||
fn compute_changes(
|
fn compute_changes(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
force_with_input_serial: Option<InputSerial>,
|
force_with_input_serial: Option<InputSerial>,
|
||||||
) -> Option<GetPaneRenderChangesResponse> {
|
) -> Option<GetPaneRenderChangesResponse> {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
@ -139,7 +138,7 @@ impl PerPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_push_pane_changes(
|
fn maybe_push_pane_changes(
|
||||||
pane: &Rc<dyn Pane>,
|
pane: &Arc<dyn Pane>,
|
||||||
sender: PduSender,
|
sender: PduSender,
|
||||||
per_pane: Arc<Mutex<PerPane>>,
|
per_pane: Arc<Mutex<PerPane>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
Loading…
Reference in New Issue
Block a user