Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

surface

Active input-surface classification. Answers "what device class is the player using right now" — "touch" or "kbm" — and notifies on change; backs Zin.surface. Virtual touch controls mount whenever the surface is "touch", in edit and play alike.

The frame rule

Resolution runs once per engine frame from the Zin.tick pipeline: a per-event observer collects which device classes produced events this frame, and the frame resolver applies one rule — touch wins a frame that contains any touch event. The primary touch contact also drives the mouse path (a projected mouse.down/move/up in the same frame), so classifying by the latest single event would flip to kbm on every tap; the frame rule keeps projection-generated mouse events from masking the touch that caused them.

Capability default

Before any input arrives, the class defaults to "touch" on sessions with a touch source (touch_capable — latched by the first contact or declared at boot by Android / the web client) and "kbm" otherwise, so touch-first devices present touch controls from the first frame.

Exports

  • M.current() -> string — the active surface class, "touch" or "kbm".
  • M.onChange(fn: (string, string?) -> ()) -> number — subscribe to class flips; fn(now, prev) where prev is the previously reported class (the first-tick capability default when no event had resolved yet). Returns a handle.
  • M.off(handle: number) -> boolean — unsubscribe an onChange handle.
  • M._beginFrame() — internal: clear this frame's per-class flags; wired by Zin.tick.
  • M._observeEvent(ev: any) — internal: per-event observer; wired by Zin.tick.
  • M._resolveFrame() — internal: resolve this frame's class and fire onChange on a flip; wired by Zin.tick.
  • M._reset() — test-only: clear resolution state and subscriptions.

Types:

  • SurfaceClass = "touch" | "kbm"

Usage

local Surface = require("@builtin::modules.zinput.surface")

if Surface.current() == "touch" then
    showTouchOverlay()
end

Surface.onChange(function(now, prev)
    print("surface flipped to", now)
end)

Notes

  • onChange fires from the Zin.tick pipeline on the frame the class flips; without a tick, resolution never advances and current() keeps returning the capability default.
  • The change signal compares against the last reported class, whose initial value is the capability default captured on the first tick of the session — a phone's first contact confirms the default silently, while a desktop touchscreen's first contact reports kbm→touch.
  • Handler errors during onChange dispatch are caught and logged, not propagated.