Skip to content

feat(webview): synthesize keyboard and mouse input#41055

Merged
yury-s merged 8 commits into
microsoft:mainfrom
yury-s:webview-input
May 29, 2026
Merged

feat(webview): synthesize keyboard and mouse input#41055
yury-s merged 8 commits into
microsoft:mainfrom
yury-s:webview-input

Conversation

@yury-s
Copy link
Copy Markdown
Member

@yury-s yury-s commented May 29, 2026

Summary

Synthesize keyboard and mouse input for the stock WebKit (WebView) backend, which has no trusted Input domain.

  • Page-side dispatch in a typed injected script (packages/injected/src/webview/webViewInput.ts) installed on every document via the page bootstrap (window.__pwWebViewInput); wvInput serializes params and drives it.
  • Keyboard: dispatch keydown/keypress/textInput, letting the textInput (TextEvent) default action perform the insertion — matching real WebKit's keydown → keypress → textInput → input sequence (Enter's text is \r, inserted data is a newline). Synthesize the legacy WebKit-only KeyboardEvent.keyIdentifier. Descend through shadow roots to find the focused element.
  • Mouse: fire the full out/leave → over/enter → move sequence (mouse + pointer) when the hovered element changes, so hover-driven UI reacts.
  • Installed via the bootstrap rather than extendInjectedScript so input dispatched immediately after a navigation doesn't race a missing dispatcher.

Removes the now-passing keyboard/typing tests from the webview expectations and adds a cross-browser test for the typing event sequence. The remaining keyboard skips need native default actions synthetic events can't trigger on stock WebKit (caret movement, selectAll, clipboard, undo, button activation) or unimplemented features (contentFrame).

yury-s added 7 commits May 29, 2026 11:49
Stock WebKit exposes no trusted Input domain, so input must be synthesized with
DOM events. Synthetic events do not trigger the browser's default behaviors, so:
- keyboard: emulate default text insertion (honoring the selection) on a
  non-prevented keypress, so press/type actually update inputs.
- mouse: fire the full out/leave -> over/enter -> move sequence (mouse and
  pointer flavors) when the hovered element changes, so hover-driven UI reacts.

The page-side dispatch lives in a typed, tsc-checked injected script
(packages/injected/src/webview/webViewInput.ts), bundled and installed into
every frame via BrowserContext.extendInjectedScript; wvInput drives it through
window.__pwWebViewInput.

Removes the now-passing input-dependent tests from the webview expectations.
…DOM typing

Injecting window.__pwWebViewInput through extendInjectedScript was racy: it
re-injects asynchronously after a navigation, so input dispatched immediately
after page.goto ran before the dispatcher existed and silently no-op'd. Install
it through the page bootstrap script instead, which runs synchronously on every
new document before page scripts — no race.

Also descend through open shadow roots when resolving the active element, so
typing/insertText targets the focused element inside a shadow root rather than
the shadow host.

Removes the now-passing page-keyboard tests from the webview expectations. The
remaining keyboard failures need native default actions that synthetic events
cannot trigger on stock WebKit (caret movement, selectAll, clipboard, undo,
button activation) or unimplemented features (contentFrame, keyIdentifier).
…ection

It fails because elementHandle.contentFrame is unimplemented, not because of
generic structural/popup limitations — group it with the other
frame-element-and-ownership skips whose comment documents that cause.
keyIdentifier is a legacy WebKit-only property that cannot be supplied via the
KeyboardEvent constructor, so synthetic key events reported "". Compute it from
the virtual key code (mirroring WebCore's keyIdentifierForWindowsKeyCode) and
define it on the event before dispatch.

Removes 'should expose keyIdentifier in webkit' from the webview expectations.
The keyboard input fixes make these pass; the only remaining failures in both
files are the 'should work with number input' tests, which are it.fail on WebKit
upstream and therefore already expected.
The keyboard input fixes also make these pass:
- locator-misc-2: should press @smoke, should type, should pressSequentially
- page-basic: page.press should work
Typing previously dispatched keydown/keypress and then manually set the value,
so the textInput (TextEvent) that real WebKit fires between keypress and input
was missing. Dispatch it via initTextEvent and let its default action perform
the insertion (which also produces the real beforeinput/input), matching the
platform. Enter's text is '\r' but the inserted/textInput data is a newline.

Adds a cross-browser test asserting the keydown/keypress/textInput/input/keyup
sequence when typing a character.
Copy link
Copy Markdown
Member

@pavelfeldman pavelfeldman left a comment

Choose a reason for hiding this comment

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

Make sure you dispatch events in individual tasks

Drop the WebViewInputInstaller indirection (a leftover from the
extendInjectedScript design); the bootstrap now constructs WebViewInput
directly with (window, document) and assigns it. Remove architecture-explaining
comments, keeping only the browser-specific ones.
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@yury-s yury-s merged commit 9fe284a into microsoft:main May 29, 2026
48 of 49 checks passed
@yury-s yury-s deleted the webview-input branch May 29, 2026 22:35
@github-actions
Copy link
Copy Markdown
Contributor

Test results for "MCP"

7233 passed, 1113 skipped


Merge workflow run.

@github-actions
Copy link
Copy Markdown
Contributor

Test results for "tests 1"

4 flaky ⚠️ [chromium-library] › library/popup.spec.ts:261 › should not throw when click closes popup `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/video.spec.ts:719 › screencast › should work with video+trace `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/video.spec.ts:682 › screencast › should capture full viewport on hidpi `@chromium-ubuntu-22.04-node24`
⚠️ [webkit-library] › library/browsertype-connect.spec.ts:792 › launchServer › should upload a folder `@webkit-ubuntu-22.04-node20`

43989 passed, 864 skipped


Merge workflow run.

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.

2 participants