1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-10 15:04:32 +03:00

software: implement most key assignments

This commit is contained in:
Wez Furlong 2019-09-28 13:46:17 -07:00
parent a7c4eb430d
commit 436bdf7589

View File

@ -1,9 +1,12 @@
use crate::config::Config;
use crate::config::TextStyle;
use crate::font::{FontConfiguration, GlyphInfo};
use crate::font::{FontConfiguration, FontSystemSelection, GlyphInfo};
use crate::frontend::guicommon::clipboard::SystemClipboard;
use crate::frontend::guicommon::host::{KeyAssignment, KeyMap};
use crate::frontend::guicommon::window::SpawnTabDomain;
use crate::frontend::{front_end, gui_executor};
use crate::mux::renderable::Renderable;
use crate::mux::tab::Tab;
use crate::mux::tab::{Tab, TabId};
use crate::mux::window::WindowId as MuxWindowId;
use crate::mux::Mux;
use ::window::bitmaps::atlas::{Atlas, Sprite, SpriteSlice};
@ -54,6 +57,7 @@ pub struct TermWindow {
glyph_cache: RefCell<HashMap<GlyphKey, Rc<CachedGlyph>>>,
atlas: RefCell<Atlas<ImageTexture>>,
clipboard: Arc<dyn term::Clipboard>,
keys: KeyMap,
}
struct Host<'a> {
@ -265,7 +269,10 @@ impl WindowCallbacks for TermWindow {
};
if let Some(key) = key_down {
if tab.key_down(key, modifiers).is_ok() {
if let Some(assignment) = self.keys.lookup(key, modifiers) {
self.perform_key_assignment(&tab, &assignment).ok();
return true;
} else if tab.key_down(key, modifiers).is_ok() {
return true;
}
}
@ -284,6 +291,7 @@ impl WindowCallbacks for TermWindow {
}
};
self.paint_tab(&tab, ctx);
self.update_title();
}
}
@ -352,6 +360,7 @@ impl TermWindow {
glyph_cache: RefCell::new(HashMap::new()),
atlas,
clipboard: Arc::new(SystemClipboard::new()),
keys: KeyMap::new(),
}),
)?;
@ -375,6 +384,198 @@ impl TermWindow {
Ok(())
}
fn update_title(&mut self) {
let mux = Mux::get().unwrap();
let window = match mux.get_window(self.mux_window_id) {
Some(window) => window,
_ => return,
};
let num_tabs = window.len();
if num_tabs == 0 {
return;
}
let tab_no = window.get_active_idx();
let title = match window.get_active() {
Some(tab) => tab.get_title(),
None => return,
};
drop(window);
if let Some(window) = self.window.as_ref() {
if num_tabs == 1 {
window.set_title(&title);
} else {
window.set_title(&format!("[{}/{}] {}", tab_no + 1, num_tabs, title));
}
}
}
fn activate_tab(&mut self, tab_idx: usize) -> Fallible<()> {
let mux = Mux::get().unwrap();
let mut window = mux
.get_window_mut(self.mux_window_id)
.ok_or_else(|| failure::format_err!("no such window"))?;
let max = window.len();
if tab_idx < max {
window.set_active(tab_idx);
drop(window);
self.update_title();
}
Ok(())
}
fn activate_tab_relative(&mut self, delta: isize) -> Fallible<()> {
let mux = Mux::get().unwrap();
let window = mux
.get_window(self.mux_window_id)
.ok_or_else(|| failure::format_err!("no such window"))?;
let max = window.len();
failure::ensure!(max > 0, "no more tabs");
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 spawn_tab(&mut self, domain: &SpawnTabDomain) -> Fallible<TabId> {
let rows = (self.dimensions.pixel_height as usize + 1) / self.cell_size.height as usize;
let cols = (self.dimensions.pixel_width as usize + 1) / self.cell_size.width as usize;
let size = portable_pty::PtySize {
rows: rows as u16,
cols: cols as u16,
pixel_width: self.dimensions.pixel_width as u16,
pixel_height: self.dimensions.pixel_height as u16,
};
let mux = Mux::get().unwrap();
let domain = match domain {
SpawnTabDomain::DefaultDomain => mux.default_domain().clone(),
SpawnTabDomain::CurrentTabDomain => {
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
Some(tab) => tab,
None => failure::bail!("window has no tabs?"),
};
mux.get_domain(tab.domain_id()).ok_or_else(|| {
failure::format_err!("current tab has unresolvable domain id!?")
})?
}
SpawnTabDomain::Domain(id) => mux.get_domain(*id).ok_or_else(|| {
failure::format_err!("spawn_tab called with unresolvable domain id!?")
})?,
SpawnTabDomain::DomainName(name) => mux.get_domain_by_name(&name).ok_or_else(|| {
failure::format_err!("spawn_tab called with unresolvable domain name {}", name)
})?,
};
let tab = domain.spawn(size, None, self.mux_window_id)?;
let tab_id = tab.tab_id();
let len = {
let window = mux
.get_window(self.mux_window_id)
.ok_or_else(|| failure::format_err!("no such window!?"))?;
window.len()
};
self.activate_tab(len - 1)?;
Ok(tab_id)
}
fn perform_key_assignment(
&mut self,
tab: &Rc<dyn Tab>,
assignment: &KeyAssignment,
) -> Fallible<()> {
use KeyAssignment::*;
match assignment {
SpawnTab(spawn_where) => {
self.spawn_tab(spawn_where)?;
}
SpawnWindow => {
self.spawn_new_window();
}
ToggleFullScreen => {
// self.toggle_full_screen(),
}
Copy => {
// Nominally copy, but that is implicit, so NOP
}
Paste => {
/*
let text = self.get_clipboard()?.get_contents()?;
if text.len() <= PASTE_CHUNK_SIZE {
// Send it all now
tab.send_paste(&text)?;
} else {
// It's pretty heavy, so we trickle it into the pty
tab.send_paste(&text[0..PASTE_CHUNK_SIZE])?;
trickle_paste(tab.tab_id(), text);
}
*/
}
ActivateTabRelative(n) => {
self.activate_tab_relative(*n)?;
}
DecreaseFontSize => self.decrease_font_size(),
IncreaseFontSize => self.increase_font_size(),
ResetFontSize => self.reset_font_size(),
ActivateTab(n) => {
self.activate_tab(*n)?;
}
SendString(s) => tab.writer().write_all(s.as_bytes())?,
Hide => {
self.window.as_ref().map(|w| w.hide());
}
Show => {
self.window.as_ref().map(|w| w.show());
}
CloseCurrentTab => self.close_current_tab(),
Nop => {}
};
Ok(())
}
pub fn spawn_new_window(&mut self) {
promise::Future::with_executor(gui_executor().unwrap(), move || {
let mux = Mux::get().unwrap();
let fonts = Rc::new(FontConfiguration::new(
Arc::clone(mux.config()),
FontSystemSelection::get_default(),
));
let window_id = mux.new_empty_window();
let tab =
mux.default_domain()
.spawn(portable_pty::PtySize::default(), None, window_id)?;
let front_end = front_end().expect("to be called on gui thread");
front_end.spawn_new_window(mux.config(), &fonts, &tab, window_id)?;
Ok(())
});
}
fn decrease_font_size(&mut self) {}
fn increase_font_size(&mut self) {}
fn reset_font_size(&mut self) {}
fn close_current_tab(&mut self) {
let mux = Mux::get().unwrap();
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
Some(tab) => tab,
None => return,
};
mux.remove_tab(tab.tab_id());
if let Some(mut win) = mux.get_window_mut(self.mux_window_id) {
win.remove_by_id(tab.tab_id());
}
self.activate_tab_relative(0).ok();
}
fn paint_tab(&mut self, tab: &Rc<dyn Tab>, ctx: &mut dyn PaintContext) {
let palette = tab.palette();