SolarOS

SolarOS 4.17.7 manual · api

Python input and clipboard API

API overview · Lua input and clipboard

solaros.hid

service.hid is retained as a dormant package and is not compiled into the standard SolarOS flavors because the TinyUSB composite stack currently costs too much internal SRAM. On an ESP32-S3 build that explicitly enables it, USB remains a composite device: the existing cdc0 serial interface is accompanied by standard keyboard, mouse, and gamepad HID reports. The API is typed; scripts cannot replace descriptors or send arbitrary report bytes.

from solaros import hid

hid.keyboard.press(hid.KEY_LEFT_CTRL, hid.KEY_C)
hid.keyboard.release_all()

hid.mouse.move(10, -4)
hid.mouse.button(hid.MOUSE_LEFT, True)
hid.mouse.button(hid.MOUSE_LEFT, False)

hid.gamepad.axis(hid.AXIS_X, -12000)
hid.gamepad.button(1, True)
hid.gamepad.hat(hid.HAT_UP)
hid.gamepad.send()

Calls raise OSError("ESP_ERR_INVALID_STATE") while USB is disconnected or HID is unavailable. SolarOS emits neutral keyboard, mouse, and gamepad reports when the Python runtime exits, is interrupted, or is force-stopped.

solaros.clipboard

The clipboard is PSRAM-backed and shared with SolarOS apps that use the clipboard service.

Example:

import solaros

solaros.clipboard.set(b"hello from python")
print(solaros.clipboard.get())

solaros.input

When service.input-keymap is included, solaros.input.load_keymap(name, path) loads a validated JSON mapping file for the named attachment, and solaros.input.reset_keymap(name) restores its built-in map. Both return None; failures raise an exception. Applying a map releases held keys. Mappings last until detach or reboot; a startup script can reload a saved file. solaros.input.keymap_info(name) reports whether a source supports mapping, physical keys, modifiers, layers, and tap/hold, together with key count and optional matrix metadata. Other drivers currently report supported=false. See source keymaps for fields and mapping formats.

Touchscreens report tap, double-tap, hold, swipe, and edge-swipe gestures in addition to pointer events. Use GESTURE_TAP, GESTURE_DOUBLE_TAP, GESTURE_HOLD, GESTURE_SWIPE, and GESTURE_EDGE_SWIPE to match their numeric gesture values. See man media.input for timing, direction, and recognition limits.

Foreground scripts can receive generic pointer, axis, and gesture events routed to their active session. sources() lists registered input sources with source, name, source_class, source_class_name, capabilities, and ready.

Pointer dictionaries have type="pointer", source metadata, pointer_id, numeric and named mode/action, x, y, delta_x, delta_y, buttons, and target. Touch and other absolute sources use x/y; relative mice use the deltas. Axis dictionaries have type="axis", source metadata, numeric and named axis, value, and delta. Gesture dictionaries have type="gesture", numeric and named gesture and direction, flags, a source-specific value, and the original sensor raw word. AirWheel values are signed counter steps; 32 steps approximate one revolution.

import solaros
from solaros import input as device_input

device_input.clear()
while not solaros.should_exit():
    event = device_input.read(100)
    if event is None:
        continue
    if event["type"] == "pointer":
        if event["mode"] == device_input.MODE_ABSOLUTE:
            print("touch", event["action_name"], event["x"], event["y"])
        else:
            print("mouse", event["delta_x"], event["delta_y"], event["buttons"])
    elif event["type"] == "axis":
        print("axis", event["axis_name"], event["value"], event["delta"])
    else:
        print("gesture", event["gesture_name"], event["direction_name"])

The queue holds 16 events. When it is full, the oldest event is discarded so the script receives current pointer state; inspect status()["dropped"] when loss matters. Event reads are available only to a foreground Python app. Agent or other headless source runners report available=False and return None. Keyboard characters and navigation keys remain available through solaros.tui.getch().

Local keyboard capture

Foreground scripts can exclusively capture one ready named key-event source:

Actions are KEY_PRESS, KEY_RELEASE, and KEY_REPEAT. Modifier bits follow USB HID order (left Ctrl, Shift, Alt, GUI, then their right counterparts); MOD_CTRL and MOD_ALT match either side.

Captured input bypasses local focus switching and the usual app-exit key. The script must implement its own exit chord and check should_exit(). Capture applies to the named local source even when another session has input focus. Port characters and other sources keep their normal routing. Headless runners cannot claim a keyboard. Runtime exit and forced stop release the claim automatically; use try/finally for normal cleanup.

The capture queue holds 32 events. Overflow discards queued events and delivers {"type": "reset"} before subsequent keys. Source release, readiness loss, and detach also deliver a reset. Release any forwarded held keys on reset; detach ends capture of that source, including if its source ID is reused.

Quick reference

Use solaros.input, solaros.hid, solaros.clipboard for input and clipboard. See man python for runtime conventions and service availability.