mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
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 }
This commit is contained in:
parent
fd410f9ec8
commit
8a0b1d9c3f
9 changed files with 149 additions and 49 deletions
|
@ -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 }
|
||||
|
|
|
@ -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~" }
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
24
src/input.rs
24
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 {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue