Skip to content

fix: make drawButton's clickable region match the box it draws - #37

Merged
dmccoystephenson merged 2 commits into
mainfrom
fix/draw-button-edge-hit-test
Aug 10, 2026
Merged

fix: make drawButton's clickable region match the box it draws#37
dmccoystephenson merged 2 commits into
mainfrom
fix/draw-button-edge-hit-test

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

  • drawButton's hit test compared strictly on both axes (xpos + width > mouse[0] > xpos), while pygame.draw.rect fills the half-open range [xpos, xpos + width). The painted left and top edge lines of every button were therefore not clickable, though the right and bottom ones were. The comparison is now half-open on both axes, so the clickable region is exactly the region the box is drawn over.
  • A second effect is corrected by the same change: buttons laid out edge to edge previously had a shared boundary coordinate that belonged to neither of them. Under half-open bounds it belongs to exactly one — the button whose left/top edge sits on it — and never to both.
  • Regression coverage is added as a parametrized sweep of all four edges, the top-left corner, and the first coordinate past each far edge, plus a companion test asserting that the pixels claimed clickable are the same ones actually painted in colorBox, so the two cannot drift apart.
  • The drawButton docstring and the README's drawButton entry now state the clickable region explicitly.

Compatibility

No public signature is changed, and the documented repeat-fire semantics are untouched. The change is a one-pixel widening of the hit area on two edges so that it coincides with the already-drawn box; no vendored consumer copy (Roam, Apex, Ophidian, Patchwork, Tic-Tak-Toe) can plausibly depend on a dead strip over painted pixels. A cross-org code search for drawButton call sites was attempted but is not available to this session, so the assessment above rests on the nature of the change rather than on enumerated call sites.

Test plan

  • python3 -m py_compile src/main/python/preponderous/graphik/graphik.py — succeeds
  • python3 -m pytest — 37 passed (was 26)
  • Regression confirmed empirically, not by reasoning: with the fix stashed, test_draw_button_clickable_region_matches_the_drawn_box[left_edge], [top_edge], [top_left_corner] and test_adjacent_buttons_do_not_share_a_clickable_boundary all FAIL; with it restored, all PASS.
  • The new tests run headless under the existing conftest.py dummy SDL drivers; no display or audio device is required.

Deferred work

Issue #34 (release tags pushed without the v prefix publish.yml requires) was the only other open issue at triage time and was not picked up this cycle. Its own body defers it pending a maintainer decision between two release-process directions, and it touches .github/workflows/ and the release process, both of which are excluded from autonomous change.

Closes #36

This PR description was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

dmccoystephenson and others added 2 commits August 10, 2026 01:44
The hit test used strict inequalities on both axes while pygame.draw.rect
fills a half-open range, so the painted left and top edge lines of every
button were dead while the right and bottom ones worked.

Comparing half-open on both axes makes the clickable region exactly the
drawn one, and keeps edge-to-edge buttons from both claiming a shared
boundary coordinate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmccoystephenson

Copy link
Copy Markdown
Member Author

Self-review rubric (scored against the diff and command output, not judgment):

  • Scope: PASS — three files are touched (graphik.py, test_graphik.py, README.md) and each is required by drawButton: the left and top edge pixels of the drawn box are not clickable #36: the fix, its regression coverage, and the doc entry that described the old behavior. git status was checked before staging; files were staged by name, and no .claude/ state was included. Net non-test change is 13 lines across 1 file, far under the scope ceiling.
  • Tests-new: PASS — no new public method is added, so the rule applies to the changed behavior instead: drawButton's hit test is now exercised at all four edges, the top-left corner, and the first coordinate past each far edge.
  • Tests-fix: PASS — confirmed empirically, not by reasoning. With graphik.py stashed, test_draw_button_clickable_region_matches_the_drawn_box[left_edge], [top_edge], [top_left_corner] and test_adjacent_buttons_do_not_share_a_clickable_boundary FAIL; after git stash pop all PASS. Scored honestly: the remaining five parameters (right_edge, bottom_edge, and the four just-outside cases) pass in both states — they are characterization of behavior that was already correct, and the regression evidence rests on the three edge parameters plus the adjacency test.
  • Sibling structure: PASS — no new file is created. The added helper and tests follow the conventions of their neighbours in the same file: a leading _-prefixed helper, pytest.param(..., id=...) for parametrization, and _rgb(display, pos) for pixel assertions.
  • Sibling renames: PASS (no signal) — no identifier is renamed.
  • Docs: PASS — the README drawButton entry and the drawButton docstring both state the clickable region. The remaining rows of the documentation table are unaffected: RELEASING.md and pyproject.toml are untouched, and no version string is involved. (Noted for the record: the version.txt and pom.xml rows of the loop's documentation table no longer exist in this repository; that is a skill-side gap, not a gap in this PR.)
  • Issue resolution: PASSdrawButton: the left and top edge pixels of the drawn box are not clickable #36 names graphik.py:171 and the strict-inequality bounds check; that exact line is what changed, and the suggested half-open form is what was applied. Nothing in drawButton: the left and top edge pixels of the drawn box are not clickable #36 is left partially addressed.
  • manual validation: PASSpython3 -m py_compile src/main/python/preponderous/graphik/graphik.py succeeds and python3 -m pytest reports 37 passed on the PR head. The suite runs headless through the existing conftest.py dummy SDL drivers.
  • camelCase: PASS — no public method is added or renamed; drawButton keeps its name and its nine-parameter signature.
  • Backward-compat: PASS with a caveat — no public member is renamed, removed, or resignatured, so the consumer-impact gate is not triggered. The observable change is that one pixel row and one pixel column of already-painted box become clickable. A cross-org gh search code for drawButton call sites is not available to this session, so this rests on the nature of the change rather than on an enumerated call-site list; it is recorded here rather than claimed as verified.
  • Headless: PASS — the new tests add no display or audio requirement beyond what the existing suite already relies on.
  • Version sync: PASS (no signal) — no version string is changed; _version.py and pyproject.toml are untouched.
  • No new deps: PASS — no import is added to graphik.py; the test file adds none beyond pygame and pytest, which it already imported.

Observations folded in rather than left inline:

  • src/test/python/preponderous/graphik/test_graphik.py:429 — the value returned by _click_at was originally compared with is against the parametrized literal. That is sound for booleans but relies on interning; it was changed to == in the follow-up commit before this comment was posted.
  • src/main/python/preponderous/graphik/graphik.py:181 — degenerate boxes were checked and are unaffected. A zero-width button matched nothing under the old strict form (xpos + 0 > mx > xpos) and matches nothing under the half-open form (xpos <= mx < xpos); a negative width likewise matches nothing, which agrees with pygame.draw.rect drawing nothing in that case. No test is added for this, since the behavior is unchanged by the diff.
  • src/test/python/preponderous/graphik/test_graphik.py:375 — the pre-existing outside_box parameter at (0, 0) is now partly redundant with the new just_left_of_box case, but it still carries the pressed-state axis that the new sweep does not, so it was left alone rather than churned.

One issue was found and fixed during this review; the remaining items are recorded above rather than blocking.

This review comment was drafted during a Gardener session (https://github.com/Stephenson-Software/gardener).


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit 9b51186 into main Aug 10, 2026
5 checks passed
@dmccoystephenson
dmccoystephenson deleted the fix/draw-button-edge-hit-test branch August 10, 2026 07:47
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.

drawButton: the left and top edge pixels of the drawn box are not clickable

1 participant