mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 23:21:08 +03:00
move Tabs -> Mux windows hash
This commit is contained in:
parent
a1bdddd8e5
commit
e69290715b
@ -4,11 +4,12 @@ use crate::config::Config;
|
||||
use crate::failure::Error;
|
||||
use crate::font::FontConfiguration;
|
||||
use crate::guicommon::host::{HostHelper, HostImpl, TabHost};
|
||||
use crate::guicommon::tabs::Tabs;
|
||||
use crate::guicommon::window::{Dimensions, TerminalWindow};
|
||||
use crate::guiloop::glutinloop::GuiEventLoop;
|
||||
use crate::guiloop::SessionTerminated;
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
use crate::opengl::render::Renderer;
|
||||
use glium;
|
||||
use glium::glutin::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
|
||||
@ -82,17 +83,15 @@ pub struct GliumTerminalWindow {
|
||||
last_mouse_coords: PhysicalPosition,
|
||||
last_modifiers: KeyModifiers,
|
||||
allow_received_character: bool,
|
||||
tabs: Tabs,
|
||||
mux_window_id: WindowId,
|
||||
have_pending_resize_check: bool,
|
||||
}
|
||||
|
||||
impl TerminalWindow for GliumTerminalWindow {
|
||||
fn get_tabs(&self) -> &Tabs {
|
||||
&self.tabs
|
||||
}
|
||||
fn get_tabs_mut(&mut self) -> &mut Tabs {
|
||||
&mut self.tabs
|
||||
fn get_mux_window_id(&self) -> WindowId {
|
||||
self.mux_window_id
|
||||
}
|
||||
|
||||
fn config(&self) -> &Arc<Config> {
|
||||
&self.config
|
||||
}
|
||||
@ -115,9 +114,6 @@ impl TerminalWindow for GliumTerminalWindow {
|
||||
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error> {
|
||||
self.renderer.recreate_atlas(&self.host.display, size)
|
||||
}
|
||||
fn renderer_and_tab(&mut self) -> (&mut Renderer, &Rc<Tab>) {
|
||||
(&mut self.renderer, self.tabs.get_active().unwrap())
|
||||
}
|
||||
|
||||
fn tab_was_created(&mut self, tab: &Rc<Tab>) -> Result<(), Error> {
|
||||
self.event_loop.register_tab(tab)
|
||||
@ -242,6 +238,9 @@ impl GliumTerminalWindow {
|
||||
let height = height as u16;
|
||||
let renderer = Renderer::new(&host.display, width, height, fonts, palette)?;
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
let mux_window_id = mux.add_new_window_with_tab(tab)?;
|
||||
|
||||
Ok(GliumTerminalWindow {
|
||||
host,
|
||||
event_loop: Rc::clone(event_loop),
|
||||
@ -255,7 +254,7 @@ impl GliumTerminalWindow {
|
||||
last_mouse_coords: PhysicalPosition::new(0.0, 0.0),
|
||||
last_modifiers: Default::default(),
|
||||
allow_received_character: false,
|
||||
tabs: Tabs::new(tab),
|
||||
mux_window_id,
|
||||
have_pending_resize_check: false,
|
||||
})
|
||||
}
|
||||
@ -286,7 +285,8 @@ impl GliumTerminalWindow {
|
||||
position: PhysicalPosition,
|
||||
modifiers: glium::glutin::ModifiersState,
|
||||
) -> Result<(), Error> {
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -326,7 +326,8 @@ impl GliumTerminalWindow {
|
||||
button: glutin::MouseButton,
|
||||
modifiers: glium::glutin::ModifiersState,
|
||||
) -> Result<(), Error> {
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -391,7 +392,8 @@ impl GliumTerminalWindow {
|
||||
_ => return Ok(()),
|
||||
};
|
||||
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -610,7 +612,8 @@ impl GliumTerminalWindow {
|
||||
}
|
||||
|
||||
fn key_event(&mut self, event: glium::glutin::KeyboardInput) -> Result<(), Error> {
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -626,7 +629,7 @@ impl GliumTerminalWindow {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.host.process_gui_shortcuts(&**tab, mods, key)? {
|
||||
if self.host.process_gui_shortcuts(&*tab, mods, key)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -678,7 +681,8 @@ impl GliumTerminalWindow {
|
||||
// eprintln!("ReceivedCharacter {} {:?}", c as u32, c);
|
||||
if self.allow_received_character {
|
||||
self.allow_received_character = false;
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ use crate::mux::tab::{alloc_tab_id, Tab, TabId};
|
||||
use crate::{Child, MasterPty};
|
||||
use failure::Error;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::rc::Rc;
|
||||
use term::{KeyCode, KeyModifiers, MouseEvent, Terminal, TerminalHost};
|
||||
|
||||
pub struct LocalTab {
|
||||
@ -99,74 +98,3 @@ impl Drop for LocalTab {
|
||||
self.process.borrow_mut().wait().ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tabs {
|
||||
tabs: Vec<Rc<Tab>>,
|
||||
active: usize,
|
||||
}
|
||||
|
||||
impl Tabs {
|
||||
pub fn new(tab: &Rc<Tab>) -> Self {
|
||||
Self {
|
||||
tabs: vec![Rc::clone(tab)],
|
||||
active: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, tab: &Rc<Tab>) {
|
||||
self.tabs.push(Rc::clone(tab))
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.tabs.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.tabs.len()
|
||||
}
|
||||
|
||||
pub fn get_by_idx(&self, idx: usize) -> Option<&Rc<Tab>> {
|
||||
self.tabs.get(idx)
|
||||
}
|
||||
|
||||
pub fn idx_by_id(&self, id: TabId) -> Option<usize> {
|
||||
for (idx, t) in self.tabs.iter().enumerate() {
|
||||
if t.tab_id() == id {
|
||||
return Some(idx);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn remove_by_id(&mut self, id: TabId) {
|
||||
if let Some(idx) = self.idx_by_id(id) {
|
||||
self.tabs.remove(idx);
|
||||
let len = self.tabs.len();
|
||||
if len > 0 && self.active == idx && idx >= len {
|
||||
self.set_active(len - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_active(&self) -> Option<&Rc<Tab>> {
|
||||
self.get_by_idx(self.active)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_active_idx(&self) -> usize {
|
||||
self.active
|
||||
}
|
||||
|
||||
pub fn set_active(&mut self, idx: usize) {
|
||||
assert!(idx < self.tabs.len());
|
||||
self.active = idx;
|
||||
self.get_by_idx(idx)
|
||||
.unwrap()
|
||||
.renderer()
|
||||
.make_all_lines_dirty();
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Rc<Tab>> {
|
||||
self.tabs.iter()
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::config::Config;
|
||||
use crate::font::FontConfiguration;
|
||||
use crate::guicommon::tabs::{LocalTab, Tabs};
|
||||
use crate::guicommon::tabs::LocalTab;
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
use crate::opengl::render::Renderer;
|
||||
use crate::opengl::textureatlas::OutOfTextureSpace;
|
||||
use crate::openpty;
|
||||
@ -25,12 +27,10 @@ pub struct Dimensions {
|
||||
/// A number of methods need to be provided by the window in order to
|
||||
/// unlock the use of the provided methods towards the bottom of the trait.
|
||||
pub trait TerminalWindow {
|
||||
fn get_tabs_mut(&mut self) -> &mut Tabs;
|
||||
fn get_tabs(&self) -> &Tabs;
|
||||
fn set_window_title(&mut self, title: &str) -> Result<(), Error>;
|
||||
fn get_mux_window_id(&self) -> WindowId;
|
||||
fn frame(&self) -> glium::Frame;
|
||||
fn renderer(&mut self) -> &mut Renderer;
|
||||
fn renderer_and_tab(&mut self) -> (&mut Renderer, &Rc<Tab>);
|
||||
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error>;
|
||||
fn advise_renderer_that_scaling_has_changed(
|
||||
&mut self,
|
||||
@ -49,31 +49,51 @@ pub trait TerminalWindow {
|
||||
}
|
||||
|
||||
fn activate_tab(&mut self, tab_idx: usize) -> Result<(), Error> {
|
||||
let max = self.get_tabs().len();
|
||||
let mux = Mux::get().unwrap();
|
||||
let mut window = mux
|
||||
.get_window_mut(self.get_mux_window_id())
|
||||
.ok_or_else(|| format_err!("no such window"))?;
|
||||
|
||||
let max = window.len();
|
||||
if tab_idx < max {
|
||||
self.get_tabs_mut().set_active(tab_idx);
|
||||
window.set_active(tab_idx);
|
||||
|
||||
drop(window);
|
||||
self.update_title();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn activate_tab_relative(&mut self, delta: isize) -> Result<(), Error> {
|
||||
let max = self.get_tabs().len();
|
||||
let active = self.get_tabs().get_active_idx() as isize;
|
||||
let mux = Mux::get().unwrap();
|
||||
let window = mux
|
||||
.get_window(self.get_mux_window_id())
|
||||
.ok_or_else(|| format_err!("no such window"))?;
|
||||
|
||||
let max = window.len();
|
||||
let active = window.get_active_idx() as isize;
|
||||
let tab = active + delta;
|
||||
let tab = if tab < 0 { max as isize + tab } else { tab };
|
||||
drop(window);
|
||||
self.activate_tab(tab as usize % max)
|
||||
}
|
||||
|
||||
fn update_title(&mut self) {
|
||||
let num_tabs = self.get_tabs().len();
|
||||
let mux = Mux::get().unwrap();
|
||||
let window = match mux.get_window(self.get_mux_window_id()) {
|
||||
Some(window) => window,
|
||||
_ => return,
|
||||
};
|
||||
let num_tabs = window.len();
|
||||
|
||||
if num_tabs == 0 {
|
||||
return;
|
||||
}
|
||||
let tab_no = self.get_tabs().get_active_idx();
|
||||
let tab_no = window.get_active_idx();
|
||||
|
||||
let title = self.get_tabs().get_active().unwrap().get_title();
|
||||
let title = window.get_active().unwrap().get_title();
|
||||
|
||||
drop(window);
|
||||
|
||||
if num_tabs == 1 {
|
||||
self.set_window_title(&title).ok();
|
||||
@ -84,7 +104,8 @@ pub trait TerminalWindow {
|
||||
}
|
||||
|
||||
fn paint_if_needed(&mut self) -> Result<(), Error> {
|
||||
let tab = match self.get_tabs().get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -98,8 +119,14 @@ pub trait TerminalWindow {
|
||||
fn paint(&mut self) -> Result<(), Error> {
|
||||
let mut target = self.frame();
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let res = {
|
||||
let (renderer, tab) = self.renderer_and_tab();
|
||||
let renderer = self.renderer();
|
||||
renderer.paint(&mut target, &mut *tab.renderer())
|
||||
};
|
||||
|
||||
@ -117,11 +144,7 @@ pub trait TerminalWindow {
|
||||
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
|
||||
eprintln!("out of texture space, allocating {}", size);
|
||||
self.recreate_texture_atlas(size)?;
|
||||
self.get_tabs_mut()
|
||||
.get_active()
|
||||
.unwrap()
|
||||
.renderer()
|
||||
.make_all_lines_dirty();
|
||||
tab.renderer().make_all_lines_dirty();
|
||||
// Recursively initiate a new paint
|
||||
return self.paint();
|
||||
}
|
||||
@ -145,6 +168,8 @@ pub trait TerminalWindow {
|
||||
let process = slave.spawn_command(cmd)?;
|
||||
eprintln!("spawned: {:?}", process);
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
|
||||
let terminal = term::Terminal::new(
|
||||
rows,
|
||||
cols,
|
||||
@ -155,8 +180,13 @@ pub trait TerminalWindow {
|
||||
let tab: Rc<Tab> = Rc::new(LocalTab::new(terminal, process, pty));
|
||||
let tab_id = tab.tab_id();
|
||||
|
||||
self.get_tabs_mut().push(&tab);
|
||||
let len = self.get_tabs().len();
|
||||
let len = {
|
||||
let mut window = mux
|
||||
.get_window_mut(self.get_mux_window_id())
|
||||
.ok_or_else(|| format_err!("no such window!?"))?;
|
||||
window.push(&tab);
|
||||
window.len()
|
||||
};
|
||||
self.activate_tab(len - 1)?;
|
||||
|
||||
self.tab_was_created(&tab)?;
|
||||
@ -179,8 +209,11 @@ pub trait TerminalWindow {
|
||||
let rows = ((height as usize + 1) / dims.cell_height) as u16;
|
||||
let cols = ((width as usize + 1) / dims.cell_width) as u16;
|
||||
|
||||
let tabs = self.get_tabs();
|
||||
for tab in tabs.iter() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let window = mux
|
||||
.get_window(self.get_mux_window_id())
|
||||
.ok_or_else(|| format_err!("no such window!?"))?;
|
||||
for tab in window.iter() {
|
||||
tab.resize(rows, cols, width as u16, height as u16)?;
|
||||
}
|
||||
|
||||
@ -205,9 +238,12 @@ pub trait TerminalWindow {
|
||||
"TerminalWindow::scaling_changed dpi_scale={} font_scale={}",
|
||||
dpi_scale, font_scale
|
||||
);
|
||||
if let Some(tab) = self.get_tabs().get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
tab.renderer().make_all_lines_dirty();
|
||||
}
|
||||
fonts.change_scaling(font_scale, dpi_scale);
|
||||
|
||||
let metrics = fonts.default_font_metrics()?;
|
||||
@ -217,13 +253,7 @@ pub trait TerminalWindow {
|
||||
// so we query for that information here.
|
||||
// If the backend supports `resize_if_not_full_screen` then we'll try
|
||||
// to resize the window to match the new cell metrics.
|
||||
let (rows, cols) = {
|
||||
self.get_tabs()
|
||||
.get_active()
|
||||
.unwrap()
|
||||
.renderer()
|
||||
.physical_dimensions()
|
||||
};
|
||||
let (rows, cols) = { tab.renderer().physical_dimensions() };
|
||||
|
||||
self.advise_renderer_that_scaling_has_changed(
|
||||
cell_width.ceil() as usize,
|
||||
@ -239,16 +269,28 @@ pub trait TerminalWindow {
|
||||
}
|
||||
|
||||
fn tab_did_terminate(&mut self, tab_id: TabId) {
|
||||
self.get_tabs_mut().remove_by_id(tab_id);
|
||||
if let Some(active) = self.get_tabs().get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let mut window = match mux.get_window_mut(self.get_mux_window_id()) {
|
||||
Some(window) => window,
|
||||
None => return,
|
||||
};
|
||||
|
||||
window.remove_by_id(tab_id);
|
||||
|
||||
if let Some(active) = window.get_active() {
|
||||
active.renderer().make_all_lines_dirty();
|
||||
self.update_title();
|
||||
}
|
||||
drop(window);
|
||||
self.update_title();
|
||||
self.deregister_tab(tab_id).ok();
|
||||
}
|
||||
fn test_for_child_exit(&mut self) -> bool {
|
||||
let tabs = self.get_tabs();
|
||||
let dead_tabs: Vec<Rc<Tab>> = tabs
|
||||
let mux = Mux::get().unwrap();
|
||||
let window = match mux.get_window(self.get_mux_window_id()) {
|
||||
Some(window) => window,
|
||||
None => return true,
|
||||
};
|
||||
let dead_tabs: Vec<Rc<Tab>> = window
|
||||
.iter()
|
||||
.filter_map(|tab| {
|
||||
if tab.is_dead() {
|
||||
@ -258,9 +300,14 @@ pub trait TerminalWindow {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
drop(window);
|
||||
for tab in dead_tabs {
|
||||
self.tab_did_terminate(tab.tab_id());
|
||||
}
|
||||
self.get_tabs().is_empty()
|
||||
let empty = match mux.get_window(self.get_mux_window_id()) {
|
||||
Some(window) => window.is_empty(),
|
||||
None => true,
|
||||
};
|
||||
empty
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use failure::Error;
|
||||
use promise::{Executor, Future};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
use std::rc::Rc;
|
||||
@ -10,12 +10,15 @@ use termwiz::hyperlink::Hyperlink;
|
||||
|
||||
pub mod renderable;
|
||||
pub mod tab;
|
||||
pub mod window;
|
||||
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::{Window, WindowId};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Mux {
|
||||
tabs: RefCell<HashMap<TabId, Rc<Tab>>>,
|
||||
windows: RefCell<HashMap<WindowId, Window>>,
|
||||
}
|
||||
|
||||
fn read_from_tab_pty(executor: Box<Executor>, tab_id: TabId, mut reader: Box<std::io::Read>) {
|
||||
@ -127,6 +130,36 @@ impl Mux {
|
||||
self.tabs.borrow_mut().remove(&tab_id);
|
||||
}
|
||||
|
||||
pub fn get_window(&self, window_id: WindowId) -> Option<Ref<Window>> {
|
||||
if !self.windows.borrow().contains_key(&window_id) {
|
||||
return None;
|
||||
}
|
||||
Some(Ref::map(self.windows.borrow(), |windows| {
|
||||
windows.get(&window_id).unwrap()
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_window_mut(&self, window_id: WindowId) -> Option<RefMut<Window>> {
|
||||
if !self.windows.borrow().contains_key(&window_id) {
|
||||
return None;
|
||||
}
|
||||
Some(RefMut::map(self.windows.borrow_mut(), |windows| {
|
||||
windows.get_mut(&window_id).unwrap()
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn get_active_tab_for_window(&self, window_id: WindowId) -> Option<Rc<Tab>> {
|
||||
let window = self.get_window(window_id)?;
|
||||
window.get_active().map(Rc::clone)
|
||||
}
|
||||
|
||||
pub fn add_new_window_with_tab(&self, tab: &Rc<Tab>) -> Result<WindowId, Error> {
|
||||
let window = Window::new(tab);
|
||||
let window_id = window.window_id();
|
||||
self.windows.borrow_mut().insert(window_id, window);
|
||||
Ok(window_id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.tabs.borrow().is_empty()
|
||||
|
82
src/mux/window.rs
Normal file
82
src/mux/window.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::mux::{Tab, TabId};
|
||||
use std::rc::Rc;
|
||||
|
||||
static WIN_ID: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
|
||||
pub type WindowId = usize;
|
||||
|
||||
pub struct Window {
|
||||
id: WindowId,
|
||||
tabs: Vec<Rc<Tab>>,
|
||||
active: usize,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(tab: &Rc<Tab>) -> Self {
|
||||
Self {
|
||||
id: WIN_ID.fetch_add(1, ::std::sync::atomic::Ordering::Relaxed),
|
||||
tabs: vec![Rc::clone(tab)],
|
||||
active: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_id(&self) -> WindowId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn push(&mut self, tab: &Rc<Tab>) {
|
||||
self.tabs.push(Rc::clone(tab))
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.tabs.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.tabs.len()
|
||||
}
|
||||
|
||||
pub fn get_by_idx(&self, idx: usize) -> Option<&Rc<Tab>> {
|
||||
self.tabs.get(idx)
|
||||
}
|
||||
|
||||
pub fn idx_by_id(&self, id: TabId) -> Option<usize> {
|
||||
for (idx, t) in self.tabs.iter().enumerate() {
|
||||
if t.tab_id() == id {
|
||||
return Some(idx);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn remove_by_id(&mut self, id: TabId) {
|
||||
if let Some(idx) = self.idx_by_id(id) {
|
||||
self.tabs.remove(idx);
|
||||
let len = self.tabs.len();
|
||||
if len > 0 && self.active == idx && idx >= len {
|
||||
self.set_active(len - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_active(&self) -> Option<&Rc<Tab>> {
|
||||
self.get_by_idx(self.active)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_active_idx(&self) -> usize {
|
||||
self.active
|
||||
}
|
||||
|
||||
pub fn set_active(&mut self, idx: usize) {
|
||||
assert!(idx < self.tabs.len());
|
||||
self.active = idx;
|
||||
self.get_by_idx(idx)
|
||||
.unwrap()
|
||||
.renderer()
|
||||
.make_all_lines_dirty();
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Rc<Tab>> {
|
||||
self.tabs.iter()
|
||||
}
|
||||
}
|
@ -4,11 +4,13 @@ use super::{Connection, Window};
|
||||
use crate::config::Config;
|
||||
use crate::font::FontConfiguration;
|
||||
use crate::guicommon::host::{HostHelper, HostImpl, TabHost};
|
||||
use crate::guicommon::tabs::{Tab, TabId, Tabs};
|
||||
use crate::guicommon::window::{Dimensions, TerminalWindow};
|
||||
use crate::guiloop::x11::{GuiEventLoop, WindowId};
|
||||
use crate::guiloop::x11::{GuiEventLoop, WindowId as X11WindowId};
|
||||
use crate::guiloop::SessionTerminated;
|
||||
use crate::mux::renderable::Renderable;
|
||||
use crate::mux::tab::{Tab, TabId};
|
||||
use crate::mux::window::WindowId;
|
||||
use crate::mux::Mux;
|
||||
use failure::Error;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
@ -43,16 +45,13 @@ pub struct X11TerminalWindow {
|
||||
height: u16,
|
||||
cell_height: usize,
|
||||
cell_width: usize,
|
||||
tabs: Tabs,
|
||||
have_pending_resize: Option<(u16, u16)>,
|
||||
mux_window_id: WindowId,
|
||||
}
|
||||
|
||||
impl TerminalWindow for X11TerminalWindow {
|
||||
fn get_tabs(&self) -> &Tabs {
|
||||
&self.tabs
|
||||
}
|
||||
fn get_tabs_mut(&mut self) -> &mut Tabs {
|
||||
&mut self.tabs
|
||||
fn get_mux_window_id(&self) -> WindowId {
|
||||
self.mux_window_id
|
||||
}
|
||||
fn config(&self) -> &Arc<Config> {
|
||||
&self.host.config
|
||||
@ -75,9 +74,6 @@ impl TerminalWindow for X11TerminalWindow {
|
||||
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error> {
|
||||
self.renderer.recreate_atlas(&self.host.window, size)
|
||||
}
|
||||
fn renderer_and_tab(&mut self) -> (&mut Renderer, &Tab) {
|
||||
(&mut self.renderer, self.tabs.get_active().unwrap())
|
||||
}
|
||||
fn tab_was_created(&mut self, tab: &Rc<Tab>) -> Result<(), Error> {
|
||||
self.host.event_loop.register_tab(tab)
|
||||
}
|
||||
@ -158,7 +154,8 @@ impl X11TerminalWindow {
|
||||
});
|
||||
|
||||
let renderer = Renderer::new(&host.window, width, height, fonts, palette)?;
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
let mux_window_id = mux.add_new_window_with_tab(tab)?;
|
||||
host.window.show();
|
||||
|
||||
Ok(X11TerminalWindow {
|
||||
@ -169,12 +166,12 @@ impl X11TerminalWindow {
|
||||
height,
|
||||
cell_height,
|
||||
cell_width,
|
||||
tabs: Tabs::new(tab),
|
||||
have_pending_resize: None,
|
||||
mux_window_id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn window_id(&self) -> WindowId {
|
||||
pub fn window_id(&self) -> X11WindowId {
|
||||
self.host.window.window.window_id
|
||||
}
|
||||
|
||||
@ -187,7 +184,8 @@ impl X11TerminalWindow {
|
||||
}
|
||||
|
||||
fn mouse_event(&mut self, event: MouseEvent) -> Result<(), Error> {
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
@ -212,7 +210,8 @@ impl X11TerminalWindow {
|
||||
}
|
||||
xcb::KEY_PRESS => {
|
||||
let key_press: &xcb::KeyPressEvent = unsafe { xcb::cast_event(event) };
|
||||
let tab = match self.tabs.get_active() {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(self.get_mux_window_id()) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user