Skip to content

Answer paste keystrokes from the paste event on wasm - #25396

Open
Cyannide wants to merge 2 commits into
bevyengine:mainfrom
Cyannide:wasm-paste-event
Open

Answer paste keystrokes from the paste event on wasm#25396
Cyannide wants to merge 2 commits into
bevyengine:mainfrom
Cyannide:wasm-paste-event

Conversation

@Cyannide

Copy link
Copy Markdown
Contributor

Objective

navigator.clipboard.readText() sits behind Chrome's clipboard-read permission (a prompt on first paste, per origin) and does not exist for page JS on Firefox. The text a paste KEYSTROKE carries is readable without any permission from the paste ClipboardEvent -- the gesture is the grant; this is how web editors avoid the prompt.

Solution

A window-level paste listener (installed at plugin build, leaked on purpose; the closure is forget()-ed; it must outlive the app) stashes the event's text with its arrival time; fetch_text() consumes a fresh stash entry before touching readText(), which remains the fallback for reads no paste event drove.

Degrades gracefully: winit currently preventDefault()s every keydown when prevent_default is on (Bevy's default), which suppresses the browser's paste event -- there the stash stays empty and behavior is exactly today's readText() path. Fully effective once the app disables prevent_default_event_handling or winit spares clipboard combos (rust-windowing/winit#2831; a 6-line exemption is field-tested).

Part of #25340.

Testing

  • End to end in production (backported to 0.19, winit patched per the
    exemption above): Chrome pastes with no permission prompt where it
    prompted before, Firefox pastes at all (readText() does not exist there),
    Safari stops showing its paste confirmation. About a month of daily
    tester use on the rest of the patch set; this piece landed this week.
  • Under stock winit + Bevy defaults the stash is never fed, and the
    readText() fallback is the untouched existing code path -- behavior is
    identical to main by construction. Reproducible without a patched winit
    by setting Window::prevent_default_event_handling = false.
  • This branch: cargo check and clippy, x86_64 and wasm32-unknown-unknown,
    with and without system_clipboard.

navigator.clipboard.readText() sits behind Chrome's clipboard-read
permission (a prompt on first paste, per origin) and does not exist for
page JS on Firefox. The text a paste KEYSTROKE carries is readable
without any permission from the `paste` ClipboardEvent -- the gesture is
the grant; this is how web editors avoid the prompt.

A window-level `paste` listener (installed at plugin build, leaked on
purpose) stashes the event's text with its arrival time; fetch_text()
consumes a fresh stash entry before touching readText(), which remains
the fallback for reads no paste event drove.

Degrades gracefully: winit currently preventDefault()s every keydown
when prevent_default is on (bevy's default), which suppresses the
browser's paste event -- there the stash stays empty and behavior is
exactly today's readText() path. Fully effective once the app disables
prevent_default_event_handling or winit spares clipboard combos
(rust-windowing/winit#2831; a 6-line exemption is field-tested).

Part of bevyengine#25340.
@kfc35 kfc35 added A-UI Graphical user interfaces, styles, layouts, and widgets O-Web Specific to web (WASM) builds A-Text Rendering and layout for characters S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Aug 13, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in UI Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Text Rendering and layout for characters A-UI Graphical user interfaces, styles, layouts, and widgets O-Web Specific to web (WASM) builds S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

2 participants