package libghostty // Render state for creating high-performance renderers. // Wraps the GhosttyRenderState C APIs (excluding row/cell iterators). /* #include */ import "C" // RenderState holds the state required to render a visible screen // (viewport) of a terminal instance. It is stateful and optimized // for repeated updates from a single terminal, only updating dirty // regions of the screen. // // A render state owns its own snapshot storage. Hold exclusive access // to the terminal while calling [RenderState.Update]. After Update // returns, the render state can be read without touching the terminal // until the next Update. Do not call Update concurrently with reads // from the same render state. // // Iterators populated from the render state are only valid until the // next Update, but copied values returned from their getter methods can // be retained. // // Basic usage: // 1. Create an empty render state with NewRenderState. // 2. Update it from a terminal via Update whenever needed. // 3. Read from the render state to get data for drawing. // 4. Call Clean after successfully rendering the complete frame. // // C: GhosttyRenderState type RenderState struct { ptr C.GhosttyRenderState } // RenderStateOverscan specifies the number of extra rows above and below the // visible viewport. These rows let a renderer draw part of an adjacent row // while scrolling smoothly. // // [RenderState.SetOverscan] sets the requested counts. [RenderState.Overscan] // returns the counts available after an update, which may be smaller. The // zero value requests no extra rows. // // C: GhosttyRenderStateOverscan type RenderStateOverscan struct { // Above is the number of rows above the viewport. Above uint16 // Below is the number of rows below the viewport. Below uint16 } // RenderStateDirty describes the dirty state after an update. // C: GhosttyRenderStateDirty type RenderStateDirty int const ( // RenderStateDirtyFalse means not dirty; rendering can be skipped. RenderStateDirtyFalse RenderStateDirty = C.GHOSTTY_RENDER_STATE_DIRTY_FALSE // RenderStateDirtyPartial means some rows changed; renderer can // redraw incrementally. RenderStateDirtyPartial RenderStateDirty = C.GHOSTTY_RENDER_STATE_DIRTY_PARTIAL // RenderStateDirtyFull means global state changed; renderer should // redraw everything. RenderStateDirtyFull RenderStateDirty = C.GHOSTTY_RENDER_STATE_DIRTY_FULL ) // CursorVisualStyle describes the visual style of the cursor. // C: GhosttyRenderStateCursorVisualStyle type CursorVisualStyle int const ( // CursorVisualStyleBar is a bar cursor (DECSCUSR 5, 6). CursorVisualStyleBar CursorVisualStyle = C.GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BAR // CursorVisualStyleBlock is a block cursor (DECSCUSR 1, 2). CursorVisualStyleBlock CursorVisualStyle = C.GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK // CursorVisualStyleUnderline is an underline cursor (DECSCUSR 3, 4). CursorVisualStyleUnderline CursorVisualStyle = C.GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_UNDERLINE // CursorVisualStyleBlockHollow is a hollow block cursor. CursorVisualStyleBlockHollow CursorVisualStyle = C.GHOSTTY_RENDER_STATE_CURSOR_VISUAL_STYLE_BLOCK_HOLLOW ) // RenderStateCursor holds all cursor information from a render state, // retrieved in a single call via the sized-struct API. // // ViewportX, ViewportY, and WideTail are only valid when ViewportHasValue is // true. The remaining fields are always populated. // C: GhosttyRenderStateCursor type RenderStateCursor struct { // ViewportHasValue reports whether the cursor is visible within the // viewport. When false, the viewport position and WideTail are undefined. ViewportHasValue bool // ViewportX is the cursor's viewport column in cells. ViewportX uint16 // ViewportY is the cursor's viewport row in cells. ViewportY uint16 // WideTail reports whether the cursor is on the tail of a wide character. WideTail bool // Visible reports whether terminal modes make the cursor visible. Visible bool // Blinking reports whether terminal modes make the cursor blink. Blinking bool // PasswordInput reports whether the cursor is at a password input field. PasswordInput bool // VisualStyle is the visual shape of the cursor. VisualStyle CursorVisualStyle } // RenderStateColors holds all color information from a render state, // retrieved in a single call via the sized-struct API. // C: GhosttyRenderStateColors type RenderStateColors struct { // Background is the default/current background color. Background ColorRGB // Foreground is the default/current foreground color. Foreground ColorRGB // Cursor is the cursor color when explicitly set by terminal state. // Only valid when CursorHasValue is true. Cursor ColorRGB // CursorHasValue is true when Cursor contains a valid explicit // cursor color value. CursorHasValue bool // Palette is the active 256-color palette. Palette Palette } // NewRenderState creates a new empty render state. func NewRenderState() (*RenderState, error) { var ptr C.GhosttyRenderState if err := resultError(C.ghostty_render_state_new(nil, &ptr)); err != nil { return nil, err } return &RenderState{ptr: ptr}, nil } // Close frees the underlying render state handle. After this call, // the render state must not be used, except that calling Close again is // a safe no-op. func (rs *RenderState) Close() { if rs == nil || rs.ptr == nil { return } C.ghostty_render_state_free(rs.ptr) rs.ptr = nil } // Update copies the terminal's current display state into rs. It consumes // dirty state from the terminal and its screen. Update is the only render state // operation that accesses the terminal. // // The caller must hold exclusive access to the terminal while Update runs. Do // not read from rs concurrently with Update. A [RenderHoldFunc] may call Update // when a hold begins to capture the last complete frame. func (rs *RenderState) Update(t *Terminal) error { return resultError(C.ghostty_render_state_update(rs.ptr, t.ptr)) } // BeginUpdate performs the terminal-dependent phase of a two-phase render // state update. Every successful call must be paired with [RenderState.EndUpdate] // before reading the render state. func (rs *RenderState) BeginUpdate(t *Terminal) error { return resultError(C.ghostty_render_state_begin_update(rs.ptr, t.ptr)) } // EndUpdate completes deferred work from [RenderState.BeginUpdate]. It only // accesses render-state-owned memory and does not require terminal access. func (rs *RenderState) EndUpdate() error { return resultError(C.ghostty_render_state_end_update(rs.ptr)) } // Clean marks all render-state dirty data as consumed. It clears both the // global dirty state and every per-row dirty flag without modifying cell // contents or terminal-owned dirty state. Call Clean only after successfully // rendering a complete frame; partial consumers should clear only the state // they consumed with [RenderState.SetDirty] and // [RenderStateRowIterator.SetDirty]. // C: ghostty_render_state_clean func (rs *RenderState) Clean() error { return resultError(C.ghostty_render_state_clean(rs.ptr)) }