Skip to content

Commit

Permalink
Fix regional scrolling leaking into history
Browse files Browse the repository at this point in the history
This fixes an issue where a scrolling region that does not start at the
top of the screen would still rotate lines into history when scrolling
the content "upwards".
  • Loading branch information
chrisduerr committed Feb 14, 2024
1 parent de12f03 commit f1853a0
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- C0 and C1 codes being emitted in associated text when using kitty keyboard
- Occasional hang on startup with some Wayland compositors
- Missing key for `NumpadDecimal` in key bindings
- Scrolling content upwards moving lines into history when it shouldn't

### Changed

Expand Down
52 changes: 30 additions & 22 deletions alacritty_terminal/src/grid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,33 +268,41 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
self.display_offset = min(self.display_offset + positions, self.max_scroll_limit);
}

// Create scrollback for the new lines.
self.increase_scroll_limit(positions);
// Only rotate the entire history if the active region starts at the top.
if region.start == 0 {
// Create scrollback for the new lines.
self.increase_scroll_limit(positions);

// Swap the lines fixed at the top to their target positions after rotation.
//
// Since we've made sure that the rotation will never rotate away the entire region, we
// know that the position of the fixed lines before the rotation must already be
// visible.
//
// We need to start from the bottom, to make sure the fixed lines aren't swapped with each
// other.
for i in (0..region.start.0).rev().map(Line::from) {
self.raw.swap(i, i + positions);
}
// Swap the lines fixed at the top to their target positions after rotation.
//
// Since we've made sure that the rotation will never rotate away the entire region, we
// know that the position of the fixed lines before the rotation must already be
// visible.
//
// We need to start from the bottom, to make sure the fixed lines aren't swapped with
// each other.
for i in (0..region.start.0).rev().map(Line::from) {
self.raw.swap(i, i + positions);
}

// Rotate the entire line buffer upward.
self.raw.rotate(-(positions as isize));
// Rotate the entire line buffer upward.
self.raw.rotate(-(positions as isize));

// Ensure all new lines are fully cleared.
let screen_lines = self.screen_lines();
for i in ((screen_lines - positions)..screen_lines).map(Line::from) {
self.raw[i].reset(&self.cursor.template);
// Swap the fixed lines at the bottom back into position.
let screen_lines = self.screen_lines() as i32;
for i in (region.end.0..screen_lines).rev().map(Line::from) {
self.raw.swap(i, i - positions);
}
} else {
// Rotate lines without moving anything into history.
for i in (region.start.0..region.end.0 - positions as i32).map(Line::from) {
self.raw.swap(i, i + positions);
}
}

// Swap the fixed lines at the bottom back into position.
for i in (region.end.0..(screen_lines as i32)).rev().map(Line::from) {
self.raw.swap(i, i - positions);
// Ensure all new lines are fully cleared.
for i in (region.end.0 - positions as i32..region.end.0).map(Line::from) {
self.raw[i].reset(&self.cursor.template);
}
}

Expand Down
1 change: 1 addition & 0 deletions alacritty_terminal/tests/ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ ref_tests! {
zerowidth
zsh_tab_completion
erase_in_line
scroll_in_region_up_preserves_history
}

fn read_u8<P>(path: P) -> Vec<u8>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls -lah
[?2004ltotal 464K
drwxr-xr-x 13 undeadleech undeadleech 4.0K Feb 12 20:50 .
drwxr-xr-x 15 undeadleech undeadleech 4.0K Dec 9 18:42 ..
drwxr-xr-x 5 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty
drwxr-xr-x 3 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_config
drwxr-xr-x 4 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_config_derive
-rw-r--r-- 1 undeadleech undeadleech 115 Feb 12 20:51 alacritty.recording
drwxr-xr-x 4 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_terminal
drwxr-xr-x 2 undeadleech undeadleech 4.0K Jan 8 23:30 .builds
-rw-r--r-- 1 undeadleech undeadleech 62K Feb 12 18:19 Cargo.lock
-rw-r--r-- 1 undeadleech undeadleech 201 Jan 8 23:29 Cargo.toml
-rw-r--r-- 1 undeadleech undeadleech 56K Feb 10 09:04 CHANGELOG.md
-rw-r--r-- 1 undeadleech undeadleech 18 Feb 12 20:50 config.json
-rw-r--r-- 1 undeadleech undeadleech 7.9K Feb 10 09:04 CONTRIBUTING.md
drwxr-xr-x 2 undeadleech undeadleech 4.0K Feb 10 09:04 docs
-rw-r--r-- 1 undeadleech undeadleech 240 Jan 8 23:29 .editorconfig
drwxr-xr-x 8 undeadleech undeadleech 4.0K Feb 10 09:04 extra
drwxr-xr-x 8 undeadleech undeadleech 4.0K Feb 12 20:50 .git
drwxr-xr-x 3 undeadleech undeadleech 4.0K Oct 14 2022 .github
-rw-r--r-- 1 undeadleech undeadleech 7 Oct 14 2022 .gitignore
-rw-r--r-- 1 undeadleech undeadleech 212K Feb 12 20:50 grid.json
-rw-r--r-- 1 undeadleech undeadleech 11K Jan 8 23:29 INSTALL.md
-rw-r--r-- 1 undeadleech undeadleech 11K Sep 1 2022 LICENSE-APACHE
-rw-r--r-- 1 undeadleech undeadleech 1023 Jan 15 2023 LICENSE-MIT
-rw-r--r-- 1 undeadleech undeadleech 3.2K Jan 8 23:29 Makefile
-rw-r--r-- 1 undeadleech undeadleech 4.2K Feb 10 09:04 README.md
-rw-r--r-- 1 undeadleech undeadleech 421 Oct 14 2022 rustfmt.toml
drwxr-xr-x 2 undeadleech undeadleech 4.0K Sep 1 2022 scripts
-rw-r--r-- 1 undeadleech undeadleech 32 Feb 12 20:50 size.json
drwxr-xr-x 6 undeadleech undeadleech 4.0K Feb 12 18:19 target
-rw-r--r-- 1 undeadleech undeadleech 27 Apr 9 2023 TODO
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ echo -e "\e[12r"
[?2004l
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls
[?2004lalacritty Cargo.toml grid.json rustfmt.toml
alacritty_config CHANGELOG.md INSTALL.md scripts
alacritty_config_derive config.json LICENSE-APACHE size.json
alacritty.recording CONTRIBUTING.md LICENSE-MIT target
alacritty_terminal docs Makefile TODO
Cargo.lock extra README.md
]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"history_size":10}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"columns":80,"screen_lines":30}

0 comments on commit f1853a0

Please sign in to comment.