Add quarantined Xorg destination-key ownership and cleanup
This commit is contained in:
1 parent
792cac5d0b
commit
cd9ae05bbe
10 files changed
+988
-29
No files matched your search
@@ -35,8 +35,9 @@ allowlist matches the external mapper's canonical subset:
|
||||
|
||||
Aliases such as `Prior`, uppercase text, shifted character names, AltGr,
|
||||
dead/IME keys, arbitrary Unicode and unrecognized names remain unsupported.
|
||||
For exact case/spelling, see `ValidRemoteKey` in
|
||||
`internal/tentaclewire/remote_key.go`. No implicit modifier transitions, text
|
||||
For exact case/spelling, see `input.ValidRemoteKeyName` in
|
||||
`internal/input/remote_key_names.go`, used by `ValidRemoteKey` in the wire/SDK
|
||||
layer. No implicit modifier transitions, text
|
||||
insertion or fallback commands are synthesized.
|
||||
|
||||
Go exposes `RemoteKey`, `RemoteKeyRequest`, `ValidRemoteKey` and
|
||||
@@ -105,6 +106,11 @@ concurrent idempotent release, overflow and retirement/replacement. The external
|
||||
bridge verifies that every canonical mapper result satisfies the public SDK
|
||||
contract. None of these tests injects a desktop key.
|
||||
|
||||
An unconnected [destination-key prerequisite](testing/remote-key-target.md) now
|
||||
retains native codes through layout changes and uncertain effects, with a
|
||||
quarantined Xorg resolver/backend. It is not attached to this mailbox and supplies
|
||||
no independent process/watchdog cleanup or physical collision guarantee.
|
||||
|
||||
No capture event API, production Xorg input owner, independent native cleanup
|
||||
helper, core escape/bypass integration or installed Remote keyboard command is
|
||||
provided. Physical-source approval, physical collision/recovery, audible speech,
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
This is an isolated prototype and a record of limitations, not a Remote input
|
||||
implementation. No reader input behavior or installed executable changes.
|
||||
A subsequent [Go destination-key prerequisite](remote-key-target.md) now supplies
|
||||
stored-code ownership, retryable cleanup and a quarantined native resolver. It
|
||||
does not inherit this Python prototype's independent EOF/watchdog behavior and
|
||||
is not attached to production input.
|
||||
The source baseline is `a47253d697c1aa44dea80646cad99a4fe163c7f1` on `testing`,
|
||||
with the existing secret-entry work preserved. The branch was checked against
|
||||
its upstream on 2026-11-03 before these tests were added.
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# Quarantined Remote destination-key prerequisite
|
||||
|
||||
The reader has a destination-key ledger and an unconnected Xorg backend.
|
||||
`internal/input/remote_key_ledger.go` owns at most 32 native destination codes;
|
||||
`internal/platform/xorg/remote_keys.go` resolves and applies the supported
|
||||
logical keys on a dedicated X connection. No production code constructs this
|
||||
target, and no reader input owner is attached to `remote.key`. The Remote
|
||||
command still discards relay keyboard traffic and offers no keyboard grant.
|
||||
|
||||
This is a native prerequisite, not a usable input service. It must remain
|
||||
quarantined until independent helper cleanup, input provenance and physical
|
||||
collision handling are established.
|
||||
|
||||
## Ownership and cleanup
|
||||
|
||||
One ledger belongs to one serial native owner and helper lifetime. Its caller
|
||||
must validate the original lease immediately before each effect, retire on
|
||||
cancellation, and finish cleanup before allowing replacement input. The ledger
|
||||
itself neither issues consent nor checks lease epochs. It must not be shared
|
||||
between leases or mutated concurrently.
|
||||
|
||||
A new logical down resolves one destination code and rejects invalid codes,
|
||||
another owned name resolving to that code, or an already-held server key. It
|
||||
reserves the code before attempting the down, because a native failure can leave
|
||||
the outcome uncertain. Duplicate downs are idempotent and perform no additional
|
||||
injection; native repeat fidelity remains unfinished. An unowned up performs
|
||||
no native operation. An owned up uses its reserved code without resolving the
|
||||
name again, including after layout/Num Lock changes.
|
||||
|
||||
Mapping failure, collision, capacity overflow or native failure stops admission.
|
||||
`Retire` attempts every owned up in reverse down order. Successful ups are
|
||||
removed; failed ups retain their exact code and original relative order for
|
||||
explicit cleanup retry. Retirement never resumes admission. Backend errors
|
||||
become constant local errors, without native diagnostic text or key names.
|
||||
|
||||
The native wrapper closes its connection only after successful ledger cleanup.
|
||||
Failed cleanup leaves the connection and pending identities available for retry.
|
||||
Opening replacement input must wait for confirmed old cleanup; a new consent
|
||||
epoch does not make an old native release harmless. Closing an XTEST connection
|
||||
or killing this process does not release held keys. The earlier
|
||||
[Python feasibility harness](remote-input-feasibility.md) demonstrates that
|
||||
limitation; its separate EOF/watchdog mechanism is not implemented by this Go
|
||||
target.
|
||||
|
||||
## Native resolution and limits
|
||||
|
||||
The logical-key vocabulary now belongs to `input.ValidRemoteKeyName`; the wire
|
||||
and Go SDK validators delegate to it, preserving the existing IPC schema and
|
||||
Python conformance. Native input therefore uses the same bounded names as the
|
||||
public SDK, without depending on the Tentacle wire package.
|
||||
|
||||
The backend fetches a fresh XKB map/state for each new resolution and requires
|
||||
one unambiguous matching destination code. It supports group zero only;
|
||||
nonzero groups are unavailable. Shift/Caps state is removed for logical base-key
|
||||
resolution while Num Lock is retained. Shift-only punctuation, unavailable or
|
||||
ambiguous symbols are rejected. It does not synthesize modifiers, assume a
|
||||
Windows scan code equals an X code, or rewrite the global keymap. The private
|
||||
fixture changes maps and lock state explicitly to exercise these cases.
|
||||
See the [XKB library specification](https://xorg.freedesktop.org/archive/current/doc/libX11/XKB/xkblib.html)
|
||||
for `XkbGetMap`, `XkbGetState` and `XkbTranslateKeyCode`.
|
||||
|
||||
Lock-key downs are unavailable until lock synchronization and reader modifier
|
||||
handling have a defined policy. This includes Caps Lock even when a reader
|
||||
configuration would otherwise use it as a modifier. AltGr, IME/dead keys,
|
||||
general group/level handling and exact remote autorepeat remain unfinished.
|
||||
|
||||
The already-held-key check is not atomic with injection. A later physical or
|
||||
other-client press of an owned code is not separately represented by the global
|
||||
bitmap. This backend cannot preserve that press during cleanup. Fresh map reads
|
||||
also do not freeze configuration changes by other clients. No physical-device,
|
||||
concurrent-map-change or same-code collision guarantee is claimed.
|
||||
|
||||
All native wrapper methods require one serial caller on a locked OS thread.
|
||||
Xlib calls and the error guard can block or terminate a process after X-server
|
||||
failure. The future production target must run in an independent helper, with
|
||||
bounded inherited-descriptor IPC, watchdog/EOF cleanup, exclusive ownership,
|
||||
provenance, policy cancellation and explicit failure reporting. Do not attach
|
||||
this synchronous wrapper to the reader event loop or directly to its mailbox.
|
||||
|
||||
## Private verification
|
||||
|
||||
From the reader checkout:
|
||||
|
||||
```sh
|
||||
go test -race ./internal/input ./internal/tentaclewire -count=1
|
||||
python3 -B tests/native_remote_keys.py
|
||||
python3 -B tests/native_remote_input.py
|
||||
```
|
||||
|
||||
The new harness requires Go, Python, Xvfb, private D-Bus and `setxkbmap`. It starts
|
||||
a 24-bit Xvfb server before private D-Bus using `native_test_session.py`, with a
|
||||
disposable runtime directory. It never uses the active reader, display or
|
||||
accessibility bus. Missing dependencies fail the harness rather than count as
|
||||
skipped acceptance. The native tests skip in ordinary unflagged Go suites;
|
||||
only an actual harness run establishes their private results.
|
||||
|
||||
Unit tests cover stored-code releases, idempotent downs, unowned ups, alias and
|
||||
preexisting collisions, constant errors, held-key limits, uncertain down/up
|
||||
outcomes, partial cleanup and retry order. Six new native Go race tests verify
|
||||
owned modifier cleanup, preservation of an already-held key from another
|
||||
synthetic client, US/German map replacement, Num Lock changes, unsupported-group
|
||||
and shift-only-symbol rejection, and lock-key refusal. They inspect server key
|
||||
state, not application command delivery or hardware behavior.
|
||||
|
||||
The new native harness, existing ten-experiment/six-native-test feasibility
|
||||
harness, input/wire/Xorg race suites, focused host keyboard/lifecycle race tests,
|
||||
external Remote race suite, affected-package vet, a separate reader build,
|
||||
the existing speech regression harness and Tentacles `make check` passed.
|
||||
No full reader suite, installed-binary behavior,
|
||||
audible speech, physical input/Braille or live NVDA/Orca acceptance was performed.
|
||||
Reference in new issue
Block a user