mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 21:32:13 +03:00
add window padding options
@jsgf suggested that it would be nice to have a degree of padding around the terminal cells. This commit adds some plumbing for this; ``` [window_padding] left = 10 top = 0 right = 10 bottom = 0 ``` The left and top padding are used top compute the top-left coordinates of the terminal cells. The right and bottom padding act as minimum values; the actual padding used may be larger depending on the size of the window and the number of cells that fit the available space. top padding > 0 and the tab bar needs some work.
This commit is contained in:
parent
3e3bfcb4d7
commit
5eeed56b1a
@ -426,6 +426,18 @@ pub struct Config {
|
||||
/// The default is true.
|
||||
#[serde(default = "default_true")]
|
||||
pub enable_wayland: bool,
|
||||
|
||||
/// Controls the amount of padding to use around the terminal cell area
|
||||
#[serde(default)]
|
||||
pub window_padding: WindowPadding,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Clone, Copy, Debug)]
|
||||
pub struct WindowPadding {
|
||||
pub left: u16,
|
||||
pub top: u16,
|
||||
pub right: u16,
|
||||
pub bottom: u16,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::glyphcache::{CachedGlyph, GlyphCache};
|
||||
use super::utilsprites::{RenderMetrics, UtilSprites};
|
||||
use crate::config::TextStyle;
|
||||
use crate::config::{configuration, TextStyle};
|
||||
use crate::font::{FontConfiguration, GlyphInfo};
|
||||
use ::window::bitmaps::ImageTexture;
|
||||
use ::window::glium::backend::Context as GliumContext;
|
||||
@ -121,7 +121,7 @@ impl OpenGLRenderState {
|
||||
|
||||
/// Compute a vertex buffer to hold the quads that comprise the visible
|
||||
/// portion of the screen. We recreate this when the screen is resized.
|
||||
/// The idea is that we want to minimize and heavy lifting and computation
|
||||
/// The idea is that we want to minimize any heavy lifting and computation
|
||||
/// and instead just poke some attributes into the offset that corresponds
|
||||
/// to a changed cell when we need to repaint the screen, and then just
|
||||
/// let the GPU figure out the rest.
|
||||
@ -136,21 +136,33 @@ impl OpenGLRenderState {
|
||||
let mut verts = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
|
||||
let num_cols = width as usize / cell_width as usize;
|
||||
let num_rows = height as usize / cell_height as usize;
|
||||
let config = configuration();
|
||||
let avail_width = (width as usize)
|
||||
.saturating_sub((config.window_padding.left + config.window_padding.right) as usize);
|
||||
let avail_height = (height as usize)
|
||||
.saturating_sub((config.window_padding.top + config.window_padding.bottom) as usize);
|
||||
|
||||
let num_cols = avail_width as usize / cell_width as usize;
|
||||
let num_rows = avail_height as usize / cell_height as usize;
|
||||
|
||||
let padding_left = config.window_padding.left as f32;
|
||||
let padding_top = config.window_padding.top as f32;
|
||||
|
||||
log::debug!(
|
||||
"compute_vertices {}x{} {}x{}",
|
||||
"compute_vertices {}x{} {}x{} padding={} {}",
|
||||
num_cols,
|
||||
num_rows,
|
||||
width,
|
||||
height
|
||||
height,
|
||||
padding_left,
|
||||
padding_top
|
||||
);
|
||||
|
||||
for y in 0..num_rows {
|
||||
let y_pos = (height / -2.0) + (y as f32 * cell_height) + padding_top;
|
||||
for x in 0..num_cols {
|
||||
let y_pos = (height / -2.0) + (y as f32 * cell_height);
|
||||
let x_pos = (width / -2.0) + (x as f32 * cell_width);
|
||||
let x_pos = (width / -2.0) + (x as f32 * cell_width) + padding_left;
|
||||
|
||||
// Remember starting index for this position
|
||||
let idx = verts.len() as u32;
|
||||
verts.push(Vertex {
|
||||
|
@ -19,6 +19,7 @@ use anyhow::{anyhow, bail, ensure};
|
||||
use portable_pty::PtySize;
|
||||
use std::any::Any;
|
||||
use std::ops::Range;
|
||||
use std::ops::Sub;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use term::color::ColorPalette;
|
||||
@ -51,7 +52,10 @@ impl term::Clipboard for ClipboardHelper {
|
||||
pub struct TermWindow {
|
||||
window: Option<Window>,
|
||||
fonts: Rc<FontConfiguration>,
|
||||
/// Window dimensions and dpi
|
||||
dimensions: Dimensions,
|
||||
/// Terminal dimensions
|
||||
terminal_size: PtySize,
|
||||
mux_window_id: MuxWindowId,
|
||||
render_metrics: RenderMetrics,
|
||||
render_state: RenderState,
|
||||
@ -149,8 +153,19 @@ impl WindowCallbacks for TermWindow {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let x = (event.coords.x.max(0) / self.render_metrics.cell_size.width) as usize;
|
||||
let y = (event.coords.y.max(0) / self.render_metrics.cell_size.height) as i64;
|
||||
let config = configuration();
|
||||
let x = (event
|
||||
.coords
|
||||
.x
|
||||
.sub(config.window_padding.left as isize)
|
||||
.max(0)
|
||||
/ self.render_metrics.cell_size.width) as usize;
|
||||
let y = (event
|
||||
.coords
|
||||
.y
|
||||
.sub(config.window_padding.top as isize)
|
||||
.max(0)
|
||||
/ self.render_metrics.cell_size.height) as i64;
|
||||
|
||||
let first_line_offset = if self.show_tab_bar { 1 } else { 0 };
|
||||
self.last_mouse_coords = (x, y);
|
||||
@ -390,17 +405,32 @@ impl TermWindow {
|
||||
|
||||
let render_metrics = RenderMetrics::new(fontconfig);
|
||||
|
||||
let width = render_metrics.cell_size.width as usize * physical_cols;
|
||||
let height = render_metrics.cell_size.height as usize
|
||||
* (physical_rows + if config.enable_tab_bar { 1 } else { 0 });
|
||||
let terminal_size = PtySize {
|
||||
rows: physical_rows as u16,
|
||||
cols: physical_cols as u16,
|
||||
pixel_width: (render_metrics.cell_size.width as usize * physical_cols) as u16,
|
||||
pixel_height: (render_metrics.cell_size.height as usize * physical_rows) as u16,
|
||||
};
|
||||
|
||||
let rows_with_tab_bar = if config.enable_tab_bar { 1 } else { 0 } + terminal_size.rows;
|
||||
// Accomodating future scroll bar UI
|
||||
let cols_with_scroll_bar = terminal_size.cols;
|
||||
|
||||
let dimensions = Dimensions {
|
||||
pixel_width: ((cols_with_scroll_bar * render_metrics.cell_size.width as u16)
|
||||
+ config.window_padding.left
|
||||
+ config.window_padding.right) as usize,
|
||||
pixel_height: ((rows_with_tab_bar * render_metrics.cell_size.height as u16)
|
||||
+ config.window_padding.top
|
||||
+ config.window_padding.bottom) as usize,
|
||||
dpi: config.dpi as usize,
|
||||
};
|
||||
|
||||
log::info!(
|
||||
"TermWindow::new_window called with mux_window_id {} {}x{} cells, {}x{}",
|
||||
"TermWindow::new_window called with mux_window_id {} {:?} {:?}",
|
||||
mux_window_id,
|
||||
physical_cols,
|
||||
physical_rows,
|
||||
width,
|
||||
height
|
||||
terminal_size,
|
||||
dimensions
|
||||
);
|
||||
|
||||
const ATLAS_SIZE: usize = 4096;
|
||||
@ -413,21 +443,15 @@ impl TermWindow {
|
||||
let window = Window::new_window(
|
||||
"wezterm",
|
||||
"wezterm",
|
||||
width,
|
||||
height,
|
||||
dimensions.pixel_width,
|
||||
dimensions.pixel_height,
|
||||
Box::new(Self {
|
||||
window: None,
|
||||
mux_window_id,
|
||||
fonts: Rc::clone(fontconfig),
|
||||
render_metrics,
|
||||
dimensions: Dimensions {
|
||||
pixel_width: width,
|
||||
pixel_height: height,
|
||||
// This is the default dpi; we'll get a resize
|
||||
// event to inform us of the true dpi if it is
|
||||
// different from this value
|
||||
dpi: 96,
|
||||
},
|
||||
dimensions,
|
||||
terminal_size,
|
||||
render_state,
|
||||
keys: KeyMap::new(),
|
||||
show_tab_bar: config.enable_tab_bar,
|
||||
@ -664,7 +688,7 @@ impl TermWindow {
|
||||
_ => return,
|
||||
};
|
||||
let new_tab_bar = TabBarState::new(
|
||||
self.dimensions.pixel_width / self.render_metrics.cell_size.width as usize,
|
||||
self.terminal_size.cols as usize,
|
||||
if self.last_mouse_coords.1 == 0 {
|
||||
Some(self.last_mouse_coords.0)
|
||||
} else {
|
||||
@ -711,10 +735,13 @@ impl TermWindow {
|
||||
let term = tab.renderer();
|
||||
let cursor = term.get_cursor_position();
|
||||
if let Some(win) = self.window.as_ref() {
|
||||
let config = configuration();
|
||||
let r = Rect::new(
|
||||
Point::new(
|
||||
cursor.x.max(0) as isize * self.render_metrics.cell_size.width,
|
||||
cursor.y.max(0) as isize * self.render_metrics.cell_size.height,
|
||||
cursor.x.sub(config.window_padding.left as usize).max(0) as isize
|
||||
* self.render_metrics.cell_size.width,
|
||||
cursor.y.sub(config.window_padding.top as i64).max(0) as isize
|
||||
* self.render_metrics.cell_size.height,
|
||||
),
|
||||
self.render_metrics.cell_size,
|
||||
);
|
||||
@ -755,23 +782,7 @@ impl TermWindow {
|
||||
}
|
||||
|
||||
fn spawn_tab(&mut self, domain: &SpawnTabDomain) -> anyhow::Result<TabId> {
|
||||
let rows =
|
||||
(self.dimensions.pixel_height as usize) / self.render_metrics.cell_size.height as usize;
|
||||
let cols =
|
||||
(self.dimensions.pixel_width as usize) / self.render_metrics.cell_size.width as usize;
|
||||
let tab_bar_adjusted_rows = if self.show_tab_bar {
|
||||
rows.saturating_sub(1)
|
||||
} else {
|
||||
rows
|
||||
};
|
||||
|
||||
let size = portable_pty::PtySize {
|
||||
rows: tab_bar_adjusted_rows as u16,
|
||||
cols: cols as u16,
|
||||
pixel_width: self.dimensions.pixel_width as u16,
|
||||
pixel_height: self.dimensions.pixel_height as u16,
|
||||
};
|
||||
|
||||
let size = self.terminal_size;
|
||||
let mux = Mux::get().unwrap();
|
||||
|
||||
let domain = match domain {
|
||||
@ -910,47 +921,65 @@ impl TermWindow {
|
||||
// final size, which in that case should result in a NOP
|
||||
// change to the tab size.
|
||||
|
||||
let size = if let Some(cell_dims) = scale_changed_cells {
|
||||
PtySize {
|
||||
let config = configuration();
|
||||
|
||||
let (size, dims) = if let Some(cell_dims) = scale_changed_cells {
|
||||
// Scaling preserves existing terminal dimensions, yielding a new
|
||||
// overall set of window dimensions
|
||||
let size = PtySize {
|
||||
rows: cell_dims.rows as u16,
|
||||
cols: cell_dims.cols as u16,
|
||||
pixel_height: cell_dims.rows as u16 * self.render_metrics.cell_size.height as u16,
|
||||
pixel_width: cell_dims.cols as u16 * self.render_metrics.cell_size.width as u16,
|
||||
}
|
||||
} else {
|
||||
PtySize {
|
||||
rows: dimensions.pixel_height as u16 / self.render_metrics.cell_size.height as u16,
|
||||
cols: dimensions.pixel_width as u16 / self.render_metrics.cell_size.width as u16,
|
||||
pixel_height: dimensions.pixel_height as u16,
|
||||
pixel_width: dimensions.pixel_width as u16,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let (size, pixel_height_including_tab_bar) = if self.show_tab_bar {
|
||||
let pixel_height_including_tab_bar = size.pixel_height;
|
||||
let rows = size.rows.saturating_sub(1);
|
||||
let height = self.render_metrics.cell_size.height as u16 * rows;
|
||||
(
|
||||
PtySize {
|
||||
rows,
|
||||
cols: size.cols,
|
||||
pixel_height: height,
|
||||
pixel_width: size.pixel_width,
|
||||
},
|
||||
pixel_height_including_tab_bar,
|
||||
)
|
||||
let rows = size.rows + if self.show_tab_bar { 1 } else { 0 };
|
||||
let cols = size.cols;
|
||||
|
||||
let pixel_height = (rows * self.render_metrics.cell_size.height as u16)
|
||||
+ (config.window_padding.top + config.window_padding.bottom);
|
||||
|
||||
let pixel_width = (cols * self.render_metrics.cell_size.width as u16)
|
||||
+ (config.window_padding.left + config.window_padding.right);
|
||||
|
||||
let dims = Dimensions {
|
||||
pixel_width: pixel_width as usize,
|
||||
pixel_height: pixel_height as usize,
|
||||
dpi: dimensions.dpi,
|
||||
};
|
||||
|
||||
(size, dims)
|
||||
} else {
|
||||
(size, size.pixel_height)
|
||||
// Resize of the window dimensions may result in changed terminal dimensions
|
||||
let avail_width = dimensions.pixel_width
|
||||
- (config.window_padding.left + config.window_padding.right) as usize;
|
||||
let avail_height = dimensions.pixel_height
|
||||
- (config.window_padding.top + config.window_padding.bottom) as usize;
|
||||
|
||||
let rows = (avail_height / self.render_metrics.cell_size.height as usize)
|
||||
.saturating_sub(if self.show_tab_bar { 1 } else { 0 });
|
||||
let cols = avail_width / self.render_metrics.cell_size.width as usize;
|
||||
|
||||
let size = PtySize {
|
||||
rows: rows as u16,
|
||||
cols: cols as u16,
|
||||
pixel_height: avail_height as u16,
|
||||
pixel_width: avail_width as u16,
|
||||
};
|
||||
|
||||
(size, *dimensions)
|
||||
};
|
||||
|
||||
self.render_state
|
||||
.advise_of_window_size_change(
|
||||
&self.render_metrics,
|
||||
size.pixel_width as usize,
|
||||
pixel_height_including_tab_bar as usize,
|
||||
dimensions.pixel_width,
|
||||
dimensions.pixel_height,
|
||||
)
|
||||
.expect("failed to advise of resize");
|
||||
|
||||
self.terminal_size = size;
|
||||
|
||||
let mux = Mux::get().unwrap();
|
||||
if let Some(window) = mux.get_window(self.mux_window_id) {
|
||||
for tab in window.iter() {
|
||||
@ -962,19 +991,17 @@ impl TermWindow {
|
||||
// Queue up a speculative resize in order to preserve the number of rows+cols
|
||||
if let Some(cell_dims) = scale_changed_cells {
|
||||
if let Some(window) = self.window.as_ref() {
|
||||
log::error!("scale changed so resize to {:?}", cell_dims);
|
||||
window.set_inner_size(
|
||||
cell_dims.cols * self.render_metrics.cell_size.width as usize,
|
||||
cell_dims.rows * self.render_metrics.cell_size.height as usize,
|
||||
);
|
||||
log::error!("scale changed so resize to {:?} {:?}", cell_dims, dims);
|
||||
window.set_inner_size(dims.pixel_width, dims.pixel_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn current_cell_dimensions(&self) -> RowsAndCols {
|
||||
let rows = self.dimensions.pixel_height / self.render_metrics.cell_size.height as usize;
|
||||
let cols = self.dimensions.pixel_width / self.render_metrics.cell_size.width as usize;
|
||||
RowsAndCols { rows, cols }
|
||||
RowsAndCols {
|
||||
rows: self.terminal_size.rows as usize,
|
||||
cols: self.terminal_size.cols as usize,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::float_cmp)]
|
||||
@ -1051,10 +1078,13 @@ impl TermWindow {
|
||||
|
||||
term.clean_dirty_lines();
|
||||
|
||||
// Fill any marginal area below the last row
|
||||
// Fill any padding
|
||||
let config = configuration();
|
||||
let bg = rgbcolor_to_window_color(palette.background);
|
||||
// Fill any padding below the last row
|
||||
let (num_rows, _num_cols) = term.physical_dimensions();
|
||||
let pixel_height_of_cells =
|
||||
(num_rows + first_line_offset) * self.render_metrics.cell_size.height as usize;
|
||||
let pixel_height_of_cells = config.window_padding.top as usize
|
||||
+ (num_rows + first_line_offset) * self.render_metrics.cell_size.height as usize;
|
||||
ctx.clear_rect(
|
||||
Rect::new(
|
||||
Point::new(0, pixel_height_of_cells as isize),
|
||||
@ -1066,8 +1096,46 @@ impl TermWindow {
|
||||
.saturating_sub(pixel_height_of_cells)) as isize,
|
||||
),
|
||||
),
|
||||
rgbcolor_to_window_color(palette.background),
|
||||
bg,
|
||||
);
|
||||
|
||||
// top padding
|
||||
ctx.clear_rect(
|
||||
Rect::new(
|
||||
Point::new(0, 0),
|
||||
Size::new(
|
||||
self.dimensions.pixel_width as isize,
|
||||
config.window_padding.top as isize,
|
||||
),
|
||||
),
|
||||
bg,
|
||||
);
|
||||
// left padding
|
||||
ctx.clear_rect(
|
||||
Rect::new(
|
||||
Point::new(0, config.window_padding.top as isize),
|
||||
Size::new(
|
||||
config.window_padding.left as isize,
|
||||
(self.dimensions.pixel_height - config.window_padding.top as usize) as isize,
|
||||
),
|
||||
),
|
||||
bg,
|
||||
);
|
||||
// right padding
|
||||
ctx.clear_rect(
|
||||
Rect::new(
|
||||
Point::new(
|
||||
(self.dimensions.pixel_width - config.window_padding.right as usize) as isize,
|
||||
config.window_padding.top as isize,
|
||||
),
|
||||
Size::new(
|
||||
config.window_padding.right as isize,
|
||||
(self.dimensions.pixel_height - config.window_padding.top as usize) as isize,
|
||||
),
|
||||
),
|
||||
bg,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1429,6 +1497,9 @@ impl TermWindow {
|
||||
) -> anyhow::Result<()> {
|
||||
let config = configuration();
|
||||
|
||||
let padding_left = config.window_padding.left as isize;
|
||||
let padding_top = config.window_padding.top as isize;
|
||||
|
||||
let (_num_rows, num_cols) = terminal.physical_dimensions();
|
||||
let current_highlight = terminal.current_highlight();
|
||||
|
||||
@ -1531,8 +1602,10 @@ impl TermWindow {
|
||||
|
||||
let cell_rect = Rect::new(
|
||||
Point::new(
|
||||
cell_idx as isize * self.render_metrics.cell_size.width,
|
||||
self.render_metrics.cell_size.height * line_idx as isize,
|
||||
(cell_idx as isize * self.render_metrics.cell_size.width)
|
||||
+ padding_left,
|
||||
(self.render_metrics.cell_size.height * line_idx as isize)
|
||||
+ padding_top,
|
||||
),
|
||||
self.render_metrics.cell_size,
|
||||
);
|
||||
@ -1668,7 +1741,8 @@ impl TermWindow {
|
||||
}
|
||||
|
||||
// Fill any marginal area to the right of the last cell
|
||||
let pixel_width_of_cells = num_cols * self.render_metrics.cell_size.width as usize;
|
||||
let pixel_width_of_cells =
|
||||
padding_left as usize + (num_cols * self.render_metrics.cell_size.width as usize);
|
||||
ctx.clear_rect(
|
||||
Rect::new(
|
||||
Point::new(
|
||||
|
Loading…
Reference in New Issue
Block a user