1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-21 19:58:15 +03:00

Render cursor and selection for resized lines

If the user enlarges the terminal we can have regions of the vertex
buffer that have colors that default to alpha channel 0.  This is
normally fine but breaks rendering of the cursor and the selection;
those attributes are out of band from the normal cell attributes,
especially for whitespace cells, so we need to handle those in
the degenerate case at the end of a line render.

Refactor the code that computes the cursor and selection colors
so that we can call it and use it in both places.
This commit is contained in:
Wez Furlong 2018-02-19 21:29:27 -08:00
parent d55d5855a5
commit 279b2018fd
2 changed files with 70 additions and 29 deletions

View File

@ -16,6 +16,7 @@ use std::rc::Rc;
use std::slice;
use term::{self, CursorPosition, KeyCode, KeyModifiers, Line, MouseButton, MouseEvent,
MouseEventKind, TerminalHost, Underline};
use term::color::RgbaTuple;
use term::hyperlink::Hyperlink;
use xcb;
use xcb_util;
@ -1000,24 +1001,14 @@ impl<'a> TerminalWindow<'a> {
}
last_cell_idx = cell_idx;
let selected = term::in_range(cell_idx, &selection);
let is_cursor = line_idx as i64 == cursor.y && cursor.x == cell_idx;
let (glyph_color, bg_color) = match (selected, is_cursor) {
// Normally, render the cell as configured
(false, false) => (glyph_color, bg_color),
// Cursor cell always renders with background over cursor color
(_, true) => (
self.palette.background.to_linear_tuple_rgba(),
self.palette.cursor.to_linear_tuple_rgba(),
),
// Selection text colors the background
(true, false) => (
glyph_color,
// TODO: configurable selection color
self.palette.cursor.to_linear_tuple_rgba(),
),
};
let (glyph_color, bg_color) = self.compute_cell_fg_bg(
line_idx,
cell_idx,
&cursor,
&selection,
glyph_color,
bg_color,
);
let vert_idx = cell_idx * VERTICES_PER_CELL;
let vert = &mut vertices[vert_idx..vert_idx + VERTICES_PER_CELL];
@ -1104,20 +1095,67 @@ impl<'a> TerminalWindow<'a> {
// open a vim split horizontally. Backgrounding vim would leave
// the right pane with its prior contents instead of showing the
// cleared lines from the shell in the main screen.
let bg_color = self.palette.background.to_linear_tuple_rgba();
let vert_idx = (last_cell_idx + 1) * VERTICES_PER_CELL;
let vert_slice = &mut vertices[vert_idx..];
for vert in vert_slice.iter_mut() {
vert.bg_color = bg_color;
vert.underline = U_NONE;
vert.tex = (0.0, 0.0);
vert.adjust = Default::default();
vert.has_color = 0.0;
for cell_idx in last_cell_idx + 1..num_cols {
let vert_idx = cell_idx * VERTICES_PER_CELL;
let vert_slice = &mut vertices[vert_idx..vert_idx + 4];
// Even though we don't have a cell for these, they still
// hold the cursor or the selection so we need to compute
// the colors in the usual way.
let (glyph_color, bg_color) = self.compute_cell_fg_bg(
line_idx,
cell_idx,
&cursor,
&selection,
self.palette.foreground.to_linear_tuple_rgba(),
self.palette.background.to_linear_tuple_rgba(),
);
for vert in vert_slice.iter_mut() {
vert.bg_color = bg_color;
vert.fg_color = glyph_color;
vert.underline = U_NONE;
vert.tex = (0.0, 0.0);
vert.adjust = Default::default();
vert.has_color = 0.0;
}
}
Ok(())
}
fn compute_cell_fg_bg(
&self,
line_idx: usize,
cell_idx: usize,
cursor: &CursorPosition,
selection: &Range<usize>,
fg_color: RgbaTuple,
bg_color: RgbaTuple,
) -> (RgbaTuple, RgbaTuple) {
let selected = term::in_range(cell_idx, &selection);
let is_cursor = line_idx as i64 == cursor.y && cursor.x == cell_idx;
let (fg_color, bg_color) = match (selected, is_cursor) {
// Normally, render the cell as configured
(false, false) => (fg_color, bg_color),
// Cursor cell always renders with background over cursor color
(_, true) => (
self.palette.background.to_linear_tuple_rgba(),
self.palette.cursor.to_linear_tuple_rgba(),
),
// Selection text colors the background
(true, false) => (
fg_color,
// TODO: configurable selection color
self.palette.cursor.to_linear_tuple_rgba(),
),
};
(fg_color, bg_color)
}
pub fn paint(&mut self) -> Result<(), Error> {
let mut target = self.host.window.draw();
let res = self.do_paint(&mut target);

View File

@ -34,6 +34,9 @@ pub struct RgbColor {
pub blue: u8,
}
pub type RgbTuple = (f32, f32, f32);
pub type RgbaTuple = (f32, f32, f32, f32);
impl RgbColor {
/// Construct a color from discrete red, green, blue values
/// in the range 0-255.
@ -45,11 +48,11 @@ impl RgbColor {
palette::Rgba::new_u8(self.red, self.green, self.blue, 0xff)
}
pub fn to_linear_tuple_rgb(&self) -> (f32, f32, f32) {
pub fn to_linear_tuple_rgb(&self) -> RgbTuple {
self.to_linear().to_pixel()
}
pub fn to_linear_tuple_rgba(&self) -> (f32, f32, f32, f32) {
pub fn to_linear_tuple_rgba(&self) -> RgbaTuple {
self.to_linear().to_pixel()
}