simvx.graphics.platform._sdl3

SDL3 windowing backend with multitouch and pen support.

Module Contents

Classes

Sdl3Backend

WindowBackend implementation using SDL3.

Data

API

simvx.graphics.platform._sdl3.__all__

[‘Sdl3Backend’]

simvx.graphics.platform._sdl3.log

‘getLogger(…)’

class simvx.graphics.platform._sdl3.Sdl3Backend

WindowBackend implementation using SDL3.

Provides keyboard, mouse, and multitouch input. Touch events are delivered with window-relative coordinates via the touch_callback.

SDL is the most forthcoming of the three desktop backends about an event beyond its identity. Every event carries the time SDL received it, in nanoseconds since SDL initialised, which :class:EventClock maps onto the monotonic clock the engine measures with; a key, a mouse button and a finger each name the device they came from; and the layout keycode beside the scan code says what the key prints, which the scan code deliberately does not.

It is also the one that reports a pen, as a pointer of its own through the pen callback: hovering, touching, its barrel buttons, the eraser end, and every axis the tablet measures. SDL sends the axes as their own SDL_EVENT_PEN_AXIS events rather than as fields on the motion, so the last value of each is held per stylus and travels with the next event from it, and an axis the stylus never reported travels as “not measured”. SDL also synthesizes a mouse and a finger from a pen, and a mouse from a finger; all three are dropped, because the real pointer is already delivered and each stroke and tap would otherwise arrive twice.

Initialization

supports_controllers

True

supports_rumble

True

create_window(width: int, height: int, title: str, *, visible: bool = True) → None
create_graphics_surface(instance: Any) → Any
get_required_instance_extensions() → list[str]
poll_events() → None
should_close() → bool
get_framebuffer_size() → tuple[int, int]
get_window_size() → tuple[int, int]
get_content_scale() → tuple[float, float]
set_title(title: str) → None
set_key_callback(callback: simvx.graphics.platform._base.KeyCallback | None) → None
set_mouse_button_callback(callback: simvx.graphics.platform._base.MouseButtonCallback | None) → None
set_cursor_pos_callback(callback: simvx.graphics.platform._base.CursorPosCallback | None) → None
set_scroll_callback(callback: simvx.graphics.platform._base.ScrollCallback | None) → None
set_char_callback(callback: simvx.graphics.platform._base.CharCallback | None) → None
set_resize_callback(callback: collections.abc.Callable[[int, int], None] | None) → None
set_focus_callback(callback: collections.abc.Callable[[bool], None] | None) → None

Set the window focus callback. Receives True on gain, False on loss.

property paused: bool

Whether the app is paused (backgrounded on mobile).

set_lifecycle_callback(callback: collections.abc.Callable[[str], None] | None) → None

Set lifecycle event callback. Receives ‘paused’ or ‘resumed’.

set_touch_callback(callback: simvx.graphics.platform._base.TouchCallback | None) → None

Set the finger callback: (finger_id, phase, x, y, pressure) in window pixels.

set_pen_callback(callback: simvx.graphics.platform._base.PenCallback | None) → None

Set the pen callback: (pen_id, phase, x, y) and the axes the stylus measured.

get_cursor_pos() → tuple[float, float]
set_cursor_shape(shape: simvx.core.input.enums.CursorShape) → None

Show shape, creating each system cursor once and keeping it for the window’s life.

set_mouse_capture(mode: int) → None

Apply a MouseCaptureMode int (0=visible, 1=hidden, 2=captured, 3=confined) to the OS cursor.

Each SDL symbol is guarded with getattr: the sdl3 binding may not expose all of them, in which case the call is skipped (debug-logged) rather than crashing.

Under CAPTURED, relative mode is enabled and poll_events integrates the per-event xrel/yrel into a virtual cursor position (self._relative), so the shared delta path tracks motion while the OS cursor is locked.

set_window_size(width: int, height: int) → None
request_close() → None
poll_controllers() → list[simvx.graphics.platform._base.PadReport]

Poll all connected controllers, one entry per pad found.

Each pad is opened once and its handle held until the pad goes away or the window is destroyed. Opening and closing per poll would make SDL generate a connect and a disconnect event every frame and throw both away, and it costs a device open sixty times a second per controller.

SDL reports sticks as signed 16-bit and triggers as 0..32767;

Func:

controller.normalise_axes maps both onto the engine’s convention.

rumble_controller(pad_id: int, strong: float, weak: float, duration: float) → bool

Run the motors on the pad poll_controllers reported as pad_id.

SDL names the two motors by frequency rather than by weight: the low one is the heavy off-centre mass a game means by “strong”. Both magnitudes are 16-bit and the duration is milliseconds, so the engine’s 0-to-1 and seconds are scaled here rather than at the call site, the same way the axis ranges are.

False for a pad this backend has no open handle for, and for a pad whose hardware has no motors: SDL answers that, and the answer travels back unchanged so a game can tell rumble from silence.

destroy() → None