feat: scroll-to-bottom on output via renderer pin tracking
Co-Authored-By: Sachin <sachinbeniwal0101@gmail.com>pull/9938/head
parent
c00949275c
commit
633b6e1cfd
|
|
@ -1059,6 +1059,12 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
|
|||
|
||||
.scrollbar => |scrollbar| self.updateScrollbar(scrollbar),
|
||||
|
||||
.scroll_to_bottom => {
|
||||
self.queueIo(.{
|
||||
.scroll_viewport = .{ .bottom = {} },
|
||||
}, .unlocked);
|
||||
},
|
||||
|
||||
.report_color_scheme => |force| self.reportColorScheme(force),
|
||||
|
||||
.present_surface => try self.presentSurface(),
|
||||
|
|
|
|||
|
|
@ -113,6 +113,10 @@ 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,
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,12 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
scrollbar: terminal.Scrollbar,
|
||||
scrollbar_dirty: bool,
|
||||
|
||||
/// 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_y: terminal.size.CellCountInt,
|
||||
|
||||
/// The most recent viewport matches so that we can render search
|
||||
/// matches in the visible frame. This is provided asynchronously
|
||||
/// from the search thread so we have the dirty flag to also note
|
||||
|
|
@ -562,6 +568,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
colorspace: configpkg.Config.WindowColorspace,
|
||||
blending: configpkg.Config.AlphaBlending,
|
||||
background_blur: configpkg.Config.BackgroundBlur,
|
||||
scroll_to_bottom_on_output: bool,
|
||||
|
||||
pub fn init(
|
||||
alloc_gpa: Allocator,
|
||||
|
|
@ -635,6 +642,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
.colorspace = config.@"window-colorspace",
|
||||
.blending = config.@"alpha-blending",
|
||||
.background_blur = config.@"background-blur",
|
||||
.scroll_to_bottom_on_output = config.@"scroll-to-bottom".output,
|
||||
.arena = arena,
|
||||
};
|
||||
}
|
||||
|
|
@ -698,6 +706,8 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
|||
.focused = true,
|
||||
.scrollbar = .zero,
|
||||
.scrollbar_dirty = false,
|
||||
.last_bottom_node = null,
|
||||
.last_bottom_y = 0,
|
||||
.search_matches = null,
|
||||
.search_selected_match = null,
|
||||
.search_matches_dirty = false,
|
||||
|
|
@ -1160,6 +1170,25 @@ 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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue