1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-29 00:21:57 +03:00

factor out the paint logic

This commit is contained in:
Wez Furlong 2019-02-23 22:04:58 -08:00
parent 315ff45880
commit d639ad0ffe
5 changed files with 112 additions and 92 deletions

View File

@ -14,6 +14,7 @@ use clipboard::{ClipboardContext, ClipboardProvider};
use glium;
use glium::glutin::dpi::{LogicalPosition, LogicalSize, PhysicalPosition};
use glium::glutin::{self, ElementState, MouseCursor};
use std::cell::RefMut;
use std::io::Write;
use std::rc::Rc;
use term::KeyCode;
@ -212,7 +213,10 @@ pub struct GliumTerminalWindow {
}
impl TerminalWindow for GliumTerminalWindow {
fn get_tabs(&mut self) -> &mut Tabs {
fn get_tabs(&self) -> &Tabs {
&self.tabs
}
fn get_tabs_mut(&mut self) -> &mut Tabs {
&mut self.tabs
}
@ -220,6 +224,23 @@ impl TerminalWindow for GliumTerminalWindow {
self.host.display.gl_window().set_title(title);
Ok(())
}
fn frame(&self) -> glium::Frame {
self.host.display.draw()
}
fn renderer(&mut self) -> &mut Renderer {
&mut self.renderer
}
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error> {
self.renderer.recreate_atlas(&self.host.display, size)
}
fn renderer_and_terminal(&mut self) -> (&mut Renderer, RefMut<term::Terminal>) {
(
&mut self.renderer,
self.tabs.get_active().unwrap().terminal(),
)
}
}
impl GliumTerminalWindow {
@ -333,14 +354,6 @@ impl GliumTerminalWindow {
Ok(())
}
pub fn activate_tab_relative(&mut self, delta: isize) -> Result<(), Error> {
let max = self.tabs.len();
let active = self.tabs.get_active_idx() as isize;
let tab = active + delta;
let tab = if tab < 0 { max as isize + tab } else { tab };
self.activate_tab(tab as usize % max)
}
pub fn window_id(&self) -> glutin::WindowId {
self.host.display.gl_window().id()
}
@ -353,35 +366,6 @@ impl GliumTerminalWindow {
.try_clone()
}
pub fn paint(&mut self) -> Result<(), Error> {
let tab = match self.tabs.get_active() {
Some(tab) => tab,
None => return Ok(()),
};
let mut target = self.host.display.draw();
let res = self.renderer.paint(&mut target, &mut tab.terminal());
// Ensure that we finish() the target before we let the
// error bubble up, otherwise we lose the context.
target.finish().unwrap();
// The only error we want to catch is texture space related;
// when that happens we need to blow our glyph cache and
// allocate a newer bigger texture.
match res {
Err(err) => {
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
eprintln!("out of texture space, allocating {}", size);
self.renderer.recreate_atlas(&self.host.display, size)?;
tab.terminal().make_all_lines_dirty();
// Recursively initiate a new paint
return self.paint();
}
Err(err)
}
Ok(_) => Ok(()),
}
}
pub fn process_data_read_from_pty(&mut self, data: &[u8], tab_id: usize) -> Result<(), Error> {
let tab = self.tabs.get_by_id(tab_id)?;

View File

@ -1,19 +1,37 @@
use crate::guicommon::tabs::Tabs;
use crate::opengl::render::Renderer;
use crate::opengl::textureatlas::OutOfTextureSpace;
use failure::Error;
use glium;
use glium::backend::Facade;
use std::cell::RefMut;
pub trait TerminalWindow {
fn get_tabs(&mut self) -> &mut Tabs;
fn get_tabs_mut(&mut self) -> &mut Tabs;
fn get_tabs(&self) -> &Tabs;
fn set_window_title(&mut self, title: &str) -> Result<(), Error>;
fn frame(&self) -> glium::Frame;
fn renderer(&mut self) -> &mut Renderer;
fn renderer_and_terminal(&mut self) -> (&mut Renderer, RefMut<term::Terminal>);
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error>;
fn activate_tab(&mut self, tab_idx: usize) -> Result<(), Error> {
let max = self.get_tabs().len();
if tab_idx < max {
self.get_tabs().set_active(tab_idx);
self.get_tabs_mut().set_active(tab_idx);
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 tab = active + delta;
let tab = if tab < 0 { max as isize + tab } else { tab };
self.activate_tab(tab as usize % max)
}
fn update_title(&mut self) {
let num_tabs = self.get_tabs().len();
@ -34,4 +52,51 @@ pub trait TerminalWindow {
.ok();
}
}
fn paint_if_needed(&mut self) -> Result<(), Error> {
let tab = match self.get_tabs().get_active() {
Some(tab) => tab,
None => return Ok(()),
};
if tab.terminal().has_dirty_lines() {
self.paint()?;
}
Ok(())
}
fn paint(&mut self) -> Result<(), Error> {
let mut target = self.frame();
let res = {
let (renderer, mut terminal) = self.renderer_and_terminal();
renderer.paint(&mut target, &mut terminal)
};
// Ensure that we finish() the target before we let the
// error bubble up, otherwise we lose the context.
target
.finish()
.expect("target.finish failed and we don't know how to recover");
// The only error we want to catch is texture space related;
// when that happens we need to blow our glyph cache and
// allocate a newer bigger texture.
match res {
Err(err) => {
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()
.terminal()
.make_all_lines_dirty();
// Recursively initiate a new paint
return self.paint();
}
Err(err)
}
Ok(_) => Ok(()),
}
}
}

View File

@ -2,6 +2,7 @@ use super::GuiSystem;
use crate::futurecore;
use crate::gliumwindows;
pub use crate::gliumwindows::GliumTerminalWindow;
use crate::guicommon::window::TerminalWindow;
use crate::guiloop::SessionTerminated;
use crate::{Child, MasterPty};
use failure::Error;

View File

@ -3,6 +3,7 @@ use crate::config::Config;
use crate::font::FontConfiguration;
use crate::futurecore;
use crate::guicommon::tabs::TabId;
use crate::guicommon::window::TerminalWindow;
use crate::xwindows::xwin::X11TerminalWindow;
use crate::xwindows::Connection;
use crate::{spawn_window_impl, Child, MasterPty};

View File

@ -13,6 +13,7 @@ use crate::{openpty, MasterPty};
use clipboard::{ClipboardContext, ClipboardProvider};
use failure::Error;
use futures;
use std::cell::RefMut;
use std::io::{self, Read, Write};
use std::rc::Rc;
use term::{self, KeyCode, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
@ -162,7 +163,10 @@ impl<'a> term::TerminalHost for TabHost<'a> {
}
impl TerminalWindow for X11TerminalWindow {
fn get_tabs(&mut self) -> &mut Tabs {
fn get_tabs(&self) -> &Tabs {
&self.tabs
}
fn get_tabs_mut(&mut self) -> &mut Tabs {
&mut self.tabs
}
@ -170,6 +174,22 @@ impl TerminalWindow for X11TerminalWindow {
self.host.window.set_title(title);
Ok(())
}
fn frame(&self) -> glium::Frame {
self.host.window.draw()
}
fn renderer(&mut self) -> &mut Renderer {
&mut self.renderer
}
fn recreate_texture_atlas(&mut self, size: u32) -> Result<(), Error> {
self.renderer.recreate_atlas(&self.host.window, size)
}
fn renderer_and_terminal(&mut self) -> (&mut Renderer, RefMut<term::Terminal>) {
(
&mut self.renderer,
self.tabs.get_active().unwrap().terminal(),
)
}
}
impl X11TerminalWindow {
@ -284,49 +304,6 @@ impl X11TerminalWindow {
self.paint()
}
pub fn paint(&mut self) -> Result<(), Error> {
let tab = match self.tabs.get_active() {
Some(tab) => tab,
None => return Ok(()),
};
let mut target = self.host.window.draw();
let res = self.renderer.paint(&mut target, &mut tab.terminal());
// Ensure that we finish() the target before we let the
// error bubble up, otherwise we lose the context.
target
.finish()
.expect("target.finish failed and we don't know how to recover");
// The only error we want to catch is texture space related;
// when that happens we need to blow our glyph cache and
// allocate a newer bigger texture.
match res {
Err(err) => {
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
eprintln!("out of texture space, allocating {}", size);
self.renderer.recreate_atlas(&self.host.window, size)?;
tab.terminal().make_all_lines_dirty();
// Recursively initiate a new paint
return self.paint();
}
Err(err)
}
Ok(_) => Ok(()),
}
}
pub fn paint_if_needed(&mut self) -> Result<(), Error> {
let tab = match self.tabs.get_active() {
Some(tab) => tab,
None => return Ok(()),
};
if tab.terminal().has_dirty_lines() {
self.paint()?;
}
Ok(())
}
pub fn tabs<'a>(&'a self) -> &'a Tabs {
&self.tabs
}
@ -536,12 +513,4 @@ impl X11TerminalWindow {
Ok(tab_id)
}
pub fn activate_tab_relative(&mut self, delta: isize) -> Result<(), Error> {
let max = self.tabs.len();
let active = self.tabs.get_active_idx() as isize;
let tab = active + delta;
let tab = if tab < 0 { max as isize + tab } else { tab };
self.activate_tab(tab as usize % max)
}
}