This commit is contained in:
2026-05-15 00:28:06 +01:00
parent 2f969fa215
commit 0d578d54f1
31 changed files with 3209 additions and 164 deletions

View File

@@ -57,6 +57,15 @@ type Emulator interface {
// ActiveScreen reports whether we are on the primary or alternate buffer.
ActiveScreen() (Screen, error)
// ScrollViewportTop moves the viewport to the top of the scrollback.
ScrollViewportTop() error
// ScrollViewportBottom moves the viewport back to the active area.
ScrollViewportBottom() error
// ScrollViewportDelta moves the viewport by `delta` rows (negative = up).
ScrollViewportDelta(delta int) error
// OnWritePTY registers a callback that fires when the emulator wants
// to write bytes back to the PTY master (e.g. responses to DA / DSR
// queries). The callback runs synchronously inside Write and must not

View File

@@ -81,6 +81,27 @@ static GhosttyResult patterm_set_userdata(GhosttyTerminal t, uintptr_t ud) {
(const void *)ud);
}
static void patterm_scroll_viewport_top(GhosttyTerminal t) {
GhosttyTerminalScrollViewport beh;
beh.tag = GHOSTTY_SCROLL_VIEWPORT_TOP;
beh.value.delta = 0;
ghostty_terminal_scroll_viewport(t, beh);
}
static void patterm_scroll_viewport_bottom(GhosttyTerminal t) {
GhosttyTerminalScrollViewport beh;
beh.tag = GHOSTTY_SCROLL_VIEWPORT_BOTTOM;
beh.value.delta = 0;
ghostty_terminal_scroll_viewport(t, beh);
}
static void patterm_scroll_viewport_delta(GhosttyTerminal t, intptr_t d) {
GhosttyTerminalScrollViewport beh;
beh.tag = GHOSTTY_SCROLL_VIEWPORT_DELTA;
beh.value.delta = d;
ghostty_terminal_scroll_viewport(t, beh);
}
static GhosttyFormatterTerminalOptions patterm_plain_fmt_opts(void) {
GhosttyFormatterTerminalOptions opts = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
@@ -161,7 +182,7 @@ func NewGhosttyEmulator(cols, rows uint16) (*GhosttyEmulator, error) {
opts := C.GhosttyTerminalOptions{
cols: C.uint16_t(cols),
rows: C.uint16_t(rows),
max_scrollback: 0,
max_scrollback: 5000,
}
if rc := C.ghostty_terminal_new(nil, &e.term, opts); rc != C.GHOSTTY_SUCCESS {
@@ -539,6 +560,39 @@ func (e *GhosttyEmulator) ActiveScreen() (Screen, error) {
return ScreenPrimary, nil
}
// ScrollViewportTop scrolls the viewport to the top of the scrollback.
func (e *GhosttyEmulator) ScrollViewportTop() error {
e.mu.Lock()
defer e.mu.Unlock()
if e.closed {
return errors.New("vt: emulator closed")
}
C.patterm_scroll_viewport_top(e.term)
return nil
}
// ScrollViewportBottom scrolls the viewport to the bottom (active area).
func (e *GhosttyEmulator) ScrollViewportBottom() error {
e.mu.Lock()
defer e.mu.Unlock()
if e.closed {
return errors.New("vt: emulator closed")
}
C.patterm_scroll_viewport_bottom(e.term)
return nil
}
// ScrollViewportDelta scrolls the viewport by `delta` rows. Negative is up.
func (e *GhosttyEmulator) ScrollViewportDelta(delta int) error {
e.mu.Lock()
defer e.mu.Unlock()
if e.closed {
return errors.New("vt: emulator closed")
}
C.patterm_scroll_viewport_delta(e.term, C.intptr_t(delta))
return nil
}
func (e *GhosttyEmulator) OnWritePTY(fn func([]byte)) {
if fn == nil {
e.onWrite.Store(nil)

View File

@@ -24,6 +24,9 @@ func (e *GhosttyEmulator) SerializeVT() ([]byte, error) { return nil, errStub
func (e *GhosttyEmulator) StyledScreenVT() ([]byte, error) { return nil, errStub }
func (e *GhosttyEmulator) Cursor() (CursorState, error) { return CursorState{}, errStub }
func (e *GhosttyEmulator) ActiveScreen() (Screen, error) { return 0, errStub }
func (e *GhosttyEmulator) ScrollViewportTop() error { return errStub }
func (e *GhosttyEmulator) ScrollViewportBottom() error { return errStub }
func (e *GhosttyEmulator) ScrollViewportDelta(int) error { return errStub }
func (e *GhosttyEmulator) OnWritePTY(fn func([]byte)) {}
func (e *GhosttyEmulator) Close() error { return nil }