fix scroll

This commit is contained in:
2025-04-30 18:16:18 +02:00
parent e5ce246760
commit 5ba5a52c14

View File

@@ -16,6 +16,7 @@ pub struct TerminalText {
renderer: TextRenderer,
dirty_regions: Vec<TextBounds>,
cursor: Cursor,
max_scroll_lines: usize,
}
// TODO
@@ -66,12 +67,13 @@ impl TerminalText {
index: 0,
affinity: glyphon::Affinity::After,
},
max_scroll_lines: 100,
}
}
fn get_line_bounds(&self, line: usize) -> TextBounds {
// Calculate the bounds for a specific line
if line >= self.buffer.lines.len() {
// Calculate the bounds delimited by the `start` and `end` lines
fn get_text_bounds(&self, start: usize, end: usize) -> TextBounds {
if start >= self.buffer.lines.len() || end > self.buffer.lines.len() {
// Return default bounds for invalid line
return TextBounds {
left: 0,
@@ -84,25 +86,24 @@ impl TerminalText {
let line_height = self.buffer.metrics().line_height;
let viewport_width = self.viewport.resolution().width;
// Use layout_runs to get information about wrapped lines
let layout_iter = self.buffer.layout_runs();
let mut top_line = 0;
let mut bottom_line = 0;
let mut found_line = false;
// Iterate through layout runs to find our target line
let mut found_start_line = false;
let mut found_end_line = false;
for (visual_line_count, run) in layout_iter.enumerate() {
if run.line_i == line {
// This run belongs to our target line
if !found_line {
// First run of our target line
top_line = visual_line_count;
found_line = true;
if run.line_i == start && !found_start_line {
top_line = visual_line_count;
found_start_line = true;
}
if run.line_i == end {
if !found_end_line {
found_end_line = true;
}
// Update bottom line for each run we find for this line
bottom_line = visual_line_count + 1;
} else if found_line {
// We've processed all runs for our target line
} else if found_end_line {
break;
}
}
@@ -150,14 +151,7 @@ impl TerminalText {
}
// Add 1 to include partially visible lines at the bottom
let end_line = if self.buffer.lines.is_empty() {
0
} else {
// Make sure we include at least the last logical line that has content in the viewport
trace!("Last logical line: {last_logical_line}");
trace!("Number of lines: {}", self.buffer.lines.len());
(last_logical_line + 1).min(self.buffer.lines.len())
};
let end_line = last_logical_line;
trace!("visible line range goes from {start_line} to {end_line}");
@@ -166,9 +160,8 @@ impl TerminalText {
fn ensure_visible_text_rendered(&mut self) {
let (start_line, end_line) = self.get_visible_line_range();
for i in start_line..end_line {
self.dirty_regions.push(self.get_line_bounds(i));
}
self.dirty_regions
.push(self.get_text_bounds(start_line, end_line));
}
fn merge_dirty_regions(&self) -> TextBounds {
@@ -239,6 +232,14 @@ impl TerminalText {
F: FnOnce(&mut Self) -> R,
{
let result = operation(self);
let mut scroll = self.buffer.scroll();
if self.buffer.lines.len() > self.max_scroll_lines {
self.buffer.lines.remove(0);
self.cursor.line -= 1;
}
scroll.line = self.buffer.lines.len();
self.buffer.set_scroll(scroll);
self.buffer.shape_until_scroll(&mut self.font_system, false);
self.ensure_visible_text_rendered();
result
@@ -309,26 +310,6 @@ impl TerminalText {
this.cursor.index = 0;
// Create a new line with text after cursor
this.buffer.lines.insert(this.cursor.line, new_line);
// Only adjust scroll if cursor would be outside visible area
let mut scroll = this.buffer.scroll();
let current_scroll_line =
(scroll.vertical / this.buffer.metrics().line_height).floor() as usize;
let max_visible_lines =
(safe_casts::u32_to_f32_or_max(this.viewport.resolution().height)
/ this.buffer.metrics().line_height)
.floor() as usize;
// Only scroll if cursor would be below visible area
if this.cursor.line >= current_scroll_line + max_visible_lines {
scroll.vertical =
safe_casts::usize_to_f32_or_max(this.cursor.line - max_visible_lines + 1)
* this.buffer.metrics().line_height;
trace!("adjusting scroll to keep cursor visible: {:?}", scroll);
this.buffer.set_scroll(scroll);
} else {
trace!("keeping current scroll: {:?}", scroll);
}
})
}
@@ -378,11 +359,6 @@ impl TerminalText {
ret = true;
}
if line > this.buffer.lines.len() {
let mut scroll = this.buffer.scroll();
scroll.vertical -= 1.0 * this.buffer.metrics().line_height;
this.buffer.set_scroll(scroll);
}
ret
})
}