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",
"nix 0.25.1",
"ntapi",
"parking_lot 0.12.1",
"percent-encoding",
"portable-pty",
"procinfo",
@ -5781,6 +5782,7 @@ dependencies = [
"metrics",
"mux",
"openssl",
"parking_lot 0.12.1",
"portable-pty",
"promise",
"rangeset",
@ -5918,6 +5920,7 @@ dependencies = [
"mux-lua",
"open",
"ordered-float",
"parking_lot 0.12.1",
"portable-pty",
"promise",
"pulldown-cmark",

View File

@ -1,11 +1,12 @@
use super::*;
use luahelper::dynamic_to_lua_value;
use std::sync::Arc;
#[derive(Clone, Copy, Debug)]
pub struct MuxPane(pub PaneId);
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)
.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"
names = { version = "0.12", default-features = false }
nix = {version="0.25", features=["term"]}
parking_lot = "0.12"
percent-encoding = "2"
portable-pty = { path = "../pty", features = ["serde_support"]}
procinfo = { path = "../procinfo" }

View File

@ -74,7 +74,7 @@ pub trait Domain: Downcast {
tab: TabId,
pane_id: PaneId,
split_request: SplitRequest,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
let mux = Mux::get().unwrap();
let tab = match mux.get_tab(tab) {
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)
}
@ -133,7 +133,7 @@ pub trait Domain: Downcast {
size: TerminalSize,
command: Option<CommandBuilder>,
command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>>;
) -> anyhow::Result<Arc<dyn Pane>>;
/// Returns false if the `spawn` method will never succeed.
/// There are some internal placeholder domains that are
@ -475,7 +475,7 @@ impl Domain for LocalDomain {
size: TerminalSize,
command: Option<CommandBuilder>,
command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
let pane_id = alloc_pane_id();
let cmd = self.build_command(command, command_dir, pane_id).await?;
let pair = self
@ -510,7 +510,7 @@ impl Domain for LocalDomain {
terminal.enable_conpty_quirks();
}
let pane: Rc<dyn Pane> = Rc::new(LocalPane::new(
let pane: Arc<dyn Pane> = Arc::new(LocalPane::new(
pane_id,
terminal,
child,

View File

@ -82,7 +82,7 @@ static SUB_ID: AtomicUsize = AtomicUsize::new(0);
pub struct Mux {
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>>,
default_domain: RefCell<Option<Arc<dyn Domain>>>,
domains: RefCell<HashMap<DomainId, Arc<dyn Domain>>>,
@ -616,15 +616,15 @@ impl Mux {
res
}
pub fn get_pane(&self, pane_id: PaneId) -> Option<Rc<dyn Pane>> {
self.panes.borrow().get(&pane_id).map(Rc::clone)
pub fn get_pane(&self, pane_id: PaneId) -> Option<Arc<dyn Pane>> {
self.panes.borrow().get(&pane_id).map(Arc::clone)
}
pub fn get_tab(&self, tab_id: TabId) -> Option<Rc<Tab>> {
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()) {
return Ok(());
}
@ -639,7 +639,7 @@ impl Mux {
self.panes
.borrow_mut()
.insert(pane.pane_id(), Rc::clone(pane));
.insert(pane.pane_id(), Arc::clone(pane));
let pane_id = pane.pane_id();
if let Some(reader) = pane.reader()? {
let banner = self.banner.borrow().clone();
@ -857,11 +857,11 @@ impl Mux {
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
.borrow()
.iter()
.map(|(_, v)| Rc::clone(v))
.map(|(_, v)| Arc::clone(v))
.collect()
}
@ -965,7 +965,7 @@ impl Mux {
fn resolve_cwd(
&self,
command_dir: Option<String>,
pane: Option<Rc<dyn Pane>>,
pane: Option<Arc<dyn Pane>>,
) -> Option<String> {
command_dir.or_else(|| {
match pane {
@ -1000,7 +1000,7 @@ impl Mux {
request: SplitRequest,
source: SplitSource,
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
.resolve_pane_id(pane_id)
.ok_or_else(|| anyhow!("pane_id {} invalid", pane_id))?;
@ -1024,7 +1024,7 @@ impl Mux {
command_dir,
} => SplitSource::Spawn {
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,
};
@ -1105,7 +1105,7 @@ impl Mux {
size: TerminalSize,
current_pane_id: Option<PaneId>,
workspace_for_new_window: String,
) -> anyhow::Result<(Rc<Tab>, Rc<dyn Pane>, WindowId)> {
) -> anyhow::Result<(Rc<Tab>, Arc<dyn Pane>, WindowId)> {
let domain = self
.resolve_spawn_tab_domain(current_pane_id, &domain)
.context("resolve_spawn_tab_domain")?;

View File

@ -10,12 +10,12 @@ use anyhow::Error;
use async_trait::async_trait;
use config::keyassignment::ScrollbackEraseMode;
use config::{configuration, ExitBehavior};
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty, PtySize};
use procinfo::LocalProcessInfo;
use rangeset::RangeSet;
use smol::channel::{bounded, Receiver, TryRecvError};
use std::borrow::Cow;
use std::cell::{RefCell, RefMut};
use std::collections::{BTreeMap, HashMap, HashSet};
use std::convert::TryInto;
use std::io::{Result as IoResult, Write};
@ -39,7 +39,7 @@ enum ProcessState {
Running {
child_waiter: Receiver<IoResult<ExitStatus>>,
pid: Option<u32>,
signaller: Box<dyn ChildKiller>,
signaller: Box<dyn ChildKiller + Send + Sync>,
// Whether we've explicitly killed the child
killed: bool,
},
@ -57,13 +57,13 @@ struct CachedProcInfo {
pub struct LocalPane {
pane_id: PaneId,
terminal: RefCell<Terminal>,
process: RefCell<ProcessState>,
pty: RefCell<Box<dyn MasterPty>>,
writer: RefCell<Box<dyn Write>>,
terminal: Mutex<Terminal>,
process: Mutex<ProcessState>,
pty: Mutex<Box<dyn MasterPty + Send>>,
writer: Mutex<Box<dyn Write + Send>>,
domain_id: DomainId,
tmux_domain: RefCell<Option<Arc<TmuxDomainState>>>,
proc_list: RefCell<Option<CachedProcInfo>>,
tmux_domain: Mutex<Option<Arc<TmuxDomainState>>>,
proc_list: Mutex<Option<CachedProcInfo>>,
command_description: String,
}
@ -78,7 +78,7 @@ impl Pane for LocalPane {
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
#[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;
// Detect whether we might be in password 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 {
let mut cursor = terminal_get_cursor_position(&mut self.terminal.borrow_mut());
if self.tmux_domain.borrow().is_some() {
let mut cursor = terminal_get_cursor_position(&mut self.terminal.lock());
if self.tmux_domain.lock().is_some() {
cursor.visibility = termwiz::surface::CursorVisibility::Hidden;
}
cursor
}
fn get_keyboard_encoding(&self) -> KeyboardEncoding {
self.terminal.borrow().get_keyboard_encoding()
self.terminal.lock().get_keyboard_encoding()
}
fn get_current_seqno(&self) -> SequenceNo {
self.terminal.borrow().current_seqno()
self.terminal.lock().current_seqno()
}
fn get_changed_since(
@ -116,7 +116,7 @@ impl Pane for LocalPane {
lines: Range<StableRowIndex>,
seqno: SequenceNo,
) -> 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(
@ -125,14 +125,14 @@ impl Pane for LocalPane {
for_line: &mut dyn ForEachPaneLogicalLine,
) {
terminal_for_each_logical_line_in_stable_range_mut(
&mut self.terminal.borrow_mut(),
&mut self.terminal.lock(),
lines,
for_line,
);
}
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>) {
@ -144,15 +144,15 @@ impl Pane for LocalPane {
}
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> {
self.terminal.borrow().user_vars().clone()
self.terminal.lock().user_vars().clone()
}
fn kill(&self) {
let mut proc = self.process.borrow_mut();
let mut proc = self.process.lock();
log::debug!(
"killing process in pane {}, state is {:?}",
self.pane_id,
@ -173,7 +173,7 @@ impl Pane for LocalPane {
}
fn is_dead(&self) -> bool {
let mut proc = self.process.borrow_mut();
let mut proc = self.process.lock();
let mut notify = None;
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>) {
self.terminal.borrow_mut().set_clipboard(clipboard);
self.terminal.lock().set_clipboard(clipboard);
}
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>) {
self.terminal.borrow_mut().set_config(config);
self.terminal.lock().set_config(config);
}
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>) {
self.terminal.borrow_mut().perform_actions(actions)
self.terminal.lock().perform_actions(actions)
}
fn mouse_event(&self, event: MouseEvent) -> Result<(), Error> {
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> {
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);
if key == KeyCode::Char('q') {
self.terminal.borrow_mut().send_paste("detach\n")?;
self.terminal.lock().send_paste("detach\n")?;
}
return Ok(());
} 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> {
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> {
self.pty.borrow_mut().resize(PtySize {
self.pty.lock().resize(PtySize {
rows: size.rows.try_into()?,
cols: size.cols.try_into()?,
pixel_width: size.pixel_width.try_into()?,
pixel_height: size.pixel_height.try_into()?,
})?;
self.terminal.borrow_mut().resize(size);
self.terminal.lock().resize(size);
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();
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>>> {
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> {
Mux::get().unwrap().record_input_for_current_identity();
if self.tmux_domain.borrow().is_some() {
if self.tmux_domain.lock().is_some() {
Ok(())
} else {
self.terminal.borrow_mut().send_paste(text)
self.terminal.lock().send_paste(text)
}
}
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
// things up a bit by returning the process basename instead
if title == "wezterm" {
@ -343,7 +346,7 @@ impl Pane for LocalPane {
}
fn palette(&self) -> ColorPalette {
self.terminal.borrow().palette()
self.terminal.lock().palette()
}
fn domain_id(&self) -> DomainId {
@ -353,41 +356,41 @@ impl Pane for LocalPane {
fn erase_scrollback(&self, erase_mode: ScrollbackEraseMode) {
match erase_mode {
ScrollbackEraseMode::ScrollbackOnly => {
self.terminal.borrow_mut().erase_scrollback();
self.terminal.lock().erase_scrollback();
}
ScrollbackEraseMode::ScrollbackAndViewport => {
self.terminal.borrow_mut().erase_scrollback_and_viewport();
self.terminal.lock().erase_scrollback_and_viewport();
}
}
}
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 {
self.terminal.borrow().has_unseen_output()
self.terminal.lock().has_unseen_output()
}
fn is_mouse_grabbed(&self) -> bool {
if self.tmux_domain.borrow().is_some() {
if self.tmux_domain.lock().is_some() {
false
} else {
self.terminal.borrow().is_mouse_grabbed()
self.terminal.lock().is_mouse_grabbed()
}
}
fn is_alt_screen_active(&self) -> bool {
if self.tmux_domain.borrow().is_some() {
if self.tmux_domain.lock().is_some() {
false
} else {
self.terminal.borrow().is_alt_screen_active()
self.terminal.lock().is_alt_screen_active()
}
}
fn get_current_working_dir(&self) -> Option<Url> {
self.terminal
.borrow()
.lock()
.get_current_dir()
.cloned()
.or_else(|| self.divine_current_working_dir())
@ -395,7 +398,7 @@ impl Pane for LocalPane {
fn get_foreground_process_info(&self) -> Option<LocalProcessInfo> {
#[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);
}
@ -404,7 +407,7 @@ impl Pane for LocalPane {
fn get_foreground_process_name(&self) -> Option<String> {
#[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) {
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
// window, we don't need to prompt to confirm closing.
// 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;
}
}
@ -488,7 +491,7 @@ impl Pane for LocalPane {
}
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()
}
@ -498,7 +501,7 @@ impl Pane for LocalPane {
range: Range<StableRowIndex>,
limit: Option<u32>,
) -> anyhow::Result<Vec<SearchResult>> {
let term = self.terminal.borrow();
let term = self.terminal.lock();
let screen = term.screen();
enum CompiledPattern {
@ -713,9 +716,7 @@ impl wezterm_term::DeviceControlHandler for LocalPaneDCSHandler {
if let Some(pane) = mux.get_pane(self.pane_id) {
let pane = pane.downcast_ref::<LocalPane>().unwrap();
pane.tmux_domain
.borrow_mut()
.replace(Arc::clone(&tmux_domain));
pane.tmux_domain.lock().replace(Arc::clone(&tmux_domain));
emit_output_for_pane(
self.pane_id,
@ -737,7 +738,7 @@ impl wezterm_term::DeviceControlHandler for LocalPaneDCSHandler {
let mux = Mux::get().expect("to be called on main thread");
if let Some(pane) = mux.get_pane(self.pane_id) {
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);
}
@ -808,7 +809,7 @@ fn split_child(
mut process: Box<dyn Child + Send>,
) -> (
Receiver<IoResult<ExitStatus>>,
Box<dyn ChildKiller>,
Box<dyn ChildKiller + Send + Sync>,
Option<u32>,
) {
let pid = process.process_id();
@ -834,8 +835,8 @@ impl LocalPane {
pane_id: PaneId,
mut terminal: Terminal,
process: Box<dyn Child + Send>,
pty: Box<dyn MasterPty>,
writer: Box<dyn Write>,
pty: Box<dyn MasterPty + Send>,
writer: Box<dyn Write + Send>,
domain_id: DomainId,
command_description: String,
) -> Self {
@ -849,25 +850,25 @@ impl LocalPane {
Self {
pane_id,
terminal: RefCell::new(terminal),
process: RefCell::new(ProcessState::Running {
terminal: Mutex::new(terminal),
process: Mutex::new(ProcessState::Running {
child_waiter: process,
pid,
signaller,
killed: false,
}),
pty: RefCell::new(pty),
writer: RefCell::new(writer),
pty: Mutex::new(pty),
writer: Mutex::new(writer),
domain_id,
tmux_domain: RefCell::new(None),
proc_list: RefCell::new(None),
tmux_domain: Mutex::new(None),
proc_list: Mutex::new(None),
command_description,
}
}
fn divine_current_working_dir(&self) -> Option<Url> {
#[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) {
return Url::parse(&format!("file://localhost{}", path.display())).ok();
}
@ -885,9 +886,9 @@ impl LocalPane {
None
}
fn divine_process_list(&self, force_refresh: bool) -> Option<RefMut<CachedProcInfo>> {
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.borrow() {
let mut proc_list = self.proc_list.borrow_mut();
fn divine_process_list(&self, force_refresh: bool) -> Option<MappedMutexGuard<CachedProcInfo>> {
if let ProcessState::Running { pid: Some(pid), .. } = &*self.process.lock() {
let mut proc_list = self.proc_list.lock();
let expired = force_refresh
|| proc_list
@ -934,7 +935,7 @@ impl LocalPane {
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
}
@ -953,7 +954,7 @@ impl Drop for LocalPane {
fn drop(&mut self) {
// Avoid lingering zombies if we can, but don't block forever.
// <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();
}
}

View File

@ -4,12 +4,12 @@ use crate::Mux;
use async_trait::async_trait;
use config::keyassignment::{KeyAssignment, ScrollbackEraseMode};
use downcast_rs::{impl_downcast, Downcast};
use parking_lot::{MappedMutexGuard, Mutex};
use rangeset::RangeSet;
use serde::{Deserialize, Serialize};
use std::cell::RefMut;
use std::collections::HashMap;
use std::ops::Range;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use termwiz::hyperlink::Rule;
use termwiz::input::KeyboardEncoding;
use termwiz::surface::{Line, SequenceNo};
@ -107,7 +107,7 @@ struct 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 pane = mux.get_pane(locked.pane_id).unwrap();
@ -186,7 +186,7 @@ impl LogicalLine {
/// A Pane represents a view on a terminal
#[async_trait(?Send)]
pub trait Pane: Downcast {
pub trait Pane: Downcast + Send + Sync {
fn pane_id(&self) -> PaneId;
/// 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 send_paste(&self, text: &str) -> anyhow::Result<()>;
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<()>;
/// Called as a hint that the pane is being resized as part of
/// 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 {
use super::*;
use k9::snapshot;
use parking_lot::{MappedMutexGuard, Mutex};
use std::borrow::Cow;
use std::cell::RefCell;
use termwiz::surface::SEQ_ZERO;
struct FakePane {
lines: RefCell<Vec<Line>>,
lines: Mutex<Vec<Line>>,
}
impl Pane for FakePane {
@ -596,7 +596,7 @@ mod test {
with_lines: &mut dyn WithPaneLines,
) {
let mut line_refs = vec![];
let mut lines = self.lines.borrow_mut();
let mut lines = self.lines.lock();
for line in lines
.iter_mut()
.skip(stable_range.start as usize)
@ -624,7 +624,7 @@ mod test {
(
first,
self.lines
.borrow()
.lock()
.iter()
.skip(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>>> {
Ok(None)
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
unimplemented!()
}
fn resize(&self, _: TerminalSize) -> anyhow::Result<()> {
@ -739,7 +739,7 @@ mod test {
);
let pane = FakePane {
lines: RefCell::new(physical_lines),
lines: Mutex::new(physical_lines),
};
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::collections::{HashMap, VecDeque};
use std::io::{BufWriter, Read, Write};
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
@ -560,12 +559,12 @@ impl Domain for RemoteSshDomain {
size: TerminalSize,
command: Option<CommandBuilder>,
command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
let pane_id = alloc_pane_id();
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 writer: BoxedWriter;
@ -677,7 +676,7 @@ impl Domain for RemoteSshDomain {
Box::new(writer.clone()),
);
let pane: Rc<dyn Pane> = Rc::new(LocalPane::new(
let pane: Arc<dyn Pane> = Arc::new(LocalPane::new(
pane_id,
terminal,
child,

View File

@ -10,12 +10,12 @@ use serde::{Deserialize, Serialize};
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::convert::TryInto;
use std::rc::Rc;
use std::sync::Arc;
use url::Url;
use wezterm_term::{StableRowIndex, TerminalSize};
pub type Tree = bintree::Tree<Rc<dyn Pane>, SplitDirectionAndSize>;
pub type Cursor = bintree::Cursor<Rc<dyn Pane>, SplitDirectionAndSize>;
pub type Tree = bintree::Tree<Arc<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);
pub type TabId = usize;
@ -43,7 +43,7 @@ pub struct Tab {
pane: RefCell<Option<Tree>>,
size: RefCell<TerminalSize>,
active: RefCell<usize>,
zoomed: RefCell<Option<Rc<dyn Pane>>>,
zoomed: RefCell<Option<Arc<dyn Pane>>>,
title: RefCell<String>,
recency: RefCell<Recency>,
}
@ -69,7 +69,7 @@ pub struct PositionedPane {
pub height: usize,
pub pixel_height: usize,
/// The pane instance
pub pane: Rc<dyn Pane>,
pub pane: Arc<dyn Pane>,
}
impl std::fmt::Debug for PositionedPane {
@ -199,7 +199,7 @@ pub struct PositionedSplit {
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 {
other.pane_id() == pane.pane_id()
} else {
@ -211,8 +211,8 @@ fn pane_tree(
tree: &Tree,
tab_id: TabId,
window_id: WindowId,
active: Option<&Rc<dyn Pane>>,
zoomed: Option<&Rc<dyn Pane>>,
active: Option<&Arc<dyn Pane>>,
zoomed: Option<&Arc<dyn Pane>>,
workspace: &str,
left_col: usize,
top_row: usize,
@ -278,12 +278,12 @@ fn pane_tree(
fn build_from_pane_tree<F>(
tree: bintree::Tree<PaneEntry, SplitDirectionAndSize>,
active: &mut Option<Rc<dyn Pane>>,
zoomed: &mut Option<Rc<dyn Pane>>,
active: &mut Option<Arc<dyn Pane>>,
zoomed: &mut Option<Arc<dyn Pane>>,
make_pane: &mut F,
) -> Tree
where
F: FnMut(PaneEntry) -> Rc<dyn Pane>,
F: FnMut(PaneEntry) -> Arc<dyn Pane>,
{
match tree {
bintree::Tree::Empty => Tree::Empty,
@ -297,10 +297,10 @@ where
let is_active_pane = entry.is_active_pane;
let pane = make_pane(entry);
if is_zoomed_pane {
zoomed.replace(Rc::clone(&pane));
zoomed.replace(Arc::clone(&pane));
}
if is_active_pane {
active.replace(Rc::clone(&pane));
active.replace(Arc::clone(&pane));
}
Tree::Leaf(pane)
}
@ -533,7 +533,7 @@ impl Tab {
/// 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)
where
F: FnMut(PaneEntry) -> Rc<dyn Pane>,
F: FnMut(PaneEntry) -> Arc<dyn Pane>,
{
let mut active = None;
let mut zoomed = None;
@ -781,7 +781,7 @@ impl Tab {
pixel_width: size.pixel_width.into(),
height: size.rows.into(),
pixel_height: size.pixel_height.into(),
pane: Rc::clone(zoomed),
pane: Arc::clone(zoomed),
});
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());
panes.push(PositionedPane {
@ -1366,7 +1366,7 @@ impl Tab {
/// Remove pane from tab.
/// The pane is still live in the mux; the intent is for the pane to
/// 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);
for pane in panes {
return Some(pane);
@ -1374,9 +1374,9 @@ impl Tab {
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
F: Fn(usize, &Rc<dyn Pane>) -> bool,
F: Fn(usize, &Arc<dyn Pane>) -> bool,
{
let mut dead_panes = vec![];
let zoomed_pane = self.zoomed.borrow().as_ref().map(|p| p.pane_id());
@ -1403,7 +1403,7 @@ impl Tab {
};
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) {
removed_indices.push(pane_index);
if Some(pane.pane_id()) == zoomed_pane {
@ -1506,15 +1506,15 @@ impl Tab {
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() {
return Some(Rc::clone(zoomed));
return Some(Arc::clone(zoomed));
}
self.iter_panes_ignoring_zoom()
.iter()
.nth(*self.active.borrow())
.map(|p| Rc::clone(&p.pane))
.map(|p| Arc::clone(&p.pane))
}
#[allow(unused)]
@ -1522,7 +1522,7 @@ impl Tab {
*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
.iter_panes_ignoring_zoom()
.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();
match (prior, current) {
(Some(prior), Some(current)) if prior.pane_id() != current.pane_id() => {
@ -1564,8 +1564,8 @@ impl Tab {
/// Assigns the root pane.
/// This is suitable when creating a new tab and then assigning
/// the initial pane
pub fn assign_pane(&self, pane: &Rc<dyn Pane>) {
match Tree::new().cursor().assign_top(Rc::clone(pane)) {
pub fn assign_pane(&self, pane: &Arc<dyn Pane>) {
match Tree::new().cursor().assign_top(Arc::clone(pane)) {
Ok(c) => *self.pane.borrow_mut() = Some(c.tree()),
Err(_) => panic!("tried to assign root pane to non-empty tree"),
}
@ -1731,7 +1731,7 @@ impl Tab {
&self,
pane_index: usize,
request: SplitRequest,
pane: Rc<dyn Pane>,
pane: Arc<dyn Pane>,
) -> anyhow::Result<usize> {
if self.zoomed.borrow().is_some() {
anyhow::bail!("cannot split while zoomed");
@ -1786,9 +1786,9 @@ impl Tab {
if request.top_level && !cursor.is_leaf() {
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 {
cursor.split_node_and_insert_left(Rc::clone(&pane))
cursor.split_node_and_insert_left(Arc::clone(&pane))
};
cursor = match result {
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 {
(existing_pane, pane)
@ -1965,6 +1965,7 @@ impl Into<String> for SerdeUrl {
mod test {
use super::*;
use crate::renderable::*;
use parking_lot::{MappedMutexGuard, Mutex};
use rangeset::RangeSet;
use std::ops::Range;
use termwiz::surface::SequenceNo;
@ -1974,14 +1975,14 @@ mod test {
struct FakePane {
id: PaneId,
size: RefCell<TerminalSize>,
size: Mutex<TerminalSize>,
}
impl FakePane {
fn new(id: PaneId, size: TerminalSize) -> Rc<dyn Pane> {
Rc::new(Self {
fn new(id: PaneId, size: TerminalSize) -> Arc<dyn Pane> {
Arc::new(Self {
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>>> {
Ok(None)
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
unimplemented!()
}
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
*self.size.borrow_mut() = size;
*self.size.lock() = size;
Ok(())
}

View File

@ -16,9 +16,9 @@ use async_trait::async_trait;
use config::keyassignment::ScrollbackEraseMode;
use crossbeam::channel::{unbounded as channel, Receiver, Sender};
use filedescriptor::{FileDescriptor, Pipe};
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
use portable_pty::*;
use rangeset::RangeSet;
use std::cell::{RefCell, RefMut};
use std::io::{BufWriter, Write};
use std::ops::Range;
use std::rc::Rc;
@ -53,7 +53,7 @@ impl Domain for TermWizTerminalDomain {
_size: TerminalSize,
_command: Option<CommandBuilder>,
_command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
bail!("cannot spawn panes in a TermWizTerminalPane");
}
@ -84,10 +84,10 @@ impl Domain for TermWizTerminalDomain {
pub struct TermWizTerminalPane {
pane_id: PaneId,
domain_id: DomainId,
terminal: RefCell<wezterm_term::Terminal>,
terminal: Mutex<wezterm_term::Terminal>,
input_tx: Sender<InputEvent>,
dead: RefCell<bool>,
writer: RefCell<Vec<u8>>,
dead: Mutex<bool>,
writer: Mutex<Vec<u8>>,
render_rx: FileDescriptor,
}
@ -101,7 +101,7 @@ impl TermWizTerminalPane {
) -> Self {
let pane_id = alloc_pane_id();
let terminal = RefCell::new(wezterm_term::Terminal::new(
let terminal = Mutex::new(wezterm_term::Terminal::new(
size,
term_config.unwrap_or_else(|| Arc::new(config::TermConfig::new())),
"WezTerm",
@ -113,10 +113,10 @@ impl TermWizTerminalPane {
pane_id,
domain_id,
terminal,
writer: RefCell::new(Vec::new()),
writer: Mutex::new(Vec::new()),
render_rx,
input_tx,
dead: RefCell::new(false),
dead: Mutex::new(false),
}
}
}
@ -127,11 +127,11 @@ impl Pane for TermWizTerminalPane {
}
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 {
self.terminal.borrow().current_seqno()
self.terminal.lock().current_seqno()
}
fn get_changed_since(
@ -139,7 +139,7 @@ impl Pane for TermWizTerminalPane {
lines: Range<StableRowIndex>,
seqno: SequenceNo,
) -> 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(
@ -148,7 +148,7 @@ impl Pane for TermWizTerminalPane {
for_line: &mut dyn ForEachPaneLogicalLine,
) {
terminal_for_each_logical_line_in_stable_range_mut(
&mut self.terminal.borrow_mut(),
&mut self.terminal.lock(),
lines,
for_line,
);
@ -159,19 +159,19 @@ impl Pane for TermWizTerminalPane {
}
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>) {
terminal_get_lines(&mut self.terminal.borrow_mut(), lines)
terminal_get_lines(&mut self.terminal.lock(), lines)
}
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 {
self.terminal.borrow_mut().get_title().to_string()
self.terminal.lock().get_title().to_string()
}
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()?)))
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
self.writer.borrow_mut()
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
MutexGuard::map(self.writer.lock(), |writer| {
let w: &mut dyn std::io::Write = writer;
w
})
}
fn resize(&self, size: TerminalSize) -> anyhow::Result<()> {
@ -198,7 +201,7 @@ impl Pane for TermWizTerminalPane {
cols: size.cols as usize,
})?;
self.terminal.borrow_mut().resize(size);
self.terminal.lock().resize(size);
Ok(())
}
@ -206,7 +209,7 @@ impl Pane for TermWizTerminalPane {
fn key_down(&self, key: KeyCode, modifiers: KeyModifiers) -> anyhow::Result<()> {
let event = InputEvent::Key(KeyEvent { key, modifiers });
if let Err(e) = self.input_tx.send(event) {
*self.dead.borrow_mut() = true;
*self.dead.lock() = true;
return Err(e.into());
}
Ok(())
@ -236,34 +239,34 @@ impl Pane for TermWizTerminalPane {
modifiers: event.modifiers,
});
if let Err(e) = self.input_tx.send(event) {
*self.dead.borrow_mut() = true;
*self.dead.lock() = true;
return Err(e.into());
}
Ok(())
}
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>> {
Some(self.terminal.borrow().get_config())
Some(self.terminal.lock().get_config())
}
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) {
*self.dead.borrow_mut() = true;
*self.dead.lock() = true;
}
fn is_dead(&self) -> bool {
*self.dead.borrow()
*self.dead.lock()
}
fn palette(&self) -> ColorPalette {
self.terminal.borrow().palette()
self.terminal.lock().palette()
}
fn domain_id(&self) -> DomainId {
@ -271,24 +274,24 @@ impl Pane for TermWizTerminalPane {
}
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 {
self.terminal.borrow().is_alt_screen_active()
self.terminal.lock().is_alt_screen_active()
}
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) {
match erase_mode {
ScrollbackEraseMode::ScrollbackOnly => {
self.terminal.borrow_mut().erase_scrollback();
self.terminal.lock().erase_scrollback();
}
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(
size: TerminalSize,
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 (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));
// 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();
mux.add_pane(&pane).expect("to be able to add pane to mux");
@ -530,7 +533,7 @@ pub async fn run<
let pane =
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));
tab.assign_pane(&pane);

View File

@ -5,12 +5,11 @@ use crate::tmux_commands::{ListAllPanes, TmuxCommand};
use crate::{Mux, MuxWindowBuilder};
use async_trait::async_trait;
use filedescriptor::FileDescriptor;
use parking_lot::{Condvar, Mutex};
use portable_pty::CommandBuilder;
use std::cell::RefCell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::io::Write;
use std::rc::Rc;
use std::sync::{Arc, Condvar, Mutex};
use std::sync::Arc;
use termwiz::tmux_cc::*;
use wezterm_term::TerminalSize;
@ -55,12 +54,12 @@ pub(crate) type TmuxCmdQueue = VecDeque<Box<dyn TmuxCommand>>;
pub(crate) struct TmuxDomainState {
pub pane_id: PaneId, // ID of the original pane
pub domain_id: DomainId, // ID of TmuxDomain
state: RefCell<State>,
state: Mutex<State>,
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
pub gui_window: RefCell<Option<MuxWindowBuilder>>,
pub gui_tabs: RefCell<Vec<TmuxTab>>,
pub remote_panes: RefCell<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
pub tmux_session: RefCell<Option<TmuxSessionId>>,
pub gui_window: Mutex<Option<MuxWindowBuilder>>,
pub gui_tabs: Mutex<Vec<TmuxTab>>,
pub remote_panes: Mutex<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
pub tmux_session: Mutex<Option<TmuxSessionId>>,
}
pub struct TmuxDomain {
@ -70,18 +69,18 @@ pub struct TmuxDomain {
impl TmuxDomainState {
pub fn advance(&self, events: Box<Vec<Event>>) {
for event in events.iter() {
let state = *self.state.borrow();
let state = *self.state.lock();
log::info!("tmux: {:?} in state {:?}", event, state);
match event {
Event::Guarded(response) => match state {
State::WaitForInitialGuard => {
*self.state.borrow_mut() = State::Idle;
*self.state.lock() = State::Idle;
}
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 domain_id = self.domain_id;
*self.state.borrow_mut() = State::Idle;
*self.state.lock() = State::Idle;
let resp = response.clone();
promise::spawn::spawn(async move {
if let Err(err) = cmd.process_result(domain_id, &resp) {
@ -93,9 +92,9 @@ impl TmuxDomainState {
State::Idle => {}
},
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) {
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()) {
log::error!("Failed to write tmux data to output: {:#}", err);
}
@ -107,15 +106,15 @@ impl TmuxDomainState {
self.create_gui_window();
}
Event::SessionChanged { session, name: _ } => {
*self.tmux_session.borrow_mut() = Some(*session);
*self.tmux_session.lock() = Some(*session);
log::info!("tmux session changed:{}", session);
}
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() {
let remote_pane = v.lock().unwrap();
let remote_pane = v.lock();
let (lock, condvar) = &*remote_pane.active_lock;
let mut released = lock.lock().unwrap();
let mut released = lock.lock();
*released = true;
condvar.notify_all();
}
@ -125,8 +124,8 @@ impl TmuxDomainState {
}
// send pending commands to tmux
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
if *self.state.borrow() == State::Idle && !cmd_queue.is_empty() {
let cmd_queue = self.cmd_queue.as_ref().lock();
if *self.state.lock() == State::Idle && !cmd_queue.is_empty() {
TmuxDomainState::schedule_send_next_command(self.domain_id);
}
}
@ -134,10 +133,10 @@ impl TmuxDomainState {
/// send next command at the front of cmd_queue.
/// must be called inside main thread
fn send_next_command(&self) {
if *self.state.borrow() != State::Idle {
if *self.state.lock() != State::Idle {
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() {
let cmd = first.get_command();
log::info!("sending cmd {:?}", cmd);
@ -146,7 +145,7 @@ impl TmuxDomainState {
let mut writer = pane.writer();
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
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 window_builder = mux.new_empty_window(None /* TODO: pass session here */);
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
}
};
@ -180,19 +179,18 @@ impl TmuxDomainState {
impl TmuxDomain {
pub fn new(pane_id: PaneId) -> Self {
let domain_id = alloc_domain_id();
// let parser = RefCell::new(Parser::new());
let mut cmd_queue = VecDeque::<Box<dyn TmuxCommand>>::new();
cmd_queue.push_back(Box::new(ListAllPanes));
let inner = Arc::new(TmuxDomainState {
domain_id,
pane_id,
// parser,
state: RefCell::new(State::WaitForInitialGuard),
state: Mutex::new(State::WaitForInitialGuard),
cmd_queue: Arc::new(Mutex::new(cmd_queue)),
gui_window: RefCell::new(None),
gui_tabs: RefCell::new(Vec::default()),
remote_panes: RefCell::new(HashMap::default()),
tmux_session: RefCell::new(None),
gui_window: Mutex::new(None),
gui_tabs: Mutex::new(Vec::default()),
remote_panes: Mutex::new(HashMap::default()),
tmux_session: Mutex::new(None),
});
Self { inner }
@ -210,7 +208,7 @@ impl Domain for TmuxDomain {
_size: TerminalSize,
_command: Option<CommandBuilder>,
_command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
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::{Mux, Pane};
use anyhow::{anyhow, Context};
use parking_lot::{Condvar, Mutex};
use portable_pty::{MasterPty, PtySize};
use std::collections::HashSet;
use std::fmt::{Debug, Write};
use std::io::Write as _;
use std::rc::Rc;
use std::sync::{Arc, Condvar, Mutex};
use std::sync::Arc;
use termwiz::tmux_cc::*;
use wezterm_term::TerminalSize;
@ -37,7 +38,7 @@ pub(crate) struct PaneItem {
impl TmuxDomainState {
/// check if a PaneItem received from ListAllPanes has been attached
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
.iter()
.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
/// TmuxPane-TmuxPane tree, so we can ref it later.
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
.iter_mut()
.find(|x| x.tmux_window_id == target.window_id)
@ -92,7 +93,7 @@ impl TmuxDomainState {
// 2) create pane if not exist
// 3) fetch scroll buffer if new created
// 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() {
if pane.session_id != current_session || self.check_pane_attached(&pane) {
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());
}
@ -150,7 +151,7 @@ impl TmuxDomainState {
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,
terminal,
Box::new(child),
@ -164,7 +165,7 @@ impl TmuxDomainState {
tab.assign_pane(&local_pane);
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() {
Some(x) => x,
None => {
@ -178,7 +179,6 @@ impl TmuxDomainState {
self.cmd_queue
.lock()
.unwrap()
.push_back(Box::new(CapturePane(pane.pane_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'
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) {
let mut pane = pane.lock().expect("Grant lock of tmux cmd queue failed");
let mut pane = pane.lock();
pane.output_write
.write_all(unescaped.as_bytes())
.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::DomainId;
use filedescriptor::FileDescriptor;
use parking_lot::{Condvar, Mutex};
use portable_pty::{Child, ChildKiller, ExitStatus, MasterPty};
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
#[derive(Debug)]
@ -24,11 +25,11 @@ struct TmuxPtyWriter {
impl Write for TmuxPtyWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let pane_id = {
let pane_lock = self.master_pane.lock().unwrap();
let pane_lock = self.master_pane.lock();
pane_lock.pane_id
};
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 {
pane: pane_id,
keys: buf.to_vec(),
@ -45,11 +46,11 @@ impl Write for TmuxPtyWriter {
impl Write for TmuxPty {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let pane_id = {
let pane_lock = self.master_pane.lock().unwrap();
let pane_lock = self.master_pane.lock();
pane_lock.pane_id
};
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 {
pane: pane_id,
keys: buf.to_vec(),
@ -74,10 +75,10 @@ impl Child for TmuxChild {
}
fn wait(&mut self) -> std::io::Result<portable_pty::ExitStatus> {
let (lock, var) = &*self.active_lock;
let mut released = lock.lock().unwrap();
let &(ref lock, ref var) = &*self.active_lock;
let mut released = lock.lock();
while !*released {
released = var.wait(released).unwrap();
var.wait(&mut released);
}
return Ok(ExitStatus::with_exit_code(0));
}
@ -123,14 +124,14 @@ impl ChildKiller for TmuxChild {
impl MasterPty for TmuxPty {
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 }));
TmuxDomainState::schedule_send_next_command(self.domain_id);
Ok(())
}
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 {
rows: pane.pane_height 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
/// increments the generation counter appropriately, the changes will be detected
/// 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
/// configuration. If the implementation may be
/// changed at runtime, it must increment the generation

View File

@ -10,7 +10,7 @@ pub enum ClipboardSelection {
PrimarySelection,
}
pub trait Clipboard {
pub trait Clipboard: Send + Sync {
fn set_contents(
&self,
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);
}
@ -61,11 +61,11 @@ pub enum Alert {
OutputSinceFocusLost,
}
pub trait AlertHandler {
pub trait AlertHandler: Send + Sync {
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>);
}
@ -132,7 +132,7 @@ impl Terminal {
/// are answerback responses to a number of escape sequences.
pub fn new(
size: TerminalSize,
config: Arc<dyn TerminalConfiguration>,
config: Arc<dyn TerminalConfiguration + Send + Sync>,
term_program: &str,
term_version: &str,
// writing to the writer sends data to input of the pty

View File

@ -1,5 +1,6 @@
use crate::input::*;
use crate::TerminalState;
use std::io::Write;
use termwiz::input::{KeyCodeEncodeModes, KeyboardEncoding};
impl TerminalState {

View File

@ -6,6 +6,7 @@ use ::image::{
};
use anyhow::Context;
use std::collections::{HashMap, HashSet};
use std::io::Write;
use std::sync::Arc;
use std::time::Duration;
use termwiz::escape::apc::{

View File

@ -7,6 +7,7 @@ use crate::config::{BidiMode, NewlineCanon};
use log::debug;
use num_traits::ToPrimitive;
use std::collections::HashMap;
use std::io::{BufWriter, Write};
use std::sync::mpsc::{channel, Sender};
use std::sync::Arc;
use terminfo::{Database, Value};
@ -350,7 +351,7 @@ pub struct TerminalState {
term_program: String,
term_version: String,
writer: Box<dyn std::io::Write>,
writer: BufWriter<ThreadedWriter>,
image_cache: lru::LruCache<[u8; 32], Arc<ImageData>>,
sixel_scrolls_right: bool,
@ -498,7 +499,7 @@ impl TerminalState {
term_version: &str,
writer: Box<dyn std::io::Write + Send>,
) -> TerminalState {
let writer = Box::new(ThreadedWriter::new(writer));
let writer = BufWriter::new(ThreadedWriter::new(writer));
let seqno = 1;
let screen = ScreenOrAlt::new(size, &config, seqno, config.bidi_mode());
@ -559,7 +560,7 @@ impl TerminalState {
current_dir: None,
term_program: term_program.to_string(),
term_version: term_version.to_string(),
writer: Box::new(std::io::BufWriter::new(writer)),
writer,
image_cache: lru::LruCache::new(16),
user_vars: HashMap::new(),
kitty_img: Default::default(),

View File

@ -2,6 +2,7 @@ use crate::input::*;
use crate::terminalstate::MouseEncoding;
use crate::TerminalState;
use anyhow::bail;
use std::io::Write;
impl TerminalState {
/// 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 ordered_float::NotNan;
use std::fmt::Write;
use std::io::Write as _;
use std::ops::{Deref, DerefMut};
use termwiz::cell::{grapheme_column_width, Cell, CellAttributes, SemanticType};
use termwiz::escape::csi::{

View File

@ -9,21 +9,20 @@ mod csi;
// mod selection; FIXME: port to render layer
use crate::color::ColorPalette;
use k9::assert_equal as assert_eq;
use std::cell::RefCell;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use termwiz::escape::csi::{Edit, EraseInDisplay, EraseInLine};
use termwiz::escape::{OneBased, OperatingSystemCommand, CSI};
use termwiz::surface::{CursorShape, CursorVisibility, SequenceNo, SEQ_ZERO};
#[derive(Debug)]
struct LocalClip {
clip: RefCell<Option<String>>,
clip: Mutex<Option<String>>,
}
impl LocalClip {
fn new() -> Self {
Self {
clip: RefCell::new(None),
clip: Mutex::new(None),
}
}
}
@ -34,7 +33,7 @@ impl Clipboard for LocalClip {
_selection: ClipboardSelection,
clip: Option<String>,
) -> anyhow::Result<()> {
*self.clip.borrow_mut() = clip;
*self.clip.lock().unwrap() = clip;
Ok(())
}
}

View File

@ -27,6 +27,7 @@ mux = { path = "../mux" }
# https://github.com/sfackler/rust-openssl/pull/1578
# https://github.com/wez/libssh-rs/blob/main/libssh-rs-sys/Cargo.toml
openssl = "=0.10.38"
parking_lot = "0.12"
portable-pty = { path = "../pty", features = ["serde_support"]}
promise = { path = "../promise" }
rangeset = { path = "../rangeset" }

View File

@ -460,7 +460,7 @@ impl ClientDomain {
// removed it from the mux. Let's add it back, but
// with a new 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,
entry.tab_id,
entry.pane_id,
@ -472,7 +472,7 @@ impl ClientDomain {
}
}
} else {
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
&inner,
entry.tab_id,
entry.pane_id,
@ -592,7 +592,7 @@ impl Domain for ClientDomain {
_size: TerminalSize,
_command: Option<CommandBuilder>,
_command_dir: Option<String>,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
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);
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
&inner,
result.tab_id,
result.pane_id,
@ -648,7 +648,7 @@ impl Domain for ClientDomain {
tab_id: TabId,
pane_id: PaneId,
split_request: SplitRequest,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
let inner = self
.inner()
.ok_or_else(|| anyhow!("domain is not attached"))?;
@ -685,7 +685,7 @@ impl Domain for ClientDomain {
})
.await?;
let pane: Rc<dyn Pane> = Rc::new(ClientPane::new(
let pane: Arc<dyn Pane> = Arc::new(ClientPane::new(
&inner,
result.tab_id,
result.pane_id,
@ -702,7 +702,7 @@ impl Domain for ClientDomain {
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();
mux.add_pane(&pane)?;

View File

@ -13,12 +13,12 @@ use mux::pane::{
use mux::renderable::{RenderableDimensions, StableCursorPosition};
use mux::tab::TabId;
use mux::{Mux, MuxNotification};
use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
use rangeset::RangeSet;
use ratelim::RateLimiter;
use std::cell::{RefCell, RefMut};
use std::cell::RefCell;
use std::collections::{BTreeMap, HashMap};
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use termwiz::input::KeyEvent;
use termwiz::surface::SequenceNo;
@ -34,14 +34,14 @@ pub struct ClientPane {
local_pane_id: PaneId,
pub remote_pane_id: PaneId,
pub remote_tab_id: TabId,
pub renderable: RefCell<RenderableState>,
palette: RefCell<ColorPalette>,
writer: RefCell<PaneWriter>,
mouse: Rc<RefCell<MouseState>>,
clipboard: RefCell<Option<Arc<dyn Clipboard>>>,
mouse_grabbed: RefCell<bool>,
ignore_next_kill: RefCell<bool>,
user_vars: RefCell<HashMap<String, String>>,
pub renderable: Mutex<RenderableState>,
palette: Mutex<ColorPalette>,
writer: Mutex<PaneWriter>,
mouse: Arc<Mutex<MouseState>>,
clipboard: Mutex<Option<Arc<dyn Clipboard>>>,
mouse_grabbed: Mutex<bool>,
ignore_next_kill: Mutex<bool>,
user_vars: Mutex<HashMap<String, String>>,
}
impl ClientPane {
@ -58,7 +58,7 @@ impl ClientPane {
remote_pane_id,
};
let mouse = Rc::new(RefCell::new(MouseState::new(
let mouse = Arc::new(Mutex::new(MouseState::new(
remote_pane_id,
client.client.clone(),
)));
@ -96,27 +96,27 @@ impl ClientPane {
remote_pane_id,
local_pane_id,
remote_tab_id,
renderable: RefCell::new(render),
writer: RefCell::new(writer),
palette: RefCell::new(palette),
clipboard: RefCell::new(None),
mouse_grabbed: RefCell::new(false),
ignore_next_kill: RefCell::new(false),
user_vars: RefCell::new(HashMap::new()),
renderable: Mutex::new(render),
writer: Mutex::new(writer),
palette: Mutex::new(palette),
clipboard: Mutex::new(None),
mouse_grabbed: Mutex::new(false),
ignore_next_kill: Mutex::new(false),
user_vars: Mutex::new(HashMap::new()),
}
}
pub async fn process_unilateral(&self, pdu: Pdu) -> anyhow::Result<()> {
match pdu {
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 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;
self.renderable
.borrow()
.lock()
.inner
.borrow_mut()
.apply_changes_to_surface(delta, bonus_lines);
@ -125,7 +125,7 @@ impl ClientPane {
clipboard,
selection,
..
}) => match self.clipboard.borrow().as_ref() {
}) => match self.clipboard.lock().as_ref() {
Some(clip) => {
log::debug!(
"Pdu::SetClipboard pane={} remote={} {:?} {:?}",
@ -141,7 +141,7 @@ impl ClientPane {
}
},
Pdu::SetPalette(SetPalette { palette, .. }) => {
*self.palette.borrow_mut() = palette;
*self.palette.lock() = palette;
let mux = Mux::get().unwrap();
mux.notify(MuxNotification::Alert {
pane_id: self.local_pane_id,
@ -152,9 +152,7 @@ impl ClientPane {
let mux = Mux::get().unwrap();
match &alert {
Alert::SetUserVar { name, value } => {
self.user_vars
.borrow_mut()
.insert(name.clone(), value.clone());
self.user_vars.lock().insert(name.clone(), value.clone());
}
_ => {}
}
@ -165,7 +163,7 @@ impl ClientPane {
}
Pdu::PaneRemoved(PaneRemoved { 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();
mux.prune_dead_windows();
@ -188,7 +186,7 @@ impl ClientPane {
/// from where they left off.
/// It isn't perfect.
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 {
let renderable = self.renderable.borrow();
let renderable = self.renderable.lock();
let inner = renderable.inner.borrow();
let mut map: BTreeMap<Value, Value> = BTreeMap::new();
@ -216,11 +214,11 @@ impl Pane for ClientPane {
}
fn get_cursor_position(&self) -> StableCursorPosition {
self.renderable.borrow().get_cursor_position()
self.renderable.lock().get_cursor_position()
}
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) {
@ -236,7 +234,7 @@ impl Pane for ClientPane {
}
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> {
@ -244,7 +242,7 @@ impl Pane for ClientPane {
}
fn get_current_seqno(&self) -> SequenceNo {
self.renderable.borrow().get_current_seqno()
self.renderable.lock().get_current_seqno()
}
fn get_changed_since(
@ -252,15 +250,15 @@ impl Pane for ClientPane {
lines: Range<StableRowIndex>,
seqno: SequenceNo,
) -> 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>) {
self.clipboard.borrow_mut().replace(Arc::clone(clipboard));
self.clipboard.lock().replace(Arc::clone(clipboard));
}
fn get_title(&self) -> String {
let renderable = self.renderable.borrow();
let renderable = self.renderable.lock();
let inner = renderable.inner.borrow();
inner.title.clone()
}
@ -269,7 +267,7 @@ impl Pane for ClientPane {
let client = Arc::clone(&self.client);
let remote_pane_id = self.remote_pane_id;
self.renderable
.borrow()
.lock()
.inner
.borrow_mut()
.predict_from_paste(text);
@ -285,11 +283,7 @@ impl Pane for ClientPane {
.await
})
.detach();
self.renderable
.borrow()
.inner
.borrow_mut()
.update_last_send();
self.renderable.lock().inner.borrow_mut().update_last_send();
Ok(())
}
@ -297,12 +291,15 @@ impl Pane for ClientPane {
Ok(None)
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
self.writer.borrow_mut()
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
MutexGuard::map(self.writer.lock(), |writer| {
let w: &mut dyn std::io::Write = writer;
w
})
}
fn set_zoomed(&self, zoomed: bool) {
let render = self.renderable.borrow();
let render = self.renderable.lock();
let mut inner = render.inner.borrow_mut();
let client = Arc::clone(&self.client);
let remote_pane_id = self.remote_pane_id;
@ -324,7 +321,7 @@ impl Pane for ClientPane {
}
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 cols = size.cols as usize;
@ -381,7 +378,7 @@ impl Pane for ClientPane {
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
let input_serial;
{
let renderable = self.renderable.borrow();
let renderable = self.renderable.lock();
let mut inner = renderable.inner.borrow_mut();
inner.input_serial = InputSerial::now();
input_serial = inner.input_serial;
@ -403,11 +400,7 @@ impl Pane for ClientPane {
.await
})
.detach();
self.renderable
.borrow()
.inner
.borrow_mut()
.update_last_send();
self.renderable.lock().inner.borrow_mut().update_last_send();
Ok(())
}
@ -417,7 +410,7 @@ impl Pane for ClientPane {
}
fn kill(&self) {
let mut ignore = self.ignore_next_kill.borrow_mut();
let mut ignore = self.ignore_next_kill.lock();
if *ignore {
*ignore = false;
return;
@ -482,27 +475,23 @@ impl Pane for ClientPane {
// status, but killing the pane prevents the server
// side from sending us further data.
// <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<()> {
self.mouse.borrow_mut().append(event);
if MouseState::next(Rc::clone(&self.mouse)) {
self.renderable
.borrow()
.inner
.borrow_mut()
.update_last_send();
self.mouse.lock().append(event);
if MouseState::next(Arc::clone(&self.mouse)) {
self.renderable.lock().inner.borrow_mut().update_last_send();
}
Ok(())
}
fn is_dead(&self) -> bool {
self.renderable.borrow().inner.borrow().dead
self.renderable.lock().inner.borrow().dead
}
fn palette(&self) -> ColorPalette {
self.palette.borrow().clone()
self.palette.lock().clone()
}
fn domain_id(&self) -> DomainId {
@ -510,7 +499,7 @@ impl Pane for ClientPane {
}
fn is_mouse_grabbed(&self) -> bool {
*self.mouse_grabbed.borrow()
*self.mouse_grabbed.lock()
}
fn is_alt_screen_active(&self) -> bool {
@ -519,7 +508,7 @@ impl Pane for ClientPane {
}
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) {
@ -555,7 +544,7 @@ impl Pane for ClientPane {
}
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 codec::*;
use mux::tab::TabId;
use std::cell::RefCell;
use parking_lot::Mutex;
use std::collections::VecDeque;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use wezterm_term::{MouseButton, MouseEvent, MouseEventKind};
pub struct MouseState {
@ -64,12 +64,12 @@ impl MouseState {
}
}
pub fn next(state: Rc<RefCell<Self>>) -> bool {
let mut mouse = state.borrow_mut();
pub fn next(state: Arc<Mutex<Self>>) -> bool {
let mut mouse = state.lock();
if let Some(event) = mouse.pop() {
let client = mouse.client.clone();
let state = Rc::clone(&state);
let state = Arc::clone(&state);
mouse.pending.store(true, Ordering::SeqCst);
let remote_pane_id = mouse.remote_pane_id;
@ -82,11 +82,11 @@ impl MouseState {
.await
.ok();
let mouse = state.borrow_mut();
let mouse = state.lock();
mouse.pending.store(false, Ordering::SeqCst);
drop(mouse);
Self::next(Rc::clone(&state));
Self::next(Arc::clone(&state));
Ok::<(), anyhow::Error>(())
})
.detach();

View File

@ -540,7 +540,7 @@ impl RenderableInner {
.get_pane(local_pane_id)
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
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();
match result {
@ -621,7 +621,7 @@ impl RenderableInner {
.get_pane(local_pane_id)
.ok_or_else(|| anyhow!("no such tab {}", local_pane_id))?;
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();
inner.dead = !alive;

View File

@ -67,6 +67,7 @@ mux = { path = "../mux" }
mux-lua = { path = "../lua-api-crates/mux" }
open = "3.0"
ordered-float = "3.0"
parking_lot = "0.12"
portable-pty = { path = "../pty", features = ["serde_support"]}
promise = { path = "../promise" }
pulldown-cmark = "0.9"

View File

@ -12,12 +12,11 @@ use mux::pane::{
use mux::renderable::*;
use mux::tab::TabId;
use ordered_float::NotNan;
use parking_lot::{MappedMutexGuard, Mutex};
use rangeset::RangeSet;
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::ops::Range;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::time::Duration;
use termwiz::cell::{Cell, CellAttributes};
use termwiz::color::AnsiColor;
@ -38,8 +37,8 @@ lazy_static::lazy_static! {
const SEARCH_CHUNK_SIZE: StableRowIndex = 1000;
pub struct CopyOverlay {
delegate: Rc<dyn Pane>,
render: RefCell<CopyRenderable>,
delegate: Arc<dyn Pane>,
render: Mutex<CopyRenderable>,
}
#[derive(Copy, Clone, Debug)]
@ -57,7 +56,7 @@ struct Jump {
struct CopyRenderable {
cursor: StableCursorPosition,
delegate: Rc<dyn Pane>,
delegate: Arc<dyn Pane>,
start: Option<SelectionCoordinate>,
selection_mode: SelectionMode,
viewport: Option<StableRowIndex>,
@ -109,9 +108,9 @@ pub struct CopyModeParams {
impl CopyOverlay {
pub fn with_pane(
term_window: &TermWindow,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
params: CopyModeParams,
) -> anyhow::Result<Rc<dyn Pane>> {
) -> anyhow::Result<Arc<dyn Pane>> {
let mut cursor = pane.get_cursor_position();
cursor.shape = termwiz::surface::CursorShape::SteadyBlock;
cursor.visibility = CursorVisibility::Visible;
@ -129,7 +128,7 @@ impl CopyOverlay {
let mut render = CopyRenderable {
cursor,
window,
delegate: Rc::clone(pane),
delegate: Arc::clone(pane),
start: None,
viewport: term_window.get_viewport(pane.pane_id()),
results: vec![],
@ -143,7 +142,6 @@ impl CopyOverlay {
pattern: if params.pattern.is_empty() {
SAVED_PATTERN
.lock()
.unwrap()
.get(&tab_id)
.map(|p| p.clone())
.unwrap_or(params.pattern)
@ -163,14 +161,14 @@ impl CopyOverlay {
render.dirty_results.add(search_row);
render.update_search();
Ok(Rc::new(CopyOverlay {
delegate: Rc::clone(pane),
render: RefCell::new(render),
Ok(Arc::new(CopyOverlay {
delegate: Arc::clone(pane),
render: Mutex::new(render),
}))
}
pub fn get_params(&self) -> CopyModeParams {
let render = self.render.borrow();
let render = self.render.lock();
CopyModeParams {
pattern: render.pattern.clone(),
editing_search: render.editing_search,
@ -178,7 +176,7 @@ impl CopyOverlay {
}
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;
if render.pattern != params.pattern {
render.pattern = params.pattern;
@ -189,7 +187,7 @@ impl CopyOverlay {
}
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 let Some(last) = render.last_bar_pos.take() {
render.dirty_results.add(last);
@ -271,7 +269,7 @@ impl CopyRenderable {
let state = term_window.pane_state(pane_id);
if let Some(overlay) = state.overlay.as_ref() {
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 {
r.update_search();
}
@ -297,7 +295,6 @@ impl CopyRenderable {
SAVED_PATTERN
.lock()
.unwrap()
.insert(self.tab_id, self.pattern.clone());
let bar_pos = self.compute_search_row();
@ -305,7 +302,7 @@ impl CopyRenderable {
self.last_result_seqno = self.delegate.get_current_seqno();
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 pattern = self.pattern.clone();
let dims = pane.get_dimensions();
@ -330,7 +327,7 @@ impl CopyRenderable {
let state = term_window.pane_state(pane_id);
if let Some(overlay) = state.overlay.as_ref() {
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);
}
}
@ -375,7 +372,7 @@ impl CopyRenderable {
}
// 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 end = range.start;
let range = end
@ -397,7 +394,7 @@ impl CopyRenderable {
let state = term_window.pane_state(pane_id);
if let Some(overlay) = state.overlay.as_ref() {
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);
}
}
@ -1025,7 +1022,7 @@ impl Pane for CopyOverlay {
fn send_paste(&self, text: &str) -> anyhow::Result<()> {
// paste into the search bar
let mut r = self.render.borrow_mut();
let mut r = self.render.lock();
r.pattern.push_str(text);
r.schedule_update_search();
Ok(())
@ -1035,7 +1032,7 @@ impl Pane for CopyOverlay {
Ok(None)
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
self.delegate.writer()
}
@ -1048,7 +1045,7 @@ impl Pane for CopyOverlay {
}
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() {
match (key, mods) {
(KeyCode::Char(c), KeyModifiers::NONE)
@ -1093,7 +1090,7 @@ impl Pane for CopyOverlay {
fn perform_assignment(&self, assignment: &KeyAssignment) -> PerformAssignmentResult {
use CopyModeAssignment::*;
let mut render = self.render.borrow_mut();
let mut render = self.render.lock();
if render.pending_jump.is_some() {
// Block key assignments until key_down is called
// and resolves the next state
@ -1190,7 +1187,7 @@ impl Pane for CopyOverlay {
}
fn get_cursor_position(&self) -> StableCursorPosition {
let renderer = self.render.borrow();
let renderer = self.render.lock();
if renderer.editing_search {
// place in the search box
StableCursorPosition {
@ -1232,8 +1229,8 @@ impl Pane for CopyOverlay {
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
// calling into its own with_lines_mut to avoid a runtime
// borrow erro!
let mut renderer = self.render.borrow_mut();
// lock erro!
let mut renderer = self.render.lock();
if self.delegate.get_current_seqno() > renderer.last_result_seqno {
renderer.update_search();
}
@ -1351,7 +1348,7 @@ impl Pane for CopyOverlay {
}
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 {
renderer.update_search();
}

View File

@ -26,7 +26,7 @@ pub fn start_overlay<T, F>(
tab: &Rc<Tab>,
func: F,
) -> (
Rc<dyn Pane>,
Arc<dyn Pane>,
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
)
where
@ -54,10 +54,10 @@ where
pub fn start_overlay_pane<T, F>(
term_window: &TermWindow,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
func: F,
) -> (
Rc<dyn Pane>,
Arc<dyn Pane>,
Pin<Box<dyn std::future::Future<Output = anyhow::Result<T>>>>,
)
where

View File

@ -7,11 +7,10 @@ use mux::pane::{
ForEachPaneLogicalLine, LogicalLine, Pane, PaneId, Pattern, SearchResult, WithPaneLines,
};
use mux::renderable::*;
use parking_lot::{MappedMutexGuard, Mutex};
use rangeset::RangeSet;
use std::cell::{RefCell, RefMut};
use std::collections::HashMap;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use termwiz::cell::{Cell, CellAttributes};
use termwiz::color::AnsiColor;
@ -148,8 +147,8 @@ mod alphabet_test {
}
pub struct QuickSelectOverlay {
renderer: RefCell<QuickSelectRenderable>,
delegate: Rc<dyn Pane>,
renderer: Mutex<QuickSelectRenderable>,
delegate: Arc<dyn Pane>,
}
#[derive(Debug)]
@ -159,7 +158,7 @@ struct MatchResult {
}
struct QuickSelectRenderable {
delegate: Rc<dyn Pane>,
delegate: Arc<dyn Pane>,
/// The text that the user entered
pattern: Pattern,
/// The most recently queried set of matches
@ -186,9 +185,9 @@ struct QuickSelectRenderable {
impl QuickSelectOverlay {
pub fn with_pane(
term_window: &TermWindow,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
args: &QuickSelectArguments,
) -> Rc<dyn Pane> {
) -> Arc<dyn Pane> {
let viewport = term_window.get_viewport(pane.pane_id());
let dims = pane.get_dimensions();
@ -228,7 +227,7 @@ impl QuickSelectOverlay {
let window = term_window.window.clone().unwrap();
let mut renderer = QuickSelectRenderable {
delegate: Rc::clone(pane),
delegate: Arc::clone(pane),
pattern,
selection: "".to_string(),
results: vec![],
@ -249,14 +248,14 @@ impl QuickSelectOverlay {
renderer.dirty_results.add(search_row);
renderer.update_search(true);
Rc::new(QuickSelectOverlay {
renderer: RefCell::new(renderer),
delegate: Rc::clone(pane),
Arc::new(QuickSelectOverlay {
renderer: Mutex::new(renderer),
delegate: Arc::clone(pane),
})
}
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 let Some(last) = render.last_bar_pos.take() {
render.dirty_results.add(last);
@ -287,7 +286,7 @@ impl Pane for QuickSelectOverlay {
Ok(None)
}
fn writer(&self) -> RefMut<dyn std::io::Write> {
fn writer(&self) -> MappedMutexGuard<dyn std::io::Write> {
self.delegate.writer()
}
@ -301,12 +300,12 @@ impl Pane for QuickSelectOverlay {
fn key_down(&self, key: KeyCode, mods: KeyModifiers) -> anyhow::Result<()> {
match (key, mods) {
(KeyCode::Escape, KeyModifiers::NONE) => self.renderer.borrow().close(),
(KeyCode::Escape, KeyModifiers::NONE) => self.renderer.lock().close(),
(KeyCode::UpArrow, KeyModifiers::NONE)
| (KeyCode::Enter, KeyModifiers::NONE)
| (KeyCode::Char('p'), KeyModifiers::CTRL) => {
// 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() {
let prior = if *cur > 0 {
cur - 1
@ -320,7 +319,7 @@ impl Pane for QuickSelectOverlay {
// Skip this page of matches and move up to the first match from
// the prior page.
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 {
let top = r.viewport.unwrap_or(dims.physical_top);
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
// the next page.
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 {
let top = r.viewport.unwrap_or(dims.physical_top);
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) => {
// 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() {
let next = if *cur + 1 >= r.results.len() {
0
@ -365,7 +364,7 @@ impl Pane for QuickSelectOverlay {
}
(KeyCode::Char(c), KeyModifiers::NONE) | (KeyCode::Char(c), KeyModifiers::SHIFT) => {
// Type to add to the selection
let mut r = self.renderer.borrow_mut();
let mut r = self.renderer.lock();
r.selection.push(c);
let lowered = r.selection.to_lowercase();
let paste = lowered != r.selection;
@ -376,12 +375,12 @@ impl Pane for QuickSelectOverlay {
}
(KeyCode::Backspace, KeyModifiers::NONE) => {
// Backspace to edit the selection
let mut r = self.renderer.borrow_mut();
let mut r = self.renderer.lock();
r.selection.pop();
}
(KeyCode::Char('u'), KeyModifiers::CTRL) => {
// CTRL-u to clear the selection
let mut r = self.renderer.borrow_mut();
let mut r = self.renderer.lock();
r.selection.clear();
}
_ => {}
@ -431,7 +430,7 @@ impl Pane for QuickSelectOverlay {
fn get_cursor_position(&self) -> StableCursorPosition {
// move to the search box
let renderer = self.renderer.borrow();
let renderer = self.renderer.lock();
StableCursorPosition {
x: 8 + wezterm_term::unicode_column_width(&renderer.selection, None),
y: renderer.compute_search_row(),
@ -450,7 +449,7 @@ impl Pane for QuickSelectOverlay {
seqno: SequenceNo,
) -> RangeSet<StableRowIndex> {
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)
}
@ -468,7 +467,7 @@ impl Pane for QuickSelectOverlay {
}
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
// calling into its own with_lines_mut to avoid a runtime
// borrow erro!
@ -579,7 +578,7 @@ impl Pane for QuickSelectOverlay {
}
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();
let dims = self.get_dimensions();
@ -791,7 +790,7 @@ impl QuickSelectRenderable {
self.dirty_results.add(bar_pos);
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 pattern = self.pattern.clone();
let scope = self.args.scope_lines;
@ -814,7 +813,7 @@ impl QuickSelectRenderable {
if let Some(search_overlay) =
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.recompute_results();
let num_results = r.results.len();

View File

@ -3,7 +3,7 @@ use crate::TermWindow;
use config::keyassignment::{ClipboardCopyDestination, ClipboardPasteSource};
use mux::pane::Pane;
use mux::Mux;
use std::rc::Rc;
use std::sync::Arc;
use window::{Clipboard, WindowOps};
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();
log::trace!(
"paste_from_clipboard in pane {} {:?}",

View File

@ -4,7 +4,7 @@ use anyhow::Context;
use config::keyassignment::{KeyAssignment, KeyTableEntry};
use mux::pane::{Pane, PerformAssignmentResult};
use smol::Timer;
use std::rc::Rc;
use std::sync::Arc;
use std::time::{Duration, Instant};
use termwiz::input::KeyboardEncoding;
@ -218,7 +218,7 @@ enum OnlyKeyBindings {
}
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
|| pane.get_keyboard_encoding() != KeyboardEncoding::Win32
{
@ -229,7 +229,7 @@ impl super::TermWindow {
fn lookup_key(
&mut self,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
keycode: &KeyCode,
mods: Modifiers,
only_key_bindings: OnlyKeyBindings,
@ -257,7 +257,7 @@ impl super::TermWindow {
fn process_key(
&mut self,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
context: &dyn WindowOps,
keycode: &KeyCode,
raw_modifiers: Modifiers,

View File

@ -176,7 +176,7 @@ pub struct SemanticZoneCache {
}
pub struct OverlayState {
pub pane: Rc<dyn Pane>,
pub pane: Arc<dyn Pane>,
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 viewport = self
.get_viewport(pane.pane_id())
@ -2095,7 +2095,7 @@ impl TermWindow {
}
/// 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
.semantic_zones
.entry(pane.pane_id())
@ -2222,7 +2222,7 @@ impl TermWindow {
pub fn perform_key_assignment(
&mut self,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
assignment: &KeyAssignment,
) -> anyhow::Result<PerformAssignmentResult> {
use KeyAssignment::*;
@ -2764,7 +2764,7 @@ impl TermWindow {
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!
// 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
@ -2967,22 +2967,22 @@ impl TermWindow {
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 {
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();
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;
}
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();
mux.get_active_tab_for_window(self.mux_window_id)
.and_then(|tab| tab.get_active_pane())
@ -2994,7 +2994,7 @@ impl TermWindow {
/// then that will be returned instead. Otherwise, if the pane has
/// an active overlay (such as search or copy mode) then that will
/// 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 tab = match mux.get_active_tab_for_window(self.mux_window_id) {
Some(tab) => tab,
@ -3116,7 +3116,7 @@ impl TermWindow {
let mut panes = tab.iter_panes();
for p in &mut panes {
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
@ -3177,7 +3177,7 @@ impl TermWindow {
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.pane_state(pane_id).overlay.replace(OverlayState {
pane,
@ -3186,7 +3186,7 @@ impl TermWindow {
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.tab_state(tab_id).overlay.replace(OverlayState {
pane: overlay,
@ -3195,7 +3195,7 @@ impl TermWindow {
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 {
Pattern::CaseSensitiveString(s) => MuxPattern::CaseSensitiveString(s),
Pattern::CaseInSensitiveString(s) => MuxPattern::CaseInSensitiveString(s),

View File

@ -12,7 +12,6 @@ use mux::tab::SplitDirection;
use mux::Mux;
use std::convert::TryInto;
use std::ops::Sub;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
use termwiz::hyperlink::Hyperlink;
@ -347,7 +346,7 @@ impl super::TermWindow {
fn mouse_event_ui_item(
&mut self,
item: UIItem,
pane: Rc<dyn Pane>,
pane: Arc<dyn Pane>,
_y: i64,
event: MouseEvent,
context: &dyn WindowOps,
@ -453,7 +452,7 @@ impl super::TermWindow {
pub fn mouse_event_above_scroll_thumb(
&mut self,
_item: UIItem,
pane: Rc<dyn Pane>,
pane: Arc<dyn Pane>,
event: MouseEvent,
context: &dyn WindowOps,
) {
@ -478,7 +477,7 @@ impl super::TermWindow {
pub fn mouse_event_below_scroll_thumb(
&mut self,
_item: UIItem,
pane: Rc<dyn Pane>,
pane: Arc<dyn Pane>,
event: MouseEvent,
context: &dyn WindowOps,
) {
@ -503,7 +502,7 @@ impl super::TermWindow {
pub fn mouse_event_scroll_thumb(
&mut self,
item: UIItem,
_pane: Rc<dyn Pane>,
_pane: Arc<dyn Pane>,
event: MouseEvent,
context: &dyn WindowOps,
) {
@ -534,7 +533,7 @@ impl super::TermWindow {
fn mouse_event_terminal(
&mut self,
mut pane: Rc<dyn Pane>,
mut pane: Arc<dyn Pane>,
position: ClickPosition,
event: MouseEvent,
context: &dyn WindowOps,
@ -569,7 +568,7 @@ impl super::TermWindow {
mux.get_active_tab_for_window(self.mux_window_id)
.map(|tab| tab.set_active_idx(pos.index));
pane = Rc::clone(&pos.pane);
pane = Arc::clone(&pos.pane);
is_click_to_focus_pane = true;
}
WMEK::Move => {
@ -578,7 +577,7 @@ impl super::TermWindow {
mux.get_active_tab_for_window(self.mux_window_id)
.map(|tab| tab.set_active_idx(pos.index));
pane = Rc::clone(&pos.pane);
pane = Arc::clone(&pos.pane);
context.invalidate();
}
}
@ -586,7 +585,7 @@ impl super::TermWindow {
WMEK::VertWheel(_) => {
// Let wheel events route to the hovered pane,
// even if it doesn't have focus
pane = Rc::clone(&pos.pane);
pane = Arc::clone(&pos.pane);
context.invalidate();
}
}

View File

@ -244,7 +244,7 @@ pub struct RenderScreenLineOpenGLParams<'a> {
pub palette: &'a ColorPalette,
pub dims: &'a RenderableDimensions,
pub config: &'a ConfigHandle,
pub pane: Option<&'a Rc<dyn Pane>>,
pub pane: Option<&'a Arc<dyn Pane>>,
pub white_space: TextureRect,
pub filled_box: TextureRect,
@ -299,7 +299,7 @@ pub struct ComputeCellFgBgParams<'a> {
pub cursor_bg: LinearRgba,
pub cursor_is_default_color: bool,
pub cursor_border_color: LinearRgba,
pub pane: Option<&'a Rc<dyn Pane>>,
pub pane: Option<&'a Arc<dyn Pane>>,
}
#[derive(Debug)]
@ -461,7 +461,7 @@ impl super::TermWindow {
fn get_intensity_if_bell_target_ringing(
&self,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
config: &ConfigHandle,
target: VisualBellTarget,
) -> Option<f32> {
@ -2183,7 +2183,7 @@ impl super::TermWindow {
&mut self,
layers: &mut TripleLayerQuadAllocator,
split: &PositionedSplit,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
) -> anyhow::Result<()> {
let palette = pane.palette();
let foreground = palette.split.to_linear();

View File

@ -2,7 +2,7 @@ use crate::selection::{Selection, SelectionCoordinate, SelectionMode, SelectionR
use ::window::WindowOps;
use mux::pane::{Pane, PaneId};
use std::cell::RefMut;
use std::rc::Rc;
use std::sync::Arc;
use termwiz::surface::Line;
use wezterm_term::StableRowIndex;
@ -12,7 +12,7 @@ impl super::TermWindow {
}
/// 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 rectangular = self.selection(pane.pane_id()).rectangular;
@ -63,7 +63,7 @@ impl super::TermWindow {
}
/// 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 rectangular = self.selection(pane.pane_id()).rectangular;
if let Some(sel) = self
@ -109,14 +109,14 @@ impl super::TermWindow {
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());
selection.clear();
selection.seqno = pane.get_current_seqno();
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();
let (position, y) = match self.pane_state(pane.pane_id()).mouse_terminal_coords {
Some(coords) => coords,
@ -240,7 +240,7 @@ impl super::TermWindow {
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 {
Some(coords) => (coords.0.column, coords.1),
None => return,

View File

@ -9,7 +9,6 @@ use mux::tab::TabId;
use mux::Mux;
use promise::spawn::spawn_into_main_thread;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use termwiz::surface::SequenceNo;
@ -51,7 +50,7 @@ pub(crate) struct PerPane {
impl PerPane {
fn compute_changes(
&mut self,
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
force_with_input_serial: Option<InputSerial>,
) -> Option<GetPaneRenderChangesResponse> {
let mut changed = false;
@ -139,7 +138,7 @@ impl PerPane {
}
fn maybe_push_pane_changes(
pane: &Rc<dyn Pane>,
pane: &Arc<dyn Pane>,
sender: PduSender,
per_pane: Arc<Mutex<PerPane>>,
) -> anyhow::Result<()> {