aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2017-12-10 00:33:58 +0100
committerJoe Wilm <jwilm@users.noreply.github.com>2017-12-24 09:46:54 -0800
commitfe29b8c6873c82517a218067abbf56b64cae413b (patch)
treea2cff4b838448d9e45ed56374db363dbcf724259
parent8195d7103498043270523bd81d703cb678cd11a2 (diff)
downloadalacritty-fe29b8c6873c82517a218067abbf56b64cae413b.tar.gz
alacritty-fe29b8c6873c82517a218067abbf56b64cae413b.zip
Add custom box cursor for unfocused window
-rw-r--r--font/src/darwin/mod.rs14
-rw-r--r--font/src/ft/mod.rs8
-rw-r--r--font/src/lib.rs47
-rw-r--r--src/display.rs6
-rw-r--r--src/event.rs1
-rw-r--r--src/term/mod.rs48
6 files changed, 81 insertions, 43 deletions
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs
index a6deba3b..56685dd5 100644
--- a/font/src/darwin/mod.rs
+++ b/font/src/darwin/mod.rs
@@ -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)
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index 765e8efb..44dc0be3 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -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
diff --git a/font/src/lib.rs b/font/src/lib.rs
index f9eaaac6..68935e45 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -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> {
diff --git a/src/display.rs b/src/display.rs
index bfd62c32..8e3d8814 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -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,
+ );
});
}
diff --git a/src/event.rs b/src/event.rs
index c8fb83e9..894777fa 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -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;
}
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 86115171..da59a037 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -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,
)
}