From 22789f35c7ab90a5ada70fdca25ca1c626eb1ca5 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Wed, 29 Jun 2016 10:21:02 -0700 Subject: Implement terminal resizing The resize event is received from glutin on the update thread, but the renderer needs to be informed as well for updating the viewport and projection matrix. This is achieved with an mpsc::channel. To support resizing, the grid now offers methods for growing and shrinking, and there are several implementations available for clear_region based on different Range* types. Core resize logic is all in Term::resize. It attempts to keep as much context as possible when shinking the window. When growing, it's basically just adding rows. --- src/term.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'src/term.rs') diff --git a/src/term.rs b/src/term.rs index c11a0d08..d4168ead 100644 --- a/src/term.rs +++ b/src/term.rs @@ -2,10 +2,21 @@ use std::ops::Range; use ansi::{self, Attr}; -use grid::{self, Grid, CellFlags}; +use grid::{self, Grid, CellFlags, ClearRegion}; use tty; use ::Rgb; +/// coerce val to be between min and max +fn limit(val: T, min: T, max: T) -> T { + if val < min { + min + } else if val > max { + max + } else { + val + } +} + /// tomorrow night bright /// /// because contrast @@ -190,6 +201,67 @@ impl Term { } } + /// Resize terminal to new dimensions + pub fn resize(&mut self, width: f32, height: f32) { + let size = SizeInfo { + width: width, + height: height, + cell_width: self.size_info.cell_width, + cell_height: self.size_info.cell_height, + }; + + let old_cols = self.size_info.cols(); + let old_rows = self.size_info.rows(); + let num_cols = size.cols(); + let num_rows = size.rows(); + + self.size_info = size; + + if old_cols == num_cols && old_rows == num_rows { + return; + } + + // Scroll up to keep cursor and as much context as possible in grid. This only runs when the + // rows decreases. + self.scroll_region = 0..self.grid.num_rows(); + // XXX why is +1 required? + let row_diff = (self.cursor_y() as isize - num_rows as isize) + 1; + if row_diff > 0 { + self.scroll(row_diff); + self.cursor.advance(-row_diff as i64, 0); + } + + println!("num_cols, num_rows = {}, {}", num_cols, num_rows); + + // Resize grids to new size + self.grid.resize(num_rows, num_cols); + self.alt_grid.resize(num_rows, num_cols); + + // Ensure cursor is in-bounds + self.cursor.y = limit(self.cursor.y, 0, num_rows as u16); + self.cursor.x = limit(self.cursor.x, 0, num_cols as u16); + + // Recreate tabs list + self.tabs = (0..self.grid.num_cols()).map(|i| i % TAB_SPACES == 0) + .collect::>(); + + // Make sure bottom of terminal is clear + if row_diff > 0 { + self.grid.clear_region((self.cursor.y as usize)..); + self.alt_grid.clear_region((self.cursor.y as usize)..); + } + + // Reset scrolling region to new size + self.scroll_region = 0..self.grid.num_rows(); + + // Inform tty of new dimensions + self.tty.resize(num_rows, + num_cols, + self.size_info.width as usize, + self.size_info.height as usize); + + } + #[inline] pub fn tty(&self) -> &tty::Tty { &self.tty -- cgit