mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-10 19:29:37 +00:00
lib-vt: add scroll-to-row viewport scrolling
This adds a GHOSTTY_SCROLL_VIEWPORT_ROW tag with a `size_t row` member
in the value union. The row is an absolute offset from the top of the
scrollable area, clamped to the active area, in the same row space as
the scrollbar offset so thumb positions round-trip cleanly:
ghostty_terminal_scroll_viewport(term,
(GhosttyTerminalScrollViewport){
.tag = GHOSTTY_SCROLL_VIEWPORT_ROW,
.value = {.row = 42},
});
The tag is appended to the existing enum and the union fits within the
reserved padding, so this is ABI compatible.
This also corrects the docs on GHOSTTY_TERMINAL_DATA_SCROLLBAR: the
getter is amortized O(1) (total is maintained incrementally, the offset
is cached), not "expensive". Since there is intentionally no change
callback, the docs now bless polling per frame or per write batch and
diffing, which is what Ghostty's own renderer does.
Motivation: Embedders building native scrollbars can already read scroll state via
GHOSTTY_TERMINAL_DATA_SCROLLBAR, but the write side only exposed
top/bottom/delta scrolling. Mapping a scrollbar thumb drag to an
absolute position required reading the current offset and computing a
delta, which is two calls that must be sequenced atomically by the
caller.
The core already supports absolute positioning and the macOS
app uses it for scroller drags via the scroll_to_row keybinding; this
exposes the same operation through the libghostty C API.
This commit is contained in:
@@ -191,6 +191,21 @@ typedef enum GHOSTTY_ENUM_TYPED {
|
||||
|
||||
/** Scroll by a delta amount (up is negative). */
|
||||
GHOSTTY_SCROLL_VIEWPORT_DELTA,
|
||||
|
||||
/**
|
||||
* Scroll to an absolute row offset from the top of the scrollable
|
||||
* area. Row 0 is the top of the scrollback and the requested row
|
||||
* becomes the first visible row of the viewport. The value is
|
||||
* clamped so the viewport never scrolls beyond the top of the
|
||||
* active area. If the terminal has no scrollback (e.g. the
|
||||
* alternate screen is active), the viewport always remains on the
|
||||
* active area.
|
||||
*
|
||||
* This is the same row space as the offset field of
|
||||
* GhosttyTerminalScrollbar, so a scrollbar position obtained from
|
||||
* GHOSTTY_TERMINAL_DATA_SCROLLBAR round-trips cleanly.
|
||||
*/
|
||||
GHOSTTY_SCROLL_VIEWPORT_ROW,
|
||||
GHOSTTY_SCROLL_VIEWPORT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
|
||||
} GhosttyTerminalScrollViewportTag;
|
||||
|
||||
@@ -203,6 +218,9 @@ typedef union {
|
||||
/** Scroll delta (only used with GHOSTTY_SCROLL_VIEWPORT_DELTA). Up is negative. */
|
||||
intptr_t delta;
|
||||
|
||||
/** Absolute row offset (only used with GHOSTTY_SCROLL_VIEWPORT_ROW). */
|
||||
size_t row;
|
||||
|
||||
/** Padding for ABI compatibility. Do not use. */
|
||||
uint64_t _padding[2];
|
||||
} GhosttyTerminalScrollViewportValue;
|
||||
@@ -767,9 +785,16 @@ typedef enum GHOSTTY_ENUM_TYPED {
|
||||
/**
|
||||
* Scrollbar state for the terminal viewport.
|
||||
*
|
||||
* This may be expensive to calculate depending on where the viewport
|
||||
* is (arbitrary pins are expensive). The caller should take care to only
|
||||
* call this as needed and not too frequently.
|
||||
* This is amortized O(1): the total is maintained incrementally as
|
||||
* the terminal is modified and the viewport offset is cached. The
|
||||
* first read after the viewport moves to an arbitrary position that
|
||||
* isn't an absolute row (e.g. scrolling to a selection) may cost
|
||||
* O(pages) to compute the offset, after which it is cached again.
|
||||
*
|
||||
* There is intentionally no change notification for scroll state.
|
||||
* Callers building scrollbars should poll this once per frame or
|
||||
* per write batch and diff the result to detect changes; this is
|
||||
* what Ghostty's own renderer does.
|
||||
*
|
||||
* Output type: GhosttyTerminalScrollbar *
|
||||
*/
|
||||
@@ -1120,7 +1145,10 @@ GHOSTTY_API void ghostty_terminal_vt_write(GhosttyTerminal terminal,
|
||||
* Scrolls the terminal's viewport according to the given behavior.
|
||||
* When using GHOSTTY_SCROLL_VIEWPORT_DELTA, set the delta field in
|
||||
* the value union to specify the number of rows to scroll (negative
|
||||
* for up, positive for down). For other behaviors, the value is ignored.
|
||||
* for up, positive for down). When using GHOSTTY_SCROLL_VIEWPORT_ROW,
|
||||
* set the row field to the absolute row offset from the top of the
|
||||
* scrollable area (the same row space as the offset field of
|
||||
* GhosttyTerminalScrollbar). For other behaviors, the value is ignored.
|
||||
*
|
||||
* @param terminal The terminal handle (may be NULL, in which case this is a no-op)
|
||||
* @param behavior The scroll behavior as a tagged union
|
||||
|
||||
Reference in New Issue
Block a user