diff options
author | Dan Aloni <alonid@gmail.com> | 2017-10-14 20:35:56 +0300 |
---|---|---|
committer | Joe Wilm <jwilm@users.noreply.github.com> | 2017-10-14 10:35:56 -0700 |
commit | 8a0b1d9c3f5a9ddb98469a340bbcd06374d4a24e (patch) | |
tree | 80768003f9a2f3c99b0238dc68f4c9b119cc77d6 | |
parent | fd410f9ec8bc53e35d46cc213244c978ef7c5816 (diff) | |
download | alacritty-8a0b1d9c3f5a9ddb98469a340bbcd06374d4a24e.tar.gz alacritty-8a0b1d9c3f5a9ddb98469a340bbcd06374d4a24e.zip |
Implement user actions for font resize (#625)
Adds support for font resizing at run-time. Three new actions are
introduced:
* IncreaseFontSize - Increases current font size by 1.0
* DecreaseFontSize - Decreases current font size by 1.0
* ResetFontSize - Resets font size to that specified in the
configuration.
The stock config files have example configuration for each which should
match gnome-terminal. For convenience, the config entries are:
- { key: Key0, mods: Control, action: ResetFontSize }
- { key: Equals, mods: Control, action: IncreaseFontSize }
- { key: Subtract, mods: Control, action: DecreaseFontSize }
-rw-r--r-- | alacritty.yml | 3 | ||||
-rw-r--r-- | alacritty_macos.yml | 3 | ||||
-rw-r--r-- | src/config.rs | 21 | ||||
-rw-r--r-- | src/display.rs | 98 | ||||
-rw-r--r-- | src/event.rs | 8 | ||||
-rw-r--r-- | src/input.rs | 24 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/renderer/mod.rs | 5 | ||||
-rw-r--r-- | src/term/mod.rs | 34 |
9 files changed, 149 insertions, 49 deletions
diff --git a/alacritty.yml b/alacritty.yml index c5684397..f69640da 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -215,6 +215,9 @@ key_bindings: - { key: Q, mods: Command, action: Quit } - { key: W, mods: Command, action: Quit } - { key: Insert, mods: Shift, action: PasteSelection } + - { key: Key0, mods: Control, action: ResetFontSize } + - { key: Equals, mods: Control, action: IncreaseFontSize } + - { key: Subtract, mods: Control, action: DecreaseFontSize } - { key: Home, chars: "\x1bOH", mode: AppCursor } - { key: Home, chars: "\x1b[H", mode: ~AppCursor } - { key: End, chars: "\x1bOF", mode: AppCursor } diff --git a/alacritty_macos.yml b/alacritty_macos.yml index 1a16a8c9..61f53868 100644 --- a/alacritty_macos.yml +++ b/alacritty_macos.yml @@ -196,6 +196,9 @@ key_bindings: - { key: Home, chars: "\x1b[H", mode: ~AppCursor } - { key: End, chars: "\x1bOF", mode: AppCursor } - { key: End, chars: "\x1b[F", mode: ~AppCursor } + - { key: Key0, mods: Control, action: ResetFontSize } + - { key: Equals, mods: Control, action: IncreaseFontSize } + - { key: Subtract, mods: Control, action: DecreaseFontSize } - { key: PageUp, mods: Shift, chars: "\x1b[5;2~" } - { key: PageUp, mods: Control, chars: "\x1b[5;5~" } - { key: PageUp, chars: "\x1b[5~" } diff --git a/src/config.rs b/src/config.rs index 4dffa70a..a310ff81 100644 --- a/src/config.rs +++ b/src/config.rs @@ -409,6 +409,9 @@ impl<'a> de::Deserialize<'a> for ActionWrapper { "Paste" => Action::Paste, "Copy" => Action::Copy, "PasteSelection" => Action::PasteSelection, + "IncreaseFontSize" => Action::IncreaseFontSize, + "DecreaseFontSize" => Action::DecreaseFontSize, + "ResetFontSize" => Action::ResetFontSize, "Quit" => Action::Quit, _ => return Err(E::invalid_value(Unexpected::Str(value), &self)), })) @@ -1298,7 +1301,7 @@ impl DeserializeFromF32 for Size { /// field in this struct. It might be nice in the future to have defaults for /// each value independently. Alternatively, maybe erroring when the user /// doesn't provide complete config is Ok. -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] pub struct Font { /// Font family pub normal: FontDescription, @@ -1311,7 +1314,7 @@ pub struct Font { // Font size in points #[serde(deserialize_with="DeserializeFromF32::deserialize_from_f32")] - size: Size, + pub size: Size, /// Extra spacing per character offset: Delta, @@ -1333,7 +1336,7 @@ fn default_italic_desc() -> FontDescription { } /// Description of a single font -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] pub struct FontDescription { pub family: String, pub style: Option<String>, @@ -1366,6 +1369,18 @@ impl Font { pub fn glyph_offset(&self) -> &Delta { &self.glyph_offset } + + /// Get a font clone with a size modification + pub fn with_size_delta(self, delta: f32) -> Font { + let mut new_size = self.size.as_f32_pts() + delta; + if new_size < 1.0 { + new_size = 1.0; + } + Font { + size : Size::new(new_size), + .. self + } + } } #[cfg(target_os = "macos")] diff --git a/src/display.rs b/src/display.rs index cb5cf8c9..25318f0e 100644 --- a/src/display.rs +++ b/src/display.rs @@ -96,6 +96,7 @@ pub struct Display { rx: mpsc::Receiver<(u32, u32)>, tx: mpsc::Sender<(u32, u32)>, meter: Meter, + font_size_modifier: i8, size_info: SizeInfo, last_background_color: Rgb, } @@ -133,7 +134,6 @@ impl Display { options: &cli::Options, ) -> Result<Display, Error> { // Extract some properties from config - let font = config.font(); let render_timer = config.render_timer(); // Create the window where Alacritty will be displayed @@ -146,39 +146,17 @@ impl Display { info!("device_pixel_ratio: {}", dpr); - let rasterizer = font::Rasterizer::new(dpr, config.use_thin_strokes())?; - // Create renderer let mut renderer = QuadRenderer::new(&config, size)?; - // Initialize glyph cache - let glyph_cache = { - info!("Initializing glyph cache"); - let init_start = ::std::time::Instant::now(); - - let cache = renderer.with_loader(|mut api| { - GlyphCache::new(rasterizer, config, &mut api) - })?; - - let stop = init_start.elapsed(); - let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64; - info!("Finished initializing glyph cache in {}", stop_f); - - cache - }; - - // Need font metrics to resize the window properly. This suggests to me the - // font metrics should be computed before creating the window in the first - // place so that a resize is not needed. - let metrics = glyph_cache.font_metrics(); - let cell_width = (metrics.average_advance + font.offset().x as f64) as u32; - let cell_height = (metrics.line_height + font.offset().y as f64) as u32; + let (glyph_cache, cell_width, cell_height) = + Self::new_glyph_cache(&window, &mut renderer, config, 0)?; // Resize window to specified dimensions let dimensions = options.dimensions() .unwrap_or_else(|| config.dimensions()); - let width = cell_width * dimensions.columns_u32(); - let height = cell_height * dimensions.lines_u32(); + let width = cell_width as u32 * dimensions.columns_u32(); + let height = cell_height as u32 * dimensions.lines_u32(); let size = Size { width: Pixels(width), height: Pixels(height) }; info!("set_inner_size: {}", size); @@ -222,11 +200,56 @@ impl Display { tx: tx, rx: rx, meter: Meter::new(), + font_size_modifier: 0, size_info: size_info, last_background_color: background_color, }) } + fn new_glyph_cache(window : &Window, renderer : &mut QuadRenderer, + config: &Config, font_size_delta: i8) + -> Result<(GlyphCache, f32, f32), Error> + { + let font = config.font().clone().with_size_delta(font_size_delta as f32); + let dpr = window.hidpi_factor(); + let rasterizer = font::Rasterizer::new(dpr, config.use_thin_strokes())?; + + // Initialize glyph cache + let glyph_cache = { + info!("Initializing glyph cache"); + let init_start = ::std::time::Instant::now(); + + let cache = renderer.with_loader(|mut api| { + GlyphCache::new(rasterizer, &font, &mut api) + })?; + + let stop = init_start.elapsed(); + let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64; + info!("Finished initializing glyph cache in {}", stop_f); + + cache + }; + + // Need font metrics to resize the window properly. This suggests to me the + // font metrics should be computed before creating the window in the first + // place so that a resize is not needed. + let metrics = glyph_cache.font_metrics(); + let cell_width = (metrics.average_advance + font.offset().x as f64) as u32; + let cell_height = (metrics.line_height + font.offset().y as f64) as u32; + + return Ok((glyph_cache, cell_width as f32, cell_height as f32)); + } + + pub fn update_glyph_cache(&mut self, config: &Config, font_size_delta: i8) + { + let (glyph_cache, cell_width, cell_height) = + Self::new_glyph_cache(&self.window, + &mut self.renderer, config, font_size_delta).unwrap(); + self.glyph_cache = glyph_cache; + self.size_info.cell_width = cell_width; + self.size_info.cell_height = cell_height; + } + #[inline] pub fn resize_channel(&self) -> mpsc::Sender<(u32, u32)> { self.tx.clone() @@ -240,6 +263,7 @@ impl Display { pub fn handle_resize( &mut self, terminal: &mut MutexGuard<Term>, + config: &Config, items: &mut [&mut OnResize] ) { // Resize events new_size and are handled outside the poll_events @@ -252,11 +276,27 @@ impl Display { new_size = Some(sz); } + if terminal.font_size_modifier != self.font_size_modifier { + // Font size modification detected + + self.font_size_modifier = terminal.font_size_modifier; + self.update_glyph_cache(config, terminal.font_size_modifier); + + if new_size == None { + // Force a resize to refresh things + new_size = Some((self.size_info.width as u32, + self.size_info.height as u32)); + } + } + // Receive any resize events; only call gl::Viewport on last // available if let Some((w, h)) = new_size.take() { - terminal.resize(w as f32, h as f32); - let size = terminal.size_info(); + self.size_info.width = w as f32; + self.size_info.height = h as f32; + + let size = &self.size_info; + terminal.resize(size); for item in items { item.on_resize(size) diff --git a/src/event.rs b/src/event.rs index 95685001..dda18652 100644 --- a/src/event.rs +++ b/src/event.rs @@ -107,6 +107,14 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> { self.terminal.pixels_to_coords(self.mouse.x as usize, self.mouse.y as usize) } + fn change_font_size(&mut self, delta: i8) { + self.terminal.change_font_size(delta); + } + + fn reset_font_size(&mut self) { + self.terminal.reset_font_size(); + } + #[inline] fn mouse_mut(&mut self) -> &mut Mouse { self.mouse diff --git a/src/input.rs b/src/input.rs index 4be7dac5..7378e8dc 100644 --- a/src/input.rs +++ b/src/input.rs @@ -62,6 +62,8 @@ pub trait ActionContext { fn received_count(&mut self) -> &mut usize; fn suppress_chars(&mut self) -> &mut bool; fn last_modifiers(&mut self) -> &mut ModifiersState; + fn change_font_size(&mut self, delta: i8); + fn reset_font_size(&mut self); } /// Describes a state and action to take in that state @@ -154,6 +156,15 @@ pub enum Action { /// Paste contents of selection buffer PasteSelection, + /// Increase font size + IncreaseFontSize, + + /// Decrease font size + DecreaseFontSize, + + /// Reset font size to the config value + ResetFontSize, + /// Run given command Command(String, Vec<String>), @@ -202,6 +213,15 @@ impl Action { // FIXME should do a more graceful shutdown ::std::process::exit(0); }, + Action::IncreaseFontSize => { + ctx.change_font_size(1); + }, + Action::DecreaseFontSize => { + ctx.change_font_size(-1); + } + Action::ResetFontSize => { + ctx.reset_font_size(); + } } } @@ -593,6 +613,10 @@ mod tests { fn last_modifiers(&mut self) -> &mut ModifiersState { &mut self.last_modifiers } + fn change_font_size(&mut self, _delta: i8) { + } + fn reset_font_size(&mut self) { + } } macro_rules! test_clickstate { diff --git a/src/main.rs b/src/main.rs index ec327009..ca7a40c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -188,7 +188,7 @@ fn run(mut config: Config, options: cli::Options) -> Result<(), Box<Error>> { // // The second argument is a list of types that want to be notified // of display size changes. - display.handle_resize(&mut terminal, &mut [&mut pty, &mut processor]); + display.handle_resize(&mut terminal, &config, &mut [&mut pty, &mut processor]); // Draw the current state of the terminal display.draw(terminal, &config, processor.selection.as_ref()); diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 9ce690ca..9e6036d4 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -29,7 +29,7 @@ use gl; use index::{Line, Column, RangeInclusive}; use notify::{Watcher, watcher, RecursiveMode, DebouncedEvent}; -use config::{self, Config, Delta}; +use config::{self, Config, Font, Delta}; use term::{self, cell, RenderableCell}; use window::{Size, Pixels}; @@ -170,12 +170,11 @@ pub struct GlyphCache { impl GlyphCache { pub fn new<L>( mut rasterizer: Rasterizer, - config: &Config, + font: &Font, loader: &mut L ) -> Result<GlyphCache, font::Error> where L: LoadGlyph { - let font = config.font(); let size = font.size(); let glyph_offset = *font.glyph_offset(); diff --git a/src/term/mod.rs b/src/term/mod.rs index f9bd5541..a16971b5 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -655,6 +655,9 @@ pub struct Term { /// Scroll region scroll_region: Range<Line>, + /// Font size modifier + pub font_size_modifier: i8, + /// Size size_info: SizeInfo, @@ -767,6 +770,7 @@ impl Term { grid: grid, alt_grid: alt, alt: false, + font_size_modifier: 0, active_charset: Default::default(), cursor: Default::default(), cursor_save: Default::default(), @@ -783,6 +787,18 @@ impl Term { } } + pub fn change_font_size(&mut self, delta: i8) { + if let Some(sum) = self.font_size_modifier.checked_add(delta) { + self.font_size_modifier = sum; + self.dirty = true; + } + } + + pub fn reset_font_size(&mut self) { + self.font_size_modifier = 0; + self.dirty = true; + } + pub fn update_config(&mut self, config: &Config) { self.semantic_escape_chars = config.selection().semantic_escape_chars.clone(); self.original_colors.fill_named(config.colors()); @@ -965,30 +981,22 @@ impl Term { } /// Resize terminal to new dimensions - pub fn resize(&mut self, width: f32, height: f32) { + pub fn resize(&mut self, size : &SizeInfo) { debug!("Term::resize"); + // Bounds check; lots of math assumes width and height are > 0 - if width as usize <= 2 * self.size_info.padding_x as usize || - height as usize <= 2 * self.size_info.padding_y as usize + if size.width as usize <= 2 * self.size_info.padding_x as usize || + size.height as usize <= 2 * self.size_info.padding_y as usize { return; } - let size = SizeInfo { - width: width, - height: height, - cell_width: self.size_info.cell_width, - cell_height: self.size_info.cell_height, - padding_x: self.size_info.padding_x, - padding_y: self.size_info.padding_y, - }; - let old_cols = self.grid.num_cols(); let old_lines = self.grid.num_lines(); let mut num_cols = size.cols(); let mut num_lines = size.lines(); - self.size_info = size; + self.size_info = *size; if old_cols == num_cols && old_lines == num_lines { debug!("Term::resize dimensions unchanged"); |