simvx.core.input.web_events

Decode the browser input wire format into :class:InputRouter calls.

Two paths deliver input from a browser: the exported static page (simvx.web) and the streaming dev client (simvx.graphics.streaming). Both page scripts serialise the same JSON events, so both decode here.

Event shapes, all keys optional with the defaults shown:

================ ==================================================== key code (engine key code), pressed, repeat char codepoint pointer id, ptype (mouse/touch/pen), primary, phase (0=down, 1=up, 2=move, 3=cancel, 4=enter, 5=leave), x, y, button (DOM ordering, -1 for none), buttons (the DOM bitmask), pressure, tiltX/tiltY and twist in degrees, tangentialPressure, width/height of the contact in engine units, or dx/dy with relative under pointer lock scroll dx, dy (positive dy scrolls up) focus focused; only false carries information controllers pads: the whole pad list this frame (see below) capabilities one key per :mod:~simvx.core.input.capabilities fact the page queried, each a bool ================ ====================================================

A pointer with phase 3 is the system taking the pointer away: the browser fires pointercancel for an edge gesture, a notification, or a gesture the page chrome decided to own. A focus event with focused: false is the page losing input, sent from blur and from visibilitychange; regaining focus needs no event, because nothing is held on the way back in.

A pad is polled, not delivered. navigator.getGamepads() is a snapshot the page reads in its frame callback, so one controllers event carries every pad the page can see and a pad missing from it has gone: the decode is one poll transaction, exactly as a desktop backend’s is, and unplugging a controller releases what it held. A page that has never seen a pad sends no event at all, which is the difference between “no pads” and “cannot see pads”: an empty snapshot from a page that never polls would read as every pad leaving at once.

Each entry in pads is index (the browser’s slot, which is the pad id), id (what the browser calls the device), mapping ("standard" when the browser has laid the device out as a controller), pressed (one 0 or 1 per button), buttons (one value per button, which is how an analog trigger reports) and axes.

The wire is older than the pages sending it. A page exported before the pointer event existed speaks the three the DOM had then, and those bundles are static files nobody re-exports, so they are decoded here too:

=========== ========================================================= mouse button (DOM ordering), pressed mousemove````x/y, or dx/dy with relative under pointer lock touch id, action (0=down, 1=up, 2=move, 3=cancel), x, y, pressure =========== =========================================================

Any event may carry ctrl/shift/alt/meta modifier flags, and a time: the DOM event’s own timeStamp verbatim, in milliseconds on the page’s performance.timeOrigin clock. A page that sends none leaves the event to be stamped at receipt, which is what a page exported before the field existed does.

Module Contents

Functions

browser_pad_guid

The stable device id inside a browser pad’s id string, or “”.

route_browser_events

Route a batch of browser input events through router.

Data

API

simvx.core.input.web_events.log

‘getLogger(…)’

simvx.core.input.web_events.browser_pad_guid(pad_id: str) → str[source]

The stable device id inside a browser pad’s id string, or “”.

The Gamepad API gives a slot index and a descriptive string, and the index is not identity: a controller unplugged and plugged back in can land in a different slot, and a game that keyed a rebinding on the slot would hand player two’s controls to player one. The string is what survives, and the part of it that is an identity rather than a description is the vendor and product the browser prints into it, which this returns as "045e:028e".

A browser that prints neither gets "", the same answer a backend with no concept of a device id gives, and the same meaning: this pad has no identity to save a rebinding against, so a per-controller setting for it lasts the session. Inventing one from the slot would be worse than having none, because it would look stable and would not be.

The spelling is deliberately not SDL’s thirty-two hex digits. The browser cannot supply the bus, version and driver those encode, and a value shaped like an SDL GUID would claim a desktop rebinding file applies here.

simvx.core.input.web_events.route_browser_events(router: simvx.core.input.router.InputRouter, events: collections.abc.Iterable[dict[str, Any]]) → None[source]

Route a batch of browser input events through router.

Args: router: The :class:InputRouter bound to the running scene tree. events: Decoded JSON event objects, in the order the page sent them.

simvx.core.input.web_events.__all__

[‘browser_pad_guid’, ‘route_browser_events’]