Commit 1887722e authored by Christian Duerr's avatar Christian Duerr Committed by GitHub

Fix rendering of selections outside the viewport

When rendering selections with both start and end outside of the visible
area, Alacritty would assume that both start and end are either above or
below the viewport and not render the selection at all.

To fix this the `buffer_line_to_visible` method now returns a
`ViewportPosition` instead of an `Option<Line>`, this allows giving more
feedback about where outside of the visible region the line is using the
`ViewportPosition::Above` and `ViewportPosition::Below` variants.

Using these newly introduced variants, a selection spanning the whole
screen is now rendered if the selection should go from above the visible
area to below it.

This fixes #1557.
parent 88076938
...@@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -42,6 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Windows started as unfocused now show the hollow cursor if the setting is enabled - Windows started as unfocused now show the hollow cursor if the setting is enabled
- Empty lines in selections are now properly copied to the clipboard - Empty lines in selections are now properly copied to the clipboard
- Selection start point lagging behind initial cursor position - Selection start point lagging behind initial cursor position
- Rendering of selections which start above the visible area and end below it
### Deprecated ### Deprecated
......
...@@ -116,6 +116,13 @@ pub enum Scroll { ...@@ -116,6 +116,13 @@ pub enum Scroll {
Bottom, Bottom,
} }
#[derive(Copy, Clone)]
pub enum ViewportPosition {
Visible(Line),
Above,
Below,
}
impl<T: Copy + Clone> Grid<T> { impl<T: Copy + Clone> Grid<T> {
pub fn new(lines: index::Line, cols: index::Column, scrollback: usize, template: T) -> Grid<T> { pub fn new(lines: index::Line, cols: index::Column, scrollback: usize, template: T) -> Grid<T> {
let raw = Storage::with_capacity(lines, Row::new(cols, &template)); let raw = Storage::with_capacity(lines, Row::new(cols, &template));
...@@ -137,18 +144,14 @@ impl<T: Copy + Clone> Grid<T> { ...@@ -137,18 +144,14 @@ impl<T: Copy + Clone> Grid<T> {
} }
} }
pub fn buffer_to_visible(&self, point: Point<usize>) -> Point { pub fn buffer_line_to_visible(&self, line: usize) -> ViewportPosition {
Point { let offset = line.saturating_sub(self.display_offset);
line: self.buffer_line_to_visible(point.line).expect("Line not visible"), if line < self.display_offset {
col: point.col ViewportPosition::Below
} } else if offset >= *self.num_lines() {
} ViewportPosition::Above
pub fn buffer_line_to_visible(&self, line: usize) -> Option<Line> {
if line >= self.display_offset {
self.offset_to_line(line - self.display_offset)
} else { } else {
None ViewportPosition::Visible(self.lines - offset - 1)
} }
} }
...@@ -300,14 +303,6 @@ impl<T: Copy + Clone> Grid<T> { ...@@ -300,14 +303,6 @@ impl<T: Copy + Clone> Grid<T> {
*(self.num_lines() - line - 1) *(self.num_lines() - line - 1)
} }
pub fn offset_to_line(&self, offset: usize) -> Option<Line> {
if offset < *self.num_lines() {
Some(self.lines - offset - 1)
} else {
None
}
}
#[inline] #[inline]
pub fn scroll_down( pub fn scroll_down(
&mut self, &mut self,
......
...@@ -23,7 +23,7 @@ use unicode_width::UnicodeWidthChar; ...@@ -23,7 +23,7 @@ use unicode_width::UnicodeWidthChar;
use font::{self, Size}; use font::{self, Size};
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset, CursorStyle}; use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset, CursorStyle};
use grid::{BidirectionalIterator, Grid, Indexed, IndexRegion, DisplayIter, Scroll}; use grid::{BidirectionalIterator, Grid, Indexed, IndexRegion, DisplayIter, Scroll, ViewportPosition};
use index::{self, Point, Column, Line, IndexRange, Contains, RangeInclusive, Linear}; use index::{self, Point, Column, Line, IndexRange, Contains, RangeInclusive, Linear};
use selection::{self, Selection, Locations}; use selection::{self, Selection, Locations};
use config::{Config, VisualBellAnimation}; use config::{Config, VisualBellAnimation};
...@@ -136,16 +136,19 @@ impl<'a> RenderableCellsIter<'a> { ...@@ -136,16 +136,19 @@ impl<'a> RenderableCellsIter<'a> {
// Get start/end locations based on what part of selection is on screen // Get start/end locations based on what part of selection is on screen
let locations = match (start_line, end_line) { let locations = match (start_line, end_line) {
(Some(start_line), Some(end_line)) => { (ViewportPosition::Visible(start_line), ViewportPosition::Visible(end_line)) => {
Some((start_line, loc.start.col, end_line, loc.end.col)) Some((start_line, loc.start.col, end_line, loc.end.col))
}, },
(Some(start_line), None) => { (ViewportPosition::Visible(start_line), ViewportPosition::Above) => {
Some((start_line, loc.start.col, Line(0), Column(0))) Some((start_line, loc.start.col, Line(0), Column(0)))
}, },
(None, Some(end_line)) => { (ViewportPosition::Below, ViewportPosition::Visible(end_line)) => {
Some((grid.num_lines(), Column(0), end_line, loc.end.col)) Some((grid.num_lines(), Column(0), end_line, loc.end.col))
}, },
(None, None) => None, (ViewportPosition::Below, ViewportPosition::Above) => {
Some((grid.num_lines(), Column(0), Line(0), Column(0)))
},
_ => None,
}; };
if let Some((start_line, start_col, end_line, end_col)) = locations { if let Some((start_line, start_col, end_line, end_col)) = locations {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment