mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-17 13:02:42 +00:00
cleanup by just scrolling in the renderer
This commit is contained in:
@@ -1070,12 +1070,6 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
|
||||
|
||||
.scrollbar => |scrollbar| self.updateScrollbar(scrollbar),
|
||||
|
||||
.scroll_to_bottom => {
|
||||
self.queueIo(.{
|
||||
.scroll_viewport = .{ .bottom = {} },
|
||||
}, .unlocked);
|
||||
},
|
||||
|
||||
.present_surface => try self.presentSurface(),
|
||||
|
||||
.password_input => |v| try self.passwordInput(v),
|
||||
@@ -1180,7 +1174,7 @@ fn selectionScrollTick(self: *Surface) !void {
|
||||
}
|
||||
|
||||
// Scroll the viewport as required
|
||||
try t.scrollViewport(.{ .delta = delta });
|
||||
t.scrollViewport(.{ .delta = delta });
|
||||
|
||||
// Next, trigger our drag behavior
|
||||
const pin = t.screens.active.pages.pin(.{
|
||||
@@ -2785,7 +2779,7 @@ pub fn keyCallback(
|
||||
try self.setSelection(null);
|
||||
}
|
||||
|
||||
if (self.config.scroll_to_bottom.keystroke) try self.io.terminal.scrollViewport(.bottom);
|
||||
if (self.config.scroll_to_bottom.keystroke) self.io.terminal.scrollViewport(.bottom);
|
||||
|
||||
try self.queueRender();
|
||||
}
|
||||
@@ -3538,7 +3532,7 @@ pub fn scrollCallback(
|
||||
// Modify our viewport, this requires a lock since it affects
|
||||
// rendering. We have to switch signs here because our delta
|
||||
// is negative down but our viewport is positive down.
|
||||
try self.io.terminal.scrollViewport(.{ .delta = y.delta * -1 });
|
||||
self.io.terminal.scrollViewport(.{ .delta = y.delta * -1 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5069,7 +5063,7 @@ pub fn posToViewport(self: Surface, xpos: f64, ypos: f64) terminal.point.Coordin
|
||||
///
|
||||
/// Precondition: the render_state mutex must be held.
|
||||
fn scrollToBottom(self: *Surface) !void {
|
||||
try self.io.terminal.scrollViewport(.{ .bottom = {} });
|
||||
self.io.terminal.scrollViewport(.{ .bottom = {} });
|
||||
try self.queueRender();
|
||||
}
|
||||
|
||||
|
||||
@@ -108,10 +108,6 @@ pub const Message = union(enum) {
|
||||
/// Selected search index change
|
||||
search_selected: ?usize,
|
||||
|
||||
/// Scroll the viewport to the bottom. This is triggered by the renderer
|
||||
/// when new output is detected and scroll-to-bottom on output is enabled.
|
||||
scroll_to_bottom,
|
||||
|
||||
pub const ReportTitleStyle = enum {
|
||||
csi_21_t,
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
/// Tracks the last bottom-right pin of the screen to detect new output.
|
||||
/// When the final line changes (node or y differs), new content was added.
|
||||
/// Used for scroll-to-bottom on output feature.
|
||||
last_bottom_node: ?*terminal.PageList.List.Node,
|
||||
last_bottom_node: ?usize,
|
||||
last_bottom_y: terminal.size.CellCountInt,
|
||||
|
||||
/// The most recent viewport matches so that we can render search
|
||||
@@ -1176,6 +1176,26 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
return;
|
||||
}
|
||||
|
||||
// If scroll-to-bottom on output is enabled, check if the final line
|
||||
// changed by comparing the bottom-right pin. If the node pointer or
|
||||
// y offset changed, new content was added to the screen.
|
||||
// Update this BEFORE we update our render state so we can
|
||||
// draw the new scrolled data immediately.
|
||||
if (self.config.scroll_to_bottom_on_output) scroll: {
|
||||
const br = state.terminal.screens.active.pages.getBottomRight(.screen) orelse break :scroll;
|
||||
|
||||
// If the pin hasn't changed, then don't scroll.
|
||||
if (self.last_bottom_node == @intFromPtr(br.node) and
|
||||
self.last_bottom_y == br.y) break :scroll;
|
||||
|
||||
// Update tracked pin state for next frame
|
||||
self.last_bottom_node = @intFromPtr(br.node);
|
||||
self.last_bottom_y = br.y;
|
||||
|
||||
// Scroll
|
||||
state.terminal.scrollViewport(.bottom);
|
||||
}
|
||||
|
||||
// Update our terminal state
|
||||
try self.terminal_state.update(self.alloc, state.terminal);
|
||||
|
||||
@@ -1192,25 +1212,6 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
// cross-thread mailbox message within the IO path.
|
||||
const scrollbar = state.terminal.screens.active.pages.scrollbar();
|
||||
|
||||
// If scroll-to-bottom on output is enabled, check if the final line
|
||||
// changed by comparing the bottom-right pin. If the node pointer or
|
||||
// y offset changed, new content was added to the screen.
|
||||
if (self.config.scroll_to_bottom_on_output) {
|
||||
const bottom_right = state.terminal.screens.active.pages.getBottomRight(.screen);
|
||||
if (bottom_right) |br| {
|
||||
const pin_changed = (self.last_bottom_node != br.node) or
|
||||
(self.last_bottom_y != br.y);
|
||||
|
||||
if (pin_changed and !state.terminal.screens.active.viewportIsBottom()) {
|
||||
_ = self.surface_mailbox.push(.scroll_to_bottom, .instant);
|
||||
}
|
||||
|
||||
// Update tracked pin state for next frame
|
||||
self.last_bottom_node = br.node;
|
||||
self.last_bottom_y = br.y;
|
||||
}
|
||||
}
|
||||
|
||||
// Get our preedit state
|
||||
const preedit: ?renderer.State.Preedit = preedit: {
|
||||
const p = state.preedit orelse break :preedit null;
|
||||
|
||||
@@ -1625,7 +1625,7 @@ pub const ScrollViewport = union(enum) {
|
||||
};
|
||||
|
||||
/// Scroll the viewport of the terminal grid.
|
||||
pub fn scrollViewport(self: *Terminal, behavior: ScrollViewport) !void {
|
||||
pub fn scrollViewport(self: *Terminal, behavior: ScrollViewport) void {
|
||||
self.screens.active.scroll(switch (behavior) {
|
||||
.top => .{ .top = {} },
|
||||
.bottom => .{ .active = {} },
|
||||
|
||||
@@ -641,10 +641,13 @@ pub fn clearScreen(self: *Termio, td: *ThreadData, history: bool) !void {
|
||||
}
|
||||
|
||||
/// Scroll the viewport
|
||||
pub fn scrollViewport(self: *Termio, scroll: terminalpkg.Terminal.ScrollViewport) !void {
|
||||
pub fn scrollViewport(
|
||||
self: *Termio,
|
||||
scroll: terminalpkg.Terminal.ScrollViewport,
|
||||
) void {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
try self.terminal.scrollViewport(scroll);
|
||||
self.terminal.scrollViewport(scroll);
|
||||
}
|
||||
|
||||
/// Jump the viewport to the prompt.
|
||||
|
||||
@@ -321,7 +321,7 @@ fn drainMailbox(
|
||||
.resize => |v| self.handleResize(cb, v),
|
||||
.size_report => |v| try io.sizeReport(data, v),
|
||||
.clear_screen => |v| try io.clearScreen(data, v.history),
|
||||
.scroll_viewport => |v| try io.scrollViewport(v),
|
||||
.scroll_viewport => |v| io.scrollViewport(v),
|
||||
.selection_scroll => |v| {
|
||||
if (v) {
|
||||
self.startScrollTimer(cb);
|
||||
|
||||
@@ -232,7 +232,7 @@ pub const StreamHandler = struct {
|
||||
.erase_display_below => self.terminal.eraseDisplay(.below, value),
|
||||
.erase_display_above => self.terminal.eraseDisplay(.above, value),
|
||||
.erase_display_complete => {
|
||||
try self.terminal.scrollViewport(.{ .bottom = {} });
|
||||
self.terminal.scrollViewport(.{ .bottom = {} });
|
||||
self.terminal.eraseDisplay(.complete, value);
|
||||
},
|
||||
.erase_display_scrollback => self.terminal.eraseDisplay(.scrollback, value),
|
||||
|
||||
Reference in New Issue
Block a user