Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,59 @@ discriminator to tell apart) -- confirmed live under Copperline via
now carries the new gadget's real, live-measured geometry and
`role=integer` line.

WB3.2-era BOOPSI/ReAction role classification is real too (issue #69):
`ClassifyByClassID()` (`intuition-model/src/walk.c`) previously
recognised only 10 of the classes documented in NDK 3.2's own
`gadgets/` header set, leaving the rest at `role=custom`. Twelve more
now get a real role -- `clicktab.gadget` (`role=page_tab_list`, the
class that motivated filing this issue: Hyperion's WB3.2-native tabbed-
panel widget), `colorwheel.gadget` (`role=color_wheel`),
`datebrowser.gadget` (`role=calendar`), `fuelgauge.gadget`
(`role=progress_bar`), `getcolor.gadget`/`getfile.gadget`/
`getfont.gadget`/`getscreenmode.gadget` (`role=color_chooser`/
`file_chooser`/`font_chooser`/`screenmode_chooser` -- AT-SPI-style
names for "a compound button that opens a system requester and shows
the result", which is genuinely what all four are per their own NDK
autodocs), `gradientslider.gadget` (`role=slider` -- reuses the
existing role rather than inventing a redundant one, since AT-SPI
itself has no separate "gradient slider" role either), `palette.gadget`
(`role=palette`), `sketchboard.gadget` (`role=canvas`),
`speedbar.gadget` (`role=toolbar`), and `texteditor.gadget`
(`role=text_editor`). Every class-ID string was confirmed against real
NDK 3.2 headers first (pragma/*_lib.h's own "<name>.gadget" comment, or
reaction_macros.h's convenience-Object macros for the two classes --
colorwheel, gradientslider -- that register a PUBLIC class name instead
of needing an explicit `XXX_GetClass()` call), not guessed, then
live-verified against a new dedicated fixture,
`fixtures/reaction-classes-app`, one instance of each class attached
DIRECTLY to a plain classic window rather than via `window.class`/
`layout.gadget` (which would make them exactly as unreachable as
issue #49's own confirmed limit already documents -- this fixture
exists specifically to sidestep that, not to demonstrate it). Two real
bugs found building this, live (2026-08-09): `colorwheel.gadget`'s
`NewObject()` silently returned NULL until `WHEEL_Screen` was supplied
-- its own autodoc does say this tag is required, but it's easy to
miss among a page of optional ones, and the failure mode (NULL, no
error text) gives no hint why; and `speedbar.gadget` registers its
class as literally `"speedbar"`, NOT `"speedbar.gadget"` like every
other class checked here -- confirmed only by reading the walker's own
`className` field back from a live object, since nothing in the NDK
materials flags this exception. `fixtures/reaction-classes-app`'s own
`ReactionClassesApp.golden` locks in the live-confirmed output for
regression protection, verified via `tests/copperline/run.sh`'s
`run_golden_check`. Five real classes from the same research pass were
deliberately left unclassified, not silently missed --
`space.gadget`/`virtual.gadget` (honest limits, `virtual.gadget`
sharing `layout.gadget`'s own unreachable-children problem),
`listview.gadget` (its own autodoc says `listbrowser.gadget`, already
mapped, is a strict upgrade), and `tabs.gadget`/`tapedeck.gadget`
(both ship as real library files on a stock WB3.2.3 install, confirmed
on disk, but neither has a documented NDK-supported construction path
in this project's own NDK 3.2 snapshot -- no `GetClass()` proto/pragma
header and no `reaction_macros.h` convenience macro exists for either)
-- see `userdocs/Locator-Tiers-and-Limits.md`'s own writeup for the
full reasoning behind each.

Phase 0.5 (reliability and reach into the wider ecosystem)
before it: `WAITFOR` (including its
`TEXT=` condition) and `CLICK`'s `EXPECT=` (wait/expectation
Expand Down
16 changes: 15 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ WBGUIAPP_BIN := $(BUILD)/fixtures/WBGuiApp
P96APP_SRC := fixtures/p96-app/src/main.c
P96APP_BIN := $(BUILD)/fixtures/P96App

# reaction-classes-app: one instance each of the 13 BOOPSI/ReAction
# gadget classes issue #69 adds role classification for, attached
# directly to a plain classic window (NOT window.class/layout.gadget
# -- see fixtures/reaction-classes-app/src/main.c's own header for
# why that would defeat the fixture's purpose).
REACTION_CLASSES_APP_SRC := fixtures/reaction-classes-app/src/main.c
REACTION_CLASSES_APP_BIN := $(BUILD)/fixtures/ReactionClassesApp

# --- server/ (phase 0.2, in progress -- see docs/implementation-plan.md) --
ACTION_SRCDIR := server/src
ACTION_INCDIR := server/include
Expand Down Expand Up @@ -127,7 +135,7 @@ all: amiga

amiga: $(INSPECT_BIN)

fixtures: $(GADTOOLS_APP_BIN) $(CLASSACT_APP_BIN) $(SECONDSCREEN_APP_BIN) $(WBAPP_BIN) $(MAKEICON_BIN) $(P96APP_BIN) $(WBGUIAPP_BIN)
fixtures: $(GADTOOLS_APP_BIN) $(CLASSACT_APP_BIN) $(SECONDSCREEN_APP_BIN) $(WBAPP_BIN) $(MAKEICON_BIN) $(P96APP_BIN) $(WBGUIAPP_BIN) $(REACTION_CLASSES_APP_BIN)

server: $(CLICKTEST_BIN) $(SETMOUSE_BIN) $(AMIPILOTD_BIN)

Expand Down Expand Up @@ -170,6 +178,12 @@ $(P96APP_BIN): $(P96APP_SRC)
@mkdir -p $(BUILD)/fixtures
$(CC) $(CFLAGS) -o $@ $(P96APP_SRC)

# -lamiga: same NewObject varargs marshaling reason as CLASSACT_APP_BIN
# above.
$(REACTION_CLASSES_APP_BIN): $(REACTION_CLASSES_APP_SRC)
@mkdir -p $(BUILD)/fixtures
$(CC) $(CFLAGS) -o $@ $(REACTION_CLASSES_APP_SRC) -lamiga

$(MAKEICON_BIN): $(MAKEICON_SRC)
@mkdir -p $(BUILD)/fixtures
$(CC) $(CFLAGS) -o $@ $(MAKEICON_SRC)
Expand Down
17 changes: 17 additions & 0 deletions fixtures/reaction-classes-app/ReactionClassesApp.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
window "AmiPilot ReAction Classes Fixture" screen="Workbench Screen" [40,0 340x256]
gadget id=0 role=custom class="buttongclass" label="" [318,0 24x11]
gadget id=0 role=custom class="buttongclass" label="" [0,0 20x11]
gadget id=0 role=custom class="gadgetclass" label="" [0,0 340x10]
gadget id=101 role=page_tab_list class="clicktab.gadget" label="" [8,20 150x22]
gadget id=102 role=color_wheel class="colorwheel.gadget" label="" [172,20 150x60]
gadget id=103 role=calendar class="datebrowser.gadget" label="" [8,84 150x22]
gadget id=104 role=progress_bar class="fuelgauge.gadget" label="" [172,84 150x22]
gadget id=105 role=color_chooser class="getcolor.gadget" label="" [8,110 150x22]
gadget id=106 role=file_chooser class="getfile.gadget" label="" [172,110 150x22]
gadget id=107 role=font_chooser class="getfont.gadget" label="" [8,136 150x22]
gadget id=108 role=screenmode_chooser class="getscreenmode.gadget" label="" [172,136 150x22]
gadget id=109 role=slider class="gradientslider.gadget" label="" [8,162 150x22]
gadget id=110 role=palette class="palette.gadget" label="" [172,162 150x22]
gadget id=111 role=canvas class="sketchboard.gadget" label="" [8,188 150x40]
gadget id=112 role=toolbar class="speedbar" label="" [172,188 150x22]
gadget id=113 role=text_editor class="texteditor.gadget" label="" [8,232 314x30]
Loading
Loading