[BUG] [WEB] `KeyUpEvent` is synthesized too eagerly when combining the Meta key with multiple non-modifier keys
- Dominant language
- Dart
- Stars
- 179k
- Forks
- 31.1k
- PR merge metrics
- PR metrics pending
Description
## Description
While PR #180692 successfully fixed issue #162305 (where the web embedder synthesized key up events too eagerly for normal typing / game control), a limitation remains when the `Meta` key (`Cmd` on Mac) is involved.
Because the key guard mechanism in the web embedder is still required and active when the Meta key is pressed, pressing multiple non-modifier keys simultaneously alongside it causes the guard to misbehave. Only the last pressed non-modifier key sends repeated events, which leads the framework to eventually (and incorrectly) synthesize key up events for the other physically held non-modifier keys.
*Note: This specific behavior was isolated to the `Meta` key during debugging in the PR, rather than all modifier keys.*
## Steps to reproduce
Using the `KeyboardListener` or `Focus.onKeyEvent` APIs on a Web build (JS or WASM):
1. Press and hold the `Cmd` (Meta) key.
2. Press and hold `[j]`.
3. Press and hold `[k]`.
4. Wait for over 1.5 seconds (or `> _kKeydownCancelDurationMac`).
You may use the sample app from the linked issue to debug this too.
## Expected results
The framework should recognize that `Cmd`, `j`, and `k` are all still actively pressed. No `KeyUpEvent` should be fired until the user physically releases the keys.
* Expected event stream: `Cmd down`, `j down`, `k down`
## Actual results
The web embedder synthesizes a premature key up event for the first non-modifier key (`j`), even though the user is still physically holding the key down.
* Actual event stream: `Cmd down`, `j down`, `k down`, **`j up` (synthesized)**
## Context and Related Issues
* This is a known limitation documented during the review of **PR #180692**: [[Fix issue where web embedder is synthesizing key up events too eagerly](https://github.com/flutter/flutter/pull/180692)](https://github.com/flutter/flutter/pull/180692).
* Related to the original **Issue #162305**: [[BUG] [WEB] `KeyboardListener`'s and `Focus.onKeyEvent`'s `KeyUpEvent` do not work correctly in JS and WASM builds](https://www.google.com/search?q=%5Bhttps://github.com/flutter/flutter/issues/162305%5D(https://github.com/flutter/flutter/issues/162305)).
A potential workaround discussed was to delay the synthesizing of non-modifier keys until the meta-key is released entirely, but this risks keeping the framework out of sync for non-modifier keys until the modifier is released. Another suggested idea was discussed where receiving repeated key-up events for *any* non-modifier key would also delay (reset guards) the synthesizing of *all* non-modifier key-up events. Both ideas are only slightly better than the current behavior, as its impossible to get a "perfect" solutions (because browser is not sending the key-up events at all when meta key is involved).
Contributor guide
Research direction
Start with the web embedder key-guard handling used by KeyboardListener and Focus.onKeyEvent, then reproduce the Cmd+j+k sequence in a JS or WASM Web build, using the sample app if available. Compare the event stream after the keydown cancellation duration with the expected Cmd down, j down, k down sequence; done means no premature j KeyUpEvent while the keys remain held.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart, javascript, wasm
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100