Skip to content

Add the cooperative geometry port (WHERE), the escape hatch for layout.gadget children - #78

Merged
sidick merged 3 commits into
mainfrom
where-port
Aug 9, 2026
Merged

sidick merged 3 commits into
mainfrom
where-port

Conversation

@sidick

@sidick sidick commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Implements issue Cooperative geometry port (WHERE): escape hatch for layout.gadget-nested gadgets #49: layout.gadget children are permanently invisible to structural walking on classic AmigaOS 3.x (the project's own documented "Confirmed limit"), so no plain GADGET manifest entry — or quirk profile — could ever address them.
  • Manifest format v2 adds WHEREPORT <port-name> and WHEREGADGET <name> <window>: a gadget resolved not by GA_ID but by querying a small, optional ARexx port the application itself exposes, reporting its own live GetAttr(GA_Left/GA_Top/GA_Width/GA_Height) geometry.
  • CLICK @name/TYPE @name route through that query automatically and then act with a genuine input.device click (AmipClickWindowRelative()) — discovery is cooperative, but actuation stays real input, unlike MUIREXX, where the target's own port does the acting too. A new standalone WHERE @name [TIMEOUT=<n>] verb is the diagnostic/test probe. GETTEXT/DRAG have no WHERE-based path — an honest RC 10 "geometry only" limit, not a silent fallback.
  • fixtures/classact-app now implements a real CAAPP.WHERE port; its manifest (previously naming zero gadgets, as the honest example of this exact limit) now addresses all three of its gadgets via WHEREGADGET. CAApp.golden is unchanged, confirming the walker's own view of the window genuinely didn't change.
  • A real bug found and fixed building this: a hand-built RexxMsg (CreateRexxMsg/FillRexxMsg/PutMsg, the same recipe MUIREXX's own AmipMuiRexxSend() already uses) arrives at the receiver with its node type left at NT_MESSAGE, not NT_REPLYMSG — rexxsyslib.library's own IsRexxMsg() rejects it despite every other field being correct. Root cause: IsRexxMsg() checks ln_Type == NT_REPLYMSG, which ReplyMsg() sets — the right question for a sender inspecting its own reply, not a receiver validating an incoming, not-yet-answered command (confirmed by ruling out two sender-side fixes live: pre-marking ln_Type before sending, and a genuine CreateArgstring()-backed rm_Args[0]). RXCOMM is the field that actually means "command invocation," and every sender here already sets it correctly. CAAPP.WHERE now validates incoming messages with rm_Action & RXCOMM instead — a completely ordinary, one-condition receive-loop check, not a dedicated-port special case, so any third-party ARexx port (including AmiAuth's own) can implement WHERE with the same one-line change. Full account in server/README.md's WHERE section and tests/copperline/README.md.

Test plan

  • make amiga fixtures server — clean build under -Wall -Wextra -Werror (via make docker)
  • make test-host — 234 host tests pass (the sole unrelated failure, missing pytest module, is a pre-existing local-environment gap, not a regression)
  • tests/copperline/run.sh's new run_where_check — verified live against real Copperline: WHERE geometry sanity, unknown-name/GETTEXT-limit rejections, TYPE @host_field landing text in a layout child (confirmed via the fixture's own log line, since GETTEXT can't read it back), and CLICK @connect_button genuinely closing the window
  • Regression pass on run_click_check/run_type_check/run_manifest_check/run_wire_check (the shared manifest-resolution code path this PR touches) — all still pass
  • CAApp.golden byte-identical (run_golden_check) — confirms the walker's own view is unaffected

🤖 Generated with Claude Code

https://claude.ai/code/session_018CbPo4nMpnM5JQX3LKE5JP

sidick and others added 3 commits August 9, 2026 11:35
…t.gadget children (#49)

layout.gadget children are permanently invisible to structural walking
on classic AmigaOS 3.x, so no plain manifest entry could ever address
them. This adds manifest format v2 (WHEREPORT/WHEREGADGET), a new
WHERE verb, and routes CLICK/TYPE @name through an app's own
cooperative ARexx port for geometry while still acting with real
input.device input -- verified end to end against a new CAAPP.WHERE
port on fixtures/classact-app, whose three gadgets previously had no
manifest entry at all.

Along the way, found and fixed a real gap: a hand-built RexxMsg
(CreateRexxMsg/FillRexxMsg/PutMsg, the same recipe MUIREXX already
uses) arrives with ln_Type left at NT_MESSAGE, causing
rexxsyslib.library's own IsRexxMsg() to reject it even though the
message is otherwise correct -- invisible in the existing MUIREXX
check only because MUI-Demo never calls IsRexxMsg() on what it
receives.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CbPo4nMpnM5JQX3LKE5JP
…RexxMsg send

Investigated whether the WHERE port's own receiver could stay a fully
standard, unmodified ARexx port (IsRexxMsg()-gated, no special
knowledge required) by fixing the sender instead -- tried both the
commonly-cited ln_Type = NT_REPLYMSG pre-marking and a genuine
CreateArgstring()-backed rm_Args[0] in AmipWhereQuery(). Neither
changed the outcome: PutMsg() itself resets the node type regardless
of what's set beforehand, so a message built via CreateRexxMsg()/
FillRexxMsg()/PutMsg() from ordinary C code cannot be made
indistinguishable from a live ARexx interpreter's own send by any
public API tried. No functional change (where.c is back to its prior
form) -- just recording the investigation so this isn't re-attempted,
and being explicit that any third-party WHERE implementation (e.g.
AmiAuth) needs a receive loop that doesn't call IsRexxMsg(), the same
as CAAPP.WHERE's own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CbPo4nMpnM5JQX3LKE5JP
… not IsRexxMsg()

The previous commit's "trust every message on a dedicated port"
workaround was correct in that it made the tests pass, but not in its
diagnosis. IsRexxMsg() checks ln_Type == NT_REPLYMSG, which ReplyMsg()
sets -- the right question for a sender inspecting its own reply, not
a receiver validating an incoming, not-yet-answered command (which is
legitimately still NT_MESSAGE regardless of how carefully the sender
is built, confirmed by ruling out two separate sender-side fixes
live: pre-marking ln_Type before sending, and using a genuine
CreateArgstring()-backed rm_Args[0]). RXCOMM is the field that
actually means "this is a command invocation" -- CAAPP.WHERE now
checks rm_Action & RXCOMM instead, a completely ordinary,
one-condition receive-loop check any third-party ARexx port
(including AmiAuth's) can use, not a dedicated-port special case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CbPo4nMpnM5JQX3LKE5JP
@sidick
sidick merged commit fc63069 into main Aug 9, 2026
7 checks passed
@sidick
sidick deleted the where-port branch August 9, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant