Native Scene UI

scene_* is Keybind's native, real-time UI primitive: a topmost, non-activating window that renders a KSL-described list of elements — rectangles, text, images, swatches, controls — at up to 60fps, with clicks/hover/keys reported back to your script by polling. No HTML, no WebView: it's GDI+ under the hood, driven entirely declaratively.

When to use it

  • **scene_*** — a native loupe/lens, a HUD, a color picker, a floating toolbar, a settings panel:

anything that wants a real-time render loop, pixel-level control, or to read a frozen screen buffer (screenbuf_*) for a magnifier. This is the primitive behind Keybind's own color-picker card + lens.

  • `overlay_page()` — reach for the HTML/WebView path instead when you want document-style

layout, rich text, or web components — it's the escape hatch for anything that doesn't need a native render loop.

  • **overlay_*/hud_show** — the simplest fixed-vocabulary overlay calls (a text label, a rect, a

HUD banner) are still the fastest one-liner when you don't need a whole element tree.

The lifecycle: open → set → poll → close

let s = scene_open({ anchor: "cursor", gap_above: 0.05, w: 260, h: 140, radius: 10,
                      theme: { accent: "#6C8CFF" } })
if s == null { throw "could not open the scene window" }

loop {
    scene_set(s, [
        { type: "text",  value: "Quick Settings", size: 16, weight: "bold", x: 12, y: 10 },
        { type: "input", id: "name", value: "", placeholder: "Your name", x: 12, y: 40, w: 220, h: 32 },
        { type: "row",   id: "save", label: "Save", x: 12, y: 84, w: 220, h: 32, hover_fill: "#333" },
    ])

    let ev = scene_poll_event(s)
    if ev.type == "input"   { log_line("typing: {ev.value}") }
    if ev.type == "click" and ev.target == "save" { break }
    if ev.type == "dismiss" { break }
    sleep(16)
}
scene_close(s)

Every scene follows this shape: scene_open creates the window and returns a handle (or null on failure — always check it); scene_set pushes the whole element tree each time your data changes (or scene_update(s, id, patch) to patch just one element cheaply); scene_poll_event drains one event per call, so poll it in a loop with a short sleep; scene_close always tears the window down when you're done.

Element vocabulary

rect, text, image, swatch, line, ellipse, and magnify (reads a screenbuf_* frozen buffer for lens/loupe effects) cover drawing. group is the layout container — set layout: "row", "column", or "stack" and it positions its children for you (padding, gap, align, justify, auto-size) instead of hand-computed coordinates.

Controls and events

checkbox, toggle, slider, input (an editable text field), and row/button are stateful, native controls — they track their own live value, support Tab-to-focus, and report changes via scene_poll_event: click, change (checkbox/toggle), input (slider drag/arrow-key, or text edits), submit (Enter in a text field), scroll (a scrollable group), move (a drag-to-move panel), hover, key, and dismiss.

Theming and motion

A scene-wide theme (accent color, text color, muted color, corner radius, font) cascades to every element that doesn't set its own value explicitly. Set anim: true (the default) and Keybind eases the window's fade-in/out, a toggle's knob slide, and hover fills instead of snapping them.

Drag and scroll

Set draggable: true on scene_open to let the user reposition the whole panel by its background; mark any group scroll: true with a fixed height to get a scrollable, mouse-wheel-driven viewport with a proportional scrollbar.

Building panels faster

The bundled modules/scene-kit helper module wraps common panel patterns — buttons, forms, and themed containers — as builder functions on top of scene_*, so you don't have to hand-author every element map for a typical settings panel or picker.

Gated by the display capability — the same one screen_freeze/screenbuf_*/color_pick_screen already use, so a script using scene_* on its own doesn't need a new capability grant.

> Full element reference, every option, and worked examples: see lib-scene in the Function > Library, or the KSL spec that ships with the app.

We use cookies for analytics to understand how the site is used. Functional cookies (your session) are always on. Privacy Policy.