Skip to content

Commit

Permalink
Fix selection rotation on the last line
Browse files Browse the repository at this point in the history
This fixes an issue with terminal resizes when the selection is on the
last line. Alacritty would fail to rotate lines and keep the selection
in the same line index whenever the terminal line count was grown or
shrunk.

This issue occurred due to the range passed to the selection's rotate
function still being based on the old terminal size, which caused the
initial or target state of the rotation to be outside of the terminal
bounds.

Closes alacritty#6698.
  • Loading branch information
chrisduerr committed Mar 22, 2023
1 parent 4b91a1d commit 268880e
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 16 deletions.
18 changes: 7 additions & 11 deletions alacritty/src/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,11 +588,10 @@ impl Display {
});
}

// XXX: this function must not call to any `OpenGL` related tasks. Renderer updates are
// performed in [`Self::process_renderer_update`] right befor drawing.
//
/// Process update events.
///
/// XXX: this function must not call to any `OpenGL` related tasks. Only logical update
/// of the state is being performed here. Rendering update takes part right before the
/// actual rendering.
pub fn handle_update<T>(
&mut self,
terminal: &mut Term<T>,
Expand Down Expand Up @@ -666,14 +665,11 @@ impl Display {
self.size_info = new_size;
}

// NOTE: Renderer updates are split off, since platforms like Wayland require resize and other
// OpenGL operations to be performed right before rendering. Otherwise they could lock the
// back buffer and render with the previous state. This also solves flickering during resizes.
//
/// Update the state of the renderer.
///
/// NOTE: The update to the renderer is split from the display update on purpose, since
/// on some platforms, like Wayland, resize and other OpenGL operations must be performed
/// right before rendering, otherwise they could lock the back buffer resulting in
/// rendering with the buffer of old size.
///
/// This also resolves any flickering, since the resize is now synced with frame callbacks.
pub fn process_renderer_update(&mut self) {
let renderer_update = match self.pending_renderer_update.take() {
Some(renderer_update) => renderer_update,
Expand Down
11 changes: 6 additions & 5 deletions alacritty_terminal/src/term/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,21 +611,22 @@ impl<T> Term<T> {
delta = cmp::min(cmp::max(delta, min_delta), history_size as i32);
self.vi_mode_cursor.point.line += delta;

let is_alt = self.mode.contains(TermMode::ALT_SCREEN);
self.grid.resize(!is_alt, num_lines, num_cols);
self.inactive_grid.resize(is_alt, num_lines, num_cols);

// Invalidate selection and tabs only when necessary.
if old_cols != num_cols {
self.selection = None;

// Recreate tabs list.
self.tabs.resize(num_cols);
} else if let Some(selection) = self.selection.take() {
let range = Line(0)..Line(num_lines as i32);
let max_lines = cmp::max(num_lines, old_lines) as i32;
let range = Line(0)..Line(max_lines);
self.selection = selection.rotate(self, &range, -delta);
}

let is_alt = self.mode.contains(TermMode::ALT_SCREEN);
self.grid.resize(!is_alt, num_lines, num_cols);
self.inactive_grid.resize(is_alt, num_lines, num_cols);

// Clamp vi cursor to viewport.
let vi_point = self.vi_mode_cursor.point;
let viewport_top = Line(-(self.grid.display_offset() as i32));
Expand Down

0 comments on commit 268880e

Please sign in to comment.