Quick navigation

Go to

Input & controls

WebUI selective keyboard capture

Capture Escape and navigation keys in a WebUI while keeping movement and mouse look active. Supported keys, permissions, errors and focus cleanup.

2 min read429 wordsMarkdown
On this page2 sections

Use page:setConsumedKeys(keys) to reserve selected keyboard keys for a WebUI while keeping movement and mouse look active. Key consumption is client-local, per surface, and requires webui.keep_input.

Check that page.setConsumedKeys exists before enabling this mode on clients with different API capabilities. If unavailable, disable the mode or require a compatible client. Keep-input alone does not prevent the native pause menu from opening.

-- Manifest: permissions { "webui.keep_input" }
local page = assert(WebUI.create({entry = "web/menu.html", layer = "hud"}))
page:on("menu:back", function()
    -- Navigate back in your UI here, or close the top-level menu:
    page:setFocus(false, false)
    page:hide()
end)
assert(page:setConsumedKeys({"escape"}))
assert(page:setFocus(true, false, true)) -- keyboard, no cursor, keep gameplay

The page still receives ordinary browser keydown/keyup events. Consumed keys are withheld from Cyberpunk's native input AND Open77's pause/scoreboard shortcuts. Other keys and raw mouse movement retain the existing keepGameInput behavior. A consumed press keeps its repeats and release consumed even when its handler releases focus, hides or destroys the page; the next press works normally.

document.addEventListener("keydown", (event) => {
  if (event.key !== "Escape" || event.repeat) return;
  event.preventDefault(); // browser behavior, not native input interception
  Open77.emit("menu:back", {});
});
Open77.ready();

Contract

page:setConsumedKeys(keys) returns true, or false, reason. It atomically replaces the surface's list; invalid input leaves the previous list unchanged. page:setConsumedKeys({}) removes the selection for future presses. Configure it before acquiring focus, not after receiving the key in JavaScript.

  • A dense Lua array of at most 32 strings; duplicates are harmless.
  • Names are case-insensitive: escape (esc), enter, tab, backspace, space, up, down, left, right (also arrowup, arrowdown, arrowleft, arrowright), home, end, pageup, pagedown, insert, delete.
  • Unknown keys, mouse buttons, controller buttons and arbitrary action names are rejected. These are navigation keys, not a replacement for gameplay action APIs.
  • The policy is active only on its visible, presentation-enabled, keyboard-focused page. A cursor-only page does not capture keys. Hiding/destroying the page or stopping its resource cannot retain a new-key input lock. Regaining focus on the same page reuses its configured list; newly created pages start with an empty list.
  • No additional permission beyond normal WebUI access; keepGameInput=true still requires webui.keep_input. Full keyboard capture without keep-input is unchanged.
  • Errors: invalid_consumed_keys, too_many_consumed_keys, unsupported_consumed_key, webui_key_capture_unavailable, webui_surface_unavailable. A stale/destroyed page handle follows the usual WebUI handle validation rules.

Why browser cancellation is insufficient

Cyberpunk receives keyboard Raw Input separately from the legacy keyboard events forwarded to Chromium. preventDefault() / stopPropagation() only affect the browser; with setFocus(true, false, true), the native stream remains enabled. Open77.session.setMenuReady(true) signals that the platform pause UI is ready; it is not a per-resource Escape blocker and should not be used for this purpose.

For a menu that also uses arrows, Enter and Tab:

assert(page:setConsumedKeys({"escape", "enter", "tab", "up", "down", "left", "right"}))
assert(page:setFocus(true, false, true))

Without setConsumedKeys, existing keep-input behavior remains unchanged. This API does not disable pause globally or intercept a controller's menu button. The debug command webui.input exposes a cumulative consumed message counter for diagnosing the native routing independently of browser event delivery.

// For agents & LLMsthis page as Markdownllms.txtllms-full.txt

// Guides Β· Lua API

Search the docs

1,905 guides and functions indexed

Try