1
1
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:
Wez Furlong 2022-11-23 09:05:30 -07:00
parent 758a09f55f
commit 6e06b9af02
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
37 changed files with 423 additions and 426 deletions

3
Cargo.lock generated
View File

@ -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",

View File

@ -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)))
} }

View File

@ -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" }

View File

@ -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,

View File

@ -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(&current_pane))), command_dir: self.resolve_cwd(command_dir, Some(Arc::clone(&current_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")?;

View File

@ -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();
} }
} }

View File

@ -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);

View File

@ -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,

View File

@ -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(())
} }

View File

@ -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);

View File

@ -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");
} }

View File

@ -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")?;

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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::{

View File

@ -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(),

View File

@ -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.

View File

@ -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::{

View File

@ -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(())
} }
} }

View File

@ -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" }

View File

@ -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)?;

View File

@ -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()
} }
} }

View File

@ -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();

View File

@ -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;

View File

@ -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"

View File

@ -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();
} }

View File

@ -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

View File

@ -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();

View File

@ -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 {} {:?}",

View File

@ -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,

View File

@ -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),

View File

@ -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();
} }
} }

View File

@ -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();

View File

@ -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,

View File

@ -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<()> {