Skip to content

fix(app): keep pointer events within window bounds - #220

Merged
kolkov merged 3 commits into
gogpu:mainfrom
besmpl:agent/keep-pointer-events-in-bounds
Aug 13, 2026
Merged

fix(app): keep pointer events within window bounds#220
kolkov merged 3 commits into
gogpu:mainfrom
besmpl:agent/keep-pointer-events-in-bounds

Conversation

@besmpl

@besmpl besmpl commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • gate ordinary mouse moves and legacy/detailed wheel events to the window's logical bounds while retaining held-button capture outside the window
  • use detailed scroll coordinates/modifiers where available, preserve platform compatibility fallbacks, and deduplicate leave/callback delivery
  • reset mouse-only capture, pressed, hover, and cursor state on focus loss or pointer cancellation without letting touch/pen mutate legacy mouse state
  • enforce ListView's drawable content X band, excluding the scrollbar inset
  • add regressions for bounds, HiDPI coordinates, capture/cancellation, zero-value windows, and ListView edges

Why

Pointer events can arrive after the cursor leaves a native window. Passing ordinary moves and wheel events through caused stale hover/selection/scroll behavior, while simply dropping every outside event would break legitimate captured drags. The bridge now distinguishes those cases at the shared boundary and cleans up incomplete pointer sequences when focus is lost.

Verification

  • go test ./... -count=1
  • CGO_ENABLED=0 go build ./...
  • go build ./...
  • go vet ./app/... ./event/... ./core/listview/...
  • focused event/ListView tests repeated 20×
  • focused race tests
  • gofmt and git diff --check

A pre-existing test-only race in TestWindow_AnimPumper_StartsOnInvalidation still prevents a clean full go test -race ./...; the changed focused packages expose no new race.

Fixes #179

Local CI and Codecov preflight

  • rebased onto current main (273cc1e)
  • go test ./... -count=1: pass
  • focused changed-package race suite: pass; the repository-wide race suite remains blocked only by the pre-existing TestWindow_AnimPumper_StartsOnInvalidation mock race noted above
  • go build ./..., go vet ./..., gofmt, and diff checks: pass
  • local Codecov-equivalent changed-production coverage: 137/137 statements (100%) (app/event_bridge.go 92/92, app/window.go 31/31, core/listview/event.go 14/14); overall coverage 86.4%

Upstream CI run approval is still external to this branch: GitHub marked the fork workflow action_required with zero jobs. A gogpu maintainer must approve the workflow before Actions and the configured Codecov upload/bot can run.

Review follow-up (2026-08-12)

Extracted mouse-button ownership tracking into the private trackMouseButtonOwnership helper, reducing HandleEvent below the configured cyclomatic-complexity limit without changing event ordering.

@besmpl
besmpl marked this pull request as ready for review August 10, 2026 17:04
@besmpl
besmpl requested a review from kolkov as a code owner August 10, 2026 17:04
@besmpl
besmpl force-pushed the agent/keep-pointer-events-in-bounds branch from f952f05 to bc42a15 Compare August 10, 2026 20:22
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kolkov kolkov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REQUEST CHANGES (1 lint issue)

Strong work on event handling. The gate logic is correct: handleBridgeMouseMove drops ordinary moves when outside window bounds with no buttons held, but preserves captured drags. Synthetic MouseLeave with leaveDispatched deduplication is well-designed. Focus-loss cancellation via cancelPointerState delivers synthetic releases per button at an outside-widget position.

Coverage is excellent: 137/137 changed statements (100%), ~65% of added lines are tests. The TestWindow_FocusLossCancelsSliderDrag end-to-end test against real slider.New is particularly good.

Lint failure (blocking):

  • app/window.go:417 -- HandleEvent cyclomatic complexity = 22 (threshold 20). Extract the early button-ownership tracking block into a private helper method (e.g., trackButtonOwnership or updateMouseButtonState).

After the gocyclo fix, this is ready to merge.

@besmpl
besmpl force-pushed the agent/keep-pointer-events-in-bounds branch from ce90c2c to 3b9dbf9 Compare August 12, 2026 06:53

@kolkov kolkov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint fix confirmed — HandleEvent complexity resolved by extracting pointInWindow and handleBridgeMouseMove helpers. CI 9/9 pass. APPROVE.

@kolkov
kolkov merged commit 6d45fde into gogpu:main Aug 13, 2026
9 checks passed
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.

app: pointer/wheel events reach widgets while the cursor is outside the window bounds

2 participants