Files
browser/src/mcp
Ramiro_quaiandClaude Sonnet 5 8a57a492a8 refactor(input): share pointer/mouse click dispatch across click paths
Follows up on the maintainer's review note on PR #3431: WebDriver.click
(testdriver), Frame.user_input.triggerMousePress/Release (CDP's
Input.dispatchMouseEvent, i.e. Puppeteer/Playwright), and actions.click
(MCP) each dispatched their own near-identical pointerdown/mousedown/
pointerup/mouseup/click sequence. Adds three shared functions to
frame/user_input.zig -- dispatchPointerPress, dispatchPointerRelease,
dispatchClickAsPointer -- and routes all three call sites through them.

This gives the CDP path pointerdown/pointerup for the first time (it
previously only fired bare mousedown/mouseup/click), and a PointerEvent
click (previously a plain MouseEvent there). It also gives WebDriver.click
suppress/focus handling it never had: that function used to dispatch its
fixed five-event sequence unconditionally, ignoring preventDefault() and
never moving focus.

Because CDP's mousePressed and mouseReleased arrive as two independent
Input.dispatchMouseEvent messages with no shared call stack, a new
Page.input_mousedown_suppressed field carries whether the press half's
cancelled pointerdown should suppress this gesture's mouseup on the
release half. It's read-and-reset unconditionally at the top of
triggerMouseRelease (and reset on a press that finds no element), so an
unmatched or missed message can't leak stale state into the next gesture.

dispatchPointerPress returns PressResult{suppress_mouse, suppress_focus}
rather than running the focus default action itself: focusForMouseDown
can fail, and the three callers don't agree on what that should mean for
the click (actions.click: warn and continue; WebDriver.click and CDP:
propagate), so each runs it against the result with its own handling.

WebDriver.click also now reads frame._page.input_modifiers so a held
modifier key still reaches its dispatched events, matching its own
pre-existing local helpers' behavior (only compiled under
-Dwpt_extensions; actions.click and CDP don't track modifier state, so
they pass an empty Modifiers{}).

WebDriver.actionSequence's performPointerSource (a fourth, more complex
copy -- click counts, drag chords, touch) is deliberately left alone, as
is its own pre-existing gap (no pointerdown-suppresses-mousedown there).

Two new CDP tests reuse the existing mcp_actions.html fixture (#btn
records the full event sequence; #btnPreventDefault's pointerdown
listener calls preventDefault()) to pin the new pointer events and the
cross-message suppression. Both were confirmed to fail against the
pre-refactor triggerMousePress/Release bodies. Extended #btn's recorder
with event.detail after an independent review caught mousedown/mouseup's
click count silently dropping to 0 at all three call sites in an earlier
version of this change; the MCP click test's assertion was updated to
match.

zig build test and zig build test -Dwpt_extensions: 1516/1516 both ways.
zig fmt --check clean on all seven changed files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XLXnBHBxQNskg2MAke3Lhv
2026-09-17 07:55:59 +08:00
..
2026-08-31 22:44:59 +08:00