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