Add custom box cursor for unfocused window
This commit is contained in:
parent
8195d71034
commit
fe29b8c687
|
@ -470,8 +470,8 @@ impl Font {
|
|||
let width = self.glyph_advance('0') as i32;
|
||||
// Return the new custom glyph
|
||||
return super::get_underline_cursor_glyph(descent, width);
|
||||
},
|
||||
super::BEAM_CURSOR_CHAR => {
|
||||
}
|
||||
super::BEAM_CURSOR_CHAR | super::BOX_CURSOR_CHAR => {
|
||||
// Get the top of the bounding box
|
||||
let metrics = self.metrics();
|
||||
let height = metrics.line_height;
|
||||
|
@ -483,9 +483,13 @@ impl Font {
|
|||
// Get the width of the cell
|
||||
let width = self.glyph_advance('0') as i32;
|
||||
// Return the new custom glyph
|
||||
return super::get_beam_cursor_glyph(ascent as i32, height as i32, width);
|
||||
},
|
||||
_ => (),
|
||||
if character == super::BEAM_CURSOR_CHAR {
|
||||
return super::get_beam_cursor_glyph(ascent as i32, height as i32, width);
|
||||
} else {
|
||||
return super::get_box_cursor_glyph(ascent as i32, height as i32, width);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let glyph_index = self.glyph_index(character)
|
||||
|
|
|
@ -310,7 +310,7 @@ impl FreeTypeRasterizer {
|
|||
// Return the new custom glyph
|
||||
super::get_underline_cursor_glyph(descent, width)
|
||||
}
|
||||
super::BEAM_CURSOR_CHAR => {
|
||||
super::BEAM_CURSOR_CHAR | super::BOX_CURSOR_CHAR => {
|
||||
// Get the top of the bounding box
|
||||
let size_metrics = face.ft_face
|
||||
.size_metrics()
|
||||
|
@ -326,7 +326,11 @@ impl FreeTypeRasterizer {
|
|||
let width = (metrics.vertAdvance as f32 / 128.).round() as i32;
|
||||
|
||||
// Return the new custom glyph
|
||||
super::get_beam_cursor_glyph(ascent, height, width)
|
||||
if glyph_key.c == super::BEAM_CURSOR_CHAR {
|
||||
super::get_beam_cursor_glyph(ascent, height, width)
|
||||
} else {
|
||||
super::get_box_cursor_glyph(ascent, height, width)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// If it's not a special char, return the normal glyph
|
||||
|
|
|
@ -58,6 +58,9 @@ mod darwin;
|
|||
#[cfg(target_os = "macos")]
|
||||
pub use darwin::*;
|
||||
|
||||
/// Width/Height of the cursor relative to the font width
|
||||
pub const CURSOR_WIDTH_PERCENTAGE: i32 = 15;
|
||||
|
||||
/// Character used for the underline cursor
|
||||
// This is part of the private use area and should not conflict with any font
|
||||
pub const UNDERLINE_CURSOR_CHAR: char = '\u{10a3e2}';
|
||||
|
@ -65,8 +68,10 @@ pub const UNDERLINE_CURSOR_CHAR: char = '\u{10a3e2}';
|
|||
/// Character used for the beam cursor
|
||||
// This is part of the private use area and should not conflict with any font
|
||||
pub const BEAM_CURSOR_CHAR: char = '\u{10a3e3}';
|
||||
/// Width of the beam cursor relative to the font width
|
||||
pub const BEAM_CURSOR_WIDTH_PERCENTAGE: i32 = 15;
|
||||
|
||||
/// Character used for the empty box cursor
|
||||
// This is part of the private use area and should not conflict with any font
|
||||
pub const BOX_CURSOR_CHAR: char = '\u{10a3e4}';
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FontDesc {
|
||||
|
@ -214,9 +219,8 @@ impl Default for RasterizedGlyph {
|
|||
|
||||
// Returns a custom underline cursor character
|
||||
pub fn get_underline_cursor_glyph(descent: i32, width: i32) -> Result<RasterizedGlyph, Error> {
|
||||
// Create a new rectangle, the height is half the distance between
|
||||
// bounding box bottom and the baseline
|
||||
let height = cmp::max(i32::abs(descent / 2), 1);
|
||||
// Create a new rectangle, the height is relative to the font width
|
||||
let height = cmp::max(width * CURSOR_WIDTH_PERCENTAGE / 100, 1);
|
||||
let buf = vec![255u8; (width * height * 3) as usize];
|
||||
|
||||
// Create a custom glyph with the rectangle data attached to it
|
||||
|
@ -237,7 +241,7 @@ pub fn get_beam_cursor_glyph(
|
|||
width: i32,
|
||||
) -> Result<RasterizedGlyph, Error> {
|
||||
// Create a new rectangle that is at least one pixel wide
|
||||
let beam_width = cmp::max(width * BEAM_CURSOR_WIDTH_PERCENTAGE / 100, 1);
|
||||
let beam_width = cmp::max(width * CURSOR_WIDTH_PERCENTAGE / 100, 1);
|
||||
let buf = vec![255u8; (beam_width * height * 3) as usize];
|
||||
|
||||
// Create a custom glyph with the rectangle data attached to it
|
||||
|
@ -251,6 +255,37 @@ pub fn get_beam_cursor_glyph(
|
|||
});
|
||||
}
|
||||
|
||||
// Returns a custom beam cursor character
|
||||
pub fn get_box_cursor_glyph(
|
||||
ascent: i32,
|
||||
height: i32,
|
||||
width: i32,
|
||||
) -> Result<RasterizedGlyph, Error> {
|
||||
// Create a new box outline rectangle
|
||||
let border_width = cmp::max(width * CURSOR_WIDTH_PERCENTAGE / 100, 1);
|
||||
let mut buf = Vec::with_capacity((width * height * 3) as usize);
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
if y < border_width || y >= height - border_width ||
|
||||
x < border_width || x >= width - border_width {
|
||||
buf.append(&mut vec![255u8; 3]);
|
||||
} else {
|
||||
buf.append(&mut vec![0u8; 3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a custom glyph with the rectangle data attached to it
|
||||
return Ok(RasterizedGlyph {
|
||||
c: BOX_CURSOR_CHAR,
|
||||
top: ascent,
|
||||
left: 0,
|
||||
height,
|
||||
width,
|
||||
buf: buf,
|
||||
});
|
||||
}
|
||||
|
||||
struct BufDebugger<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for BufDebugger<'a> {
|
||||
|
|
|
@ -354,6 +354,7 @@ impl Display {
|
|||
//
|
||||
// TODO I wonder if the renderable cells iter could avoid the
|
||||
// mutable borrow
|
||||
let window_focused = self.window.is_focused;
|
||||
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
|
||||
// Clear screen to update whole background with new color
|
||||
if background_color_changed {
|
||||
|
@ -361,7 +362,10 @@ impl Display {
|
|||
}
|
||||
|
||||
// Draw the grid
|
||||
api.render_cells(terminal.renderable_cells(config, selection), glyph_cache);
|
||||
api.render_cells(
|
||||
terminal.renderable_cells(config, selection, window_focused),
|
||||
glyph_cache,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -330,6 +330,7 @@ impl<N: Notify> Processor<N> {
|
|||
processor.ctx.terminal.dirty = true;
|
||||
processor.ctx.terminal.next_is_urgent = Some(false);
|
||||
} else {
|
||||
processor.ctx.terminal.dirty = true;
|
||||
*hide_cursor = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,6 +118,7 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
config: &'b Config,
|
||||
selection: Option<RangeInclusive<index::Linear>>,
|
||||
cursor_style: CursorStyle,
|
||||
window_focused: bool,
|
||||
) -> RenderableCellsIter<'b> {
|
||||
let cursor_index = Linear(cursor.line.0 * grid.num_cols().0 + cursor.col.0);
|
||||
|
||||
|
@ -132,10 +133,15 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
config: config,
|
||||
colors: colors,
|
||||
cursor_cells: ArrayDeque::new(),
|
||||
}.initialize(cursor_style)
|
||||
}.initialize(cursor_style, window_focused)
|
||||
}
|
||||
|
||||
fn populate_block_cursor(&mut self) {
|
||||
fn populate_block_cursor(&mut self, window_focused: bool) {
|
||||
if !window_focused {
|
||||
self.populate_cursor(font::BOX_CURSOR_CHAR, ' ');
|
||||
return;
|
||||
}
|
||||
|
||||
let (text_color, cursor_color) = if self.config.custom_cursor_colors() {
|
||||
(
|
||||
Color::Named(NamedColor::CursorText),
|
||||
|
@ -173,33 +179,14 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
}
|
||||
|
||||
fn populate_beam_cursor(&mut self) {
|
||||
let mut cursor_cell = self.grid[self.cursor];
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
column: self.cursor.col,
|
||||
inner: cursor_cell,
|
||||
});
|
||||
|
||||
let cursor_color = self.text_cursor_color(&cursor_cell);
|
||||
cursor_cell.c = font::BEAM_CURSOR_CHAR;
|
||||
cursor_cell.fg = cursor_color;
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
column: self.cursor.col,
|
||||
inner: cursor_cell,
|
||||
});
|
||||
|
||||
if self.is_wide_cursor(&cursor_cell) {
|
||||
cursor_cell.c = ' ';
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
column: self.cursor.col + 1,
|
||||
inner: cursor_cell,
|
||||
});
|
||||
}
|
||||
self.populate_cursor(font::BEAM_CURSOR_CHAR, ' ');
|
||||
}
|
||||
|
||||
fn populate_underline_cursor(&mut self) {
|
||||
self.populate_cursor(font::UNDERLINE_CURSOR_CHAR, font::UNDERLINE_CURSOR_CHAR);
|
||||
}
|
||||
|
||||
fn populate_cursor(&mut self, cursor: char, wide_cursor: char) {
|
||||
let mut cursor_cell = self.grid[self.cursor];
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
|
@ -208,7 +195,7 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
});
|
||||
|
||||
let cursor_color = self.text_cursor_color(&cursor_cell);
|
||||
cursor_cell.c = font::UNDERLINE_CURSOR_CHAR;
|
||||
cursor_cell.c = cursor;
|
||||
cursor_cell.fg = cursor_color;
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
|
@ -217,6 +204,7 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
});
|
||||
|
||||
if self.is_wide_cursor(&cursor_cell) {
|
||||
cursor_cell.c = wide_cursor;
|
||||
self.cursor_cells.push_back(Indexed {
|
||||
line: self.cursor.line,
|
||||
column: self.cursor.col + 1,
|
||||
|
@ -243,11 +231,11 @@ impl<'a> RenderableCellsIter<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
fn initialize(mut self, cursor_style: CursorStyle) -> Self {
|
||||
fn initialize(mut self, cursor_style: CursorStyle, window_focused: bool) -> Self {
|
||||
if self.cursor_is_visible() {
|
||||
match cursor_style {
|
||||
CursorStyle::Block => {
|
||||
self.populate_block_cursor();
|
||||
self.populate_block_cursor(window_focused);
|
||||
},
|
||||
CursorStyle::Beam => {
|
||||
self.populate_beam_cursor();
|
||||
|
@ -971,6 +959,7 @@ impl Term {
|
|||
&'b self,
|
||||
config: &'b Config,
|
||||
selection: Option<&'b Selection>,
|
||||
window_focused: bool,
|
||||
) -> RenderableCellsIter {
|
||||
let selection = selection.and_then(|s| s.to_span(self))
|
||||
.map(|span| span.to_range());
|
||||
|
@ -983,6 +972,7 @@ impl Term {
|
|||
config,
|
||||
selection,
|
||||
self.cursor_style.unwrap_or(self.default_cursor_style),
|
||||
window_focused,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue