Add Remote Braille IPC to the host and both SDKs
remote.braille requests and events carry a typed op under a braille-stream lease: the controller's width and gestures for a controlled reader, rendered cells back to its child, and cells, local geometry and display gestures for a controller. Direction is validated per role; a full mailbox revokes the lease. No display owner is attached yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
477d860fb8
commit
2651b5e9bd
10 files changed
+476
-3
No files matched your search
@@ -166,6 +166,48 @@ def valid_remote_focus_request(request):
|
||||
return False
|
||||
|
||||
|
||||
def valid_remote_braille(value, role=None, request=None):
|
||||
"""Validate one Remote Braille operation; role/request also check direction."""
|
||||
try:
|
||||
_fields(value, ("op",), ("width", "gesture", "index", "cells"))
|
||||
op = value["op"]
|
||||
width, gesture, index = value.get("width", 0), value.get("gesture", ""), value.get("index", 0)
|
||||
cells = value.get("cells")
|
||||
if type(width) is not int or type(index) is not int or not isinstance(gesture, str):
|
||||
return False
|
||||
if op in ("size", "geometry"):
|
||||
ok = 0 <= width <= 4096 and gesture == "" and index == 0 and cells is None
|
||||
elif op == "gesture":
|
||||
ok = (width == 0 and cells is None
|
||||
and (gesture in ("pan-left", "pan-right") and index == 0
|
||||
or gesture == "route" and 0 <= index < 4096))
|
||||
elif op == "cells":
|
||||
ok = (isinstance(cells, list) and 1 <= len(cells) <= 4096
|
||||
and all(type(cell) is int and 0 <= cell <= 255 for cell in cells)
|
||||
and width == 0 and gesture == "" and index == 0)
|
||||
else:
|
||||
return False
|
||||
if not ok or role is None:
|
||||
return ok
|
||||
if role == "controlled":
|
||||
return op in ("size", "gesture") if request else op == "cells"
|
||||
if role == "controller":
|
||||
return (op == "cells" or op == "geometry" and width == 0) if request else op in ("gesture", "geometry")
|
||||
return False
|
||||
except (ProtocolError, TypeError, ValueError):
|
||||
return False
|
||||
|
||||
|
||||
def valid_remote_braille_request(request):
|
||||
"""Validate remote.braille parameters; display effects remain owned by core."""
|
||||
try:
|
||||
_fields(request, ("lease", "epoch", "sequence", "braille"))
|
||||
return (_token(request["lease"]) and _positive(request["epoch"])
|
||||
and _positive(request["sequence"]) and valid_remote_braille(request["braille"]))
|
||||
except (ProtocolError, TypeError, ValueError, UnicodeError):
|
||||
return False
|
||||
|
||||
|
||||
REMOTE_FOCUS_REASONS = frozenset(("requested", "escape", "local", "unavailable"))
|
||||
|
||||
|
||||
@@ -358,11 +400,12 @@ class SessionClient:
|
||||
waiter.put_nowait(value)
|
||||
|
||||
def _event(self, event):
|
||||
_fields(event, ("sequence", "kind", "epoch"), ("action", "lease", "role", "grants", "reason", "speech", "input", "focus"))
|
||||
_fields(event, ("sequence", "kind", "epoch"), ("action", "lease", "role", "grants", "reason", "speech", "input", "focus", "braille"))
|
||||
if not _positive(event["sequence"]) or not _positive(event["epoch"]):
|
||||
raise ProtocolError("Invalid event sequence")
|
||||
if (event["kind"] != "remote.input" and "input" in event
|
||||
or event["kind"] != "remote.focus" and event.get("focus", "") != ""):
|
||||
or event["kind"] != "remote.focus" and event.get("focus", "") != ""
|
||||
or event["kind"] != "remote.braille" and "braille" in event):
|
||||
raise ProtocolError("Invalid session event")
|
||||
if event["kind"] == "remote.action":
|
||||
grants = event.get("grants")
|
||||
@@ -386,6 +429,14 @@ class SessionClient:
|
||||
or event.get("reason", "") != "" or "speech" in event
|
||||
or not valid_remote_captured_key(event.get("input"))):
|
||||
raise ProtocolError("Invalid input event")
|
||||
elif event["kind"] == "remote.braille":
|
||||
braille = event.get("braille")
|
||||
if (not _token(event.get("lease")) or event.get("action", "") != ""
|
||||
or event.get("role", "") != "" or event.get("grants", []) != []
|
||||
or event.get("reason", "") != "" or "speech" in event
|
||||
or not (valid_remote_braille(braille, "controlled", False)
|
||||
or valid_remote_braille(braille, "controller", False))):
|
||||
raise ProtocolError("Invalid Braille event")
|
||||
elif event["kind"] == "remote.focus":
|
||||
if (not _token(event.get("lease")) or event.get("action", "") != ""
|
||||
or event.get("role", "") != "" or event.get("grants", []) != []
|
||||
|
||||
Reference in new issue
Block a user