mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 23:21:08 +03:00
wezterm: tidy up pane/tab/window killing, resize boundaries
This should make closing panes more consistent and reliable; there were some cases where we wouldn't always terminate the associated process and this improves that. There are also some resize boundary check improvements. refs: https://github.com/wez/wezterm/issues/157#issuecomment-700408882 refs: https://github.com/wez/wezterm/issues/157#issuecomment-700335114
This commit is contained in:
parent
3a47d76094
commit
53c63267e8
@ -2038,10 +2038,12 @@ impl TermWindow {
|
||||
(size, dims)
|
||||
} else {
|
||||
// Resize of the window dimensions may result in changed terminal dimensions
|
||||
let avail_width = dimensions.pixel_width
|
||||
- (config.window_padding.left + self.effective_right_padding(&config)) as usize;
|
||||
let avail_height = dimensions.pixel_height
|
||||
- (config.window_padding.top + config.window_padding.bottom) as usize;
|
||||
let avail_width = dimensions.pixel_width.saturating_sub(
|
||||
(config.window_padding.left + self.effective_right_padding(&config)) as usize,
|
||||
);
|
||||
let avail_height = dimensions.pixel_height.saturating_sub(
|
||||
(config.window_padding.top + config.window_padding.bottom) as usize,
|
||||
);
|
||||
|
||||
let rows = (avail_height / self.render_metrics.cell_size.height as usize)
|
||||
.saturating_sub(if self.show_tab_bar { 1 } else { 0 });
|
||||
|
@ -5,7 +5,7 @@ use crate::ratelim::RateLimiter;
|
||||
use crate::server::pollable::{pollable_channel, PollableReceiver, PollableSender};
|
||||
use anyhow::{anyhow, Error};
|
||||
use domain::{Domain, DomainId};
|
||||
use log::{debug, error};
|
||||
use log::error;
|
||||
use portable_pty::ExitStatus;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
@ -223,16 +223,16 @@ impl Mux {
|
||||
self.add_pane(&pane)
|
||||
}
|
||||
|
||||
pub fn remove_pane(&self, pane_id: PaneId) {
|
||||
debug!("removing pane {}", pane_id);
|
||||
fn remove_pane_internal(&self, pane_id: PaneId) {
|
||||
log::debug!("removing pane {}", pane_id);
|
||||
if let Some(pane) = self.panes.borrow_mut().remove(&pane_id) {
|
||||
log::debug!("killing pane {}", pane_id);
|
||||
pane.kill();
|
||||
}
|
||||
self.prune_dead_windows();
|
||||
}
|
||||
|
||||
pub fn remove_tab(&self, tab_id: TabId) {
|
||||
debug!("removing tab {}", tab_id);
|
||||
fn remove_tab_internal(&self, tab_id: TabId) {
|
||||
log::debug!("remove_tab_internal tab {}", tab_id);
|
||||
let mut pane_ids = vec![];
|
||||
if let Some(tab) = self.tabs.borrow_mut().remove(&tab_id) {
|
||||
for pos in tab.iter_panes() {
|
||||
@ -240,61 +240,65 @@ impl Mux {
|
||||
}
|
||||
}
|
||||
for pane_id in pane_ids {
|
||||
self.remove_pane(pane_id);
|
||||
self.remove_pane_internal(pane_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_window_internal(&self, window_id: WindowId) {
|
||||
log::debug!("remove_window_internal {}", window_id);
|
||||
let window = self.windows.borrow_mut().remove(&window_id);
|
||||
if let Some(window) = window {
|
||||
for tab in window.iter() {
|
||||
self.remove_tab_internal(tab.tab_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_pane(&self, pane_id: PaneId) {
|
||||
self.remove_pane_internal(pane_id);
|
||||
self.prune_dead_windows();
|
||||
}
|
||||
|
||||
pub fn remove_tab(&self, tab_id: TabId) {
|
||||
self.remove_tab_internal(tab_id);
|
||||
self.prune_dead_windows();
|
||||
}
|
||||
|
||||
pub fn prune_dead_windows(&self) {
|
||||
let live_tab_ids: Vec<TabId> = self.tabs.borrow().keys().cloned().collect();
|
||||
let mut windows = self.windows.borrow_mut();
|
||||
let mut dead_windows = vec![];
|
||||
let dead_tab_ids: Vec<TabId>;
|
||||
|
||||
{
|
||||
let mut windows = self.windows.borrow_mut();
|
||||
for (window_id, win) in windows.iter_mut() {
|
||||
win.prune_dead_tabs(&live_tab_ids);
|
||||
if win.is_empty() {
|
||||
log::error!("prune_dead_windows: window is now empty");
|
||||
log::debug!("prune_dead_windows: window is now empty");
|
||||
dead_windows.push(*window_id);
|
||||
}
|
||||
}
|
||||
|
||||
let dead_tab_ids: Vec<TabId> = self
|
||||
dead_tab_ids = self
|
||||
.tabs
|
||||
.borrow()
|
||||
.iter()
|
||||
.filter_map(|(&id, tab)| if tab.is_dead() { Some(id) } else { None })
|
||||
.collect();
|
||||
}
|
||||
|
||||
for tab_id in dead_tab_ids {
|
||||
log::error!("tab {} is dead", tab_id);
|
||||
self.tabs.borrow_mut().remove(&tab_id);
|
||||
self.remove_tab_internal(tab_id);
|
||||
}
|
||||
|
||||
/*
|
||||
let dead_pane_ids: Vec<TabId> = self
|
||||
.panes
|
||||
.borrow()
|
||||
.iter()
|
||||
.filter_map(|(&id, pane)| if pane.is_dead() { Some(id) } else { None })
|
||||
.collect();
|
||||
|
||||
for pane_id in dead_pane_ids {
|
||||
self.panes.borrow_mut().remove(&pane_id);
|
||||
}
|
||||
*/
|
||||
|
||||
for window_id in dead_windows {
|
||||
error!("removing window {}", window_id);
|
||||
windows.remove(&window_id);
|
||||
self.remove_window_internal(window_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kill_window(&self, window_id: WindowId) {
|
||||
let mut windows = self.windows.borrow_mut();
|
||||
if let Some(window) = windows.remove(&window_id) {
|
||||
for tab in window.iter() {
|
||||
self.tabs.borrow_mut().remove(&tab.tab_id());
|
||||
}
|
||||
}
|
||||
self.remove_window_internal(window_id);
|
||||
}
|
||||
|
||||
pub fn get_window(&self, window_id: WindowId) -> Option<Ref<Window>> {
|
||||
@ -382,12 +386,28 @@ impl Mux {
|
||||
}
|
||||
|
||||
pub fn domain_was_detached(&self, domain: DomainId) {
|
||||
self.panes
|
||||
.borrow_mut()
|
||||
.retain(|_pane_id, pane| pane.domain_id() != domain);
|
||||
// Ideally we'd do this here, but that seems to cause problems
|
||||
// at the moment:
|
||||
// self.prune_dead_windows();
|
||||
let mut dead_panes = vec![];
|
||||
for pane in self.panes.borrow().values() {
|
||||
if pane.domain_id() == domain {
|
||||
dead_panes.push(pane.pane_id());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut windows = self.windows.borrow_mut();
|
||||
for (_, win) in windows.iter_mut() {
|
||||
for tab in win.iter() {
|
||||
tab.kill_panes_in_domain(domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::error!("domain detached panes: {:?}", dead_panes);
|
||||
for pane_id in dead_panes {
|
||||
self.remove_pane_internal(pane_id);
|
||||
}
|
||||
|
||||
self.prune_dead_windows();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -762,6 +762,11 @@ impl Tab {
|
||||
/// first. For large resizes this tends to proportionally adjust
|
||||
/// the relative sizes of the elements in a split.
|
||||
pub fn resize(&self, size: PtySize) {
|
||||
if size.rows == 0 || size.cols == 0 {
|
||||
// Ignore "impossible" resize requests
|
||||
return;
|
||||
}
|
||||
|
||||
// Un-zoom first, so that the layout can be reasoned about
|
||||
// more easily.
|
||||
let was_zoomed = self.zoomed.borrow().is_some();
|
||||
@ -1150,7 +1155,13 @@ impl Tab {
|
||||
|
||||
pub fn kill_active_pane(&self) -> bool {
|
||||
let active_idx = *self.active.borrow();
|
||||
self.remove_pane_if(|idx, _| idx == active_idx)
|
||||
let killed = self.remove_pane_if(|idx, _| idx == active_idx);
|
||||
log::debug!("kill_active_pane: killed={}", killed);
|
||||
killed
|
||||
}
|
||||
|
||||
pub fn kill_panes_in_domain(&self, domain: DomainId) -> bool {
|
||||
self.remove_pane_if(|_, pane| pane.domain_id() == domain)
|
||||
}
|
||||
|
||||
fn remove_pane_if<F>(&self, f: F) -> bool
|
||||
@ -1197,6 +1208,7 @@ impl Tab {
|
||||
// We might be the root, for example
|
||||
if c.is_top() && c.is_leaf() {
|
||||
root.replace(Tree::Empty);
|
||||
dead_panes.push(pane.pane_id());
|
||||
} else {
|
||||
root.replace(c.tree());
|
||||
}
|
||||
|
@ -252,7 +252,6 @@ fn client_thread(
|
||||
for (_, mut promise) in promises.into_iter() {
|
||||
promise.result(Err(anyhow!("{}", reason)));
|
||||
}
|
||||
// FIXME: detach the domain here
|
||||
return Err(err).context("Error while decoding response pdu");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user