-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clarify keypress
event handling for keys that map to non-BMP Unicode symbols
#346
Comments
Firefox developers must have intended to work it with |
@masayuki-nakano Thank you for clarifying this. Since this is the case, it would seem that there is some misalignment with Safari because Safari is only available on macOS and macOS dispatches the entire surrogate pair for an input. With this information, there are three viewpoints to this problem:
Table (a)
Table (b)
|
I suggest we align with the OS perspective for the following reasons:
|
I think that it's not good approach to align to OS behavior. I guess that most web developers do not check/test key input behavior in all major platforms per browser. Therefore, inconsistent behavior between OSes may make end users inconvenient.
On the other hand, I don't know keyboard layouts which have a key to input a non-BMP character. Therefore, this issue may appear only in specific environments. (Note that like Emoji palette in each OS, browsers do not handle them as a key sequence, therefore, this is really a special case for most users.) |
FYI: a bug in Firefox |
Ah, this may be a dup of #227 (although it's InputEvent). |
Note that if you enter e.g. an emote using the Windows On-Screen Keyboard then that will be expressed as two distinct keydown/keypress/keyup sequences, with the keypress part of each describing one of the two UTF-16 surrogates. For those events, though, the VKEY value is "PACKET" - the keydown/keyup events are essentially a platform-specific quirk that conveys almost no extra information - so it could make sense for the browser to simply drop those events, and coalesce the WM_CHARs into a single valid Unicode code-point. As Masayuki points out, though, given that the keyCode field and keypress event are deprecated and their spec is normative should it really define a behaviour, or simply document the UTF-16 & UCS4 models for |
@drwez When using the On-Screen Keyboard, Internet Explorer and Edge both send a single event. This is not a Windows platform issue, it's not an OS issue. The bad behavior is specific to Firefox / Chrome on Windows, and unfortunately it does cause real-world problems: It's a widespread problem that affects many events, not just keydown/keypress/keyup. Even idiomatic events like Safari's behavior is correct. Internet Explorer / Edge behavior is correct. Chrome and Firefox are simply buggy, they are sending invalid incorrect strings. They should be fixed so that they behave correctly and consistently. Here are the relevant bug reports for those browsers: https://bugzilla.mozilla.org/show_bug.cgi?id=1541349 https://bugs.chromium.org/p/chromium/issues/detail?id=949056 Ideally this behavior would be specified in the spec, so that way it is easier for the browsers to coordinate their behavior. I don't know what the wording should be, but the behavior should be something like "if an input character is outside of the BMP then the browser MUST NOT send multiple events (one event per surrogate pair), instead it MUST send a single event (which contains both surrogate pairs)". |
No, |
@masayuki-nakano I don't have a Windows machine right now, so I can't test it, but how does Edge handle I understand the web compat issues, but if Safari and Edge have already fixed the issue, then the web compat issue must not be that big of a deal, or we would have heard about it. |
Can you clarify what you mean? I might be misunderstanding. Turning a numeric UTF-16 code unit into a string requires |
I believe Masayuki's point is that With To reiterate my earlier point: Defining the desired behaviour for the modern input events (e.g. |
Re the event sequence from the Windows OSK: I don't have a device handy right now with which to verify the platform level behaviour wrt |
That is not a Windows platform issue, because Internet Explorer and Edge do not have that issue. It is a deviant behavior from Chrome / Firefox only (which happens to only affect Windows). |
We may be talking about different things, or different versions of Windows, then? Using the OSK on a Windows 10 device, Edge shows the same behaviour as Chrome (which is unsurprising, since both are based on Chromium), with two |
@drwez You specifically mentioned the It seems Edge 42 was before the switch to Chromium. So it is not a Windows issue, because the EdgeHTML engine did not have that issue. It is specific to the Blink / Gecko engines. And that means it is fixable, it is not an OS limitation, it is specific to particular browser engines. That also means that for several years Edge on Windows did not have this bug, but Firefox / Chrome did have this bug. Which means websites already needed to take into account the (correct) behavior of Edge and Safari, so the compat issues should be minimal. |
Ah, OK. As you point out, though, the current behaviour of Chrome (and presumably Edge) for Unicode code-points that require surrogate pairs to express in UTF-16 is incorrect with respect to the |
It seems we are going back and forth here. Let me summarize the current situation based on my work and all the evidence currently available:
This implies Chromium-based browsers and Firefox need an intermediate layer that joins the surrogate pairs to emit a proper keyboard sequence on Windows. @Pauan @drwez There are two perspectives here. One can blame Windows for dispatching two events or one can blame the bad browsers for not handling two events on Windows. Since it's not reasonable to expect Windows to change behavior (obviously), we can attribute the blame to the browsers. For everyone in this issue, let's try to conclude with a solution: I believe the spec is well-defined, in that surrogate pairs must be fully concatenated before emitting an event. Although this is not specifically stated, it's a given considering past behavior in Edge and I.E. + current behavior in Safari. WDYT? |
Re:
This description conflates the Re:
No, that's not a given at all I'm afraid. If things were appropriately defined in the spec then this spec issue would not exist :) The The |
I think there is miscommunication. It is explicitly stated that the key code is given as the unicode code point (or 0). See https://www.w3.org/TR/uievents/#determine-keypress-keyCode. When I wrote
I meant that this specific statement wasn't stated, but this statement is a given since a broken surrogate pair is not a unicode code point.
The reason this issue exists is not because the spec is not well-defined, but the fact there is misalignment between implementations and the spec. Again, there are two perspectives here:
I'm stating that we should confess (1) and reenforce the current wording of the spec with specifics on surrogate point handling. |
Yes, that's what my point is. If If web apps wants to access a (maybe) valid Unicode character, |
In my understanding, |
And in the Firefox's case, the behavior is originated in the path to handle dead key of Windows. If you type a dead key and |
@masayuki-nakano I think our browser logic is somewhat similar. It should be since Firefox and Chrome output the same sequence on Windows. On macOS, Chrome is just broken w.r.t. unicode
Since each browser already has different behavior, all web apps using For |
Alright, so after some internal discussion with @drwez, we've designed the following solution:
@drwez @masayuki-nakano WDYT? |
Focusing on the scope of this bug (i.e. just the spec, not the bugs in the various implementations), it sounds like there are one or two AIs:
Depending on the agreement for #2, it looks like Firefox and Chromium would then need their Separately there is the question of whether |
Note that that entire section is non-normative. We do not intend to normatively specify
From unicode.org:
So sending a single surrogate code point is technically valid according to the current text of the spec. Allowing a Unicode character from 2 surrogate pairs would require the spec to be re-worded.
The spec is actually clear on this. The data attribute is a DOMString, which usually permits unmatched surrogate pairs, but the text in the spec states it should only contain Unicode characters (so maybe the attribute should instead be defined as a USVString). Based on this, Firefox is not correct to include unmatched surrogates. From my perspective, the primary problem here is when 2 separate event sequences are sent when the user enters a single character. I think this is unexpected and undesirable. In the Firefox example, I get the sense that the main reason for sending multiple In the examples above, I think that Safari and Chrome are both doing appropriate things (except that Chrome is not setting the Here are my high-level thoughts on this:
To fix things, I believe the key changes (Firefox/Chrome) needed are:
To support these fixes, we might need minor spec updates based on how Firefox/Chromium choose to approach this. For example, we could consider any of the following:
Note that anything we say in the spec regarding |
Thanks @garykac for your input. It definitely clarifies/reinforces some of the thoughts we discussed in this issue. I've created another issue to discuss the As you mentioned, Firefox is the only implementation that doesn't follow that issue at the moment. Regarding |
(Sorry for the delay to reply, I lost notifications during catching COVID-19 in early this month.)
Oh, yeah, it's just a bug.
Those handlers should refer From my experiences, if it'll be standardized, only one behavior should be defined. E.g., UI Events has non-normative explanation about |
This is not the case in Web engines originating from the platform vendor. Here are screenshots from IE and EdgeHTML-based Edge running on Windows 10 2004 showing the page https://hsivonen.com/test/moz/input.html (note that the event log shows the most recent event first) with the following actions taken with focus in the input field:
IE: EdgeHTML-based Edge: Notably: In all cases:
|
@hsivonen My description was in relation to the events received from the platform, not the way that those events are interpreted by the user agent, which I think we'd already discussed earlier as differing. :) The |
Is it known that IE and EdgeHTML use the same system API surface as Gecko and Blink? Notably, https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-unichar seems to exist.
Indeed the
Yes, but the bogus values suggest that it's not that likely for the Web to be relying on The Chrome Mac behavior (https://hsivonen.fi/screen/chrome-mac-adlam.png) also suggests that it should be Web-compatible to align to the Safari behavior.
I think the primary problem with splitting non-BMP characters across events is that (as far as I know) this is the only case where the environment that JS/Wasm runs in introduces unpaired surrogates. In every other case, environment-supplied DOMStrings are actually well-formed UTF-16 and the only way for a site-supplied program to get an unpaired surrogate in a string returned by a browser API is to first offer an unpaired surrogate as input to a browser API. Therefore, these events are the only place in the platform that breaks the mappability of DOMString to the native string type of compiled-to-Wasm languages whose native string type's value space is a sequence of Unicode Scalar Values. For practical purposes today, this means Rust, but in principle it also means Swift (which, as I understand it, isn't a common compile-to-Wasm language today). That multi-scalar-value emoji that is a single user-perceived character and a single press of a Windows 10 touch keyboard "key" gets spread across multiple events is not a problem for the perspective of mappability to Rust (or Swift) strings, since the Mac: Firefox on Windows: Chrome on Windows: Notably, Chrome on Windows treats Adlam, which is an actual keyboard layout, as an IME even though it treats the emoji touch keyboard as a keyboard! Considering that Chrome on Windows doesn't even appear to treat non-BMP keyboard layouts as keyboard layouts (even though IE, EdgeHTML, and Firefox treat them as keyboard layouts), I have a really hard time believing that the Web Platform couldn't converge on the combination of Safari and Windows 10 touch keyboard behaviors:
|
As far as I've tested, Emoji palette in the onscreen keyboard of Win10/11, it sends 2 sets of One problem here is, browsers need to keep storing the last surrogate pair if
One of the problems of this approach is, only editable applications can detect text input strictly. (There is no attribute in
How does it work if the field is not editable like And with a custom keyboard layout created with MSKLC, I see usual sequence of keyboard events in Chrome for Windows. So, the Adlam keyboard layout could change their behavior with window class name of focused window. |
Browser implementations under Windows could certainly attempt to "collect" the first UTF-16 surrogate rather than propagating it, and then only emit an actual
As per the documentation you linked,
Sadly, not really - non-BMP keyboard input is still incredibly rare, so it seems plausible that it's not a case that folks are noticing is broken with their implementations yet.
See above; non-BMP is still so rare that I suspect we're just not (yet) seeing folks impacted by the brokenness of
Chrome Mac isn't emitting
I think Gary was referring to the fact that Firefox emits two separate Firefox and Chrome Windows are consistent with historical behaviour of Since the spec for
That's an interesting observation! Both behaviours seem technically valid, though the Firefox behaviour seems more useful. I wonder what the difference there is.
The Web Platform has converged on behaviours for
So the spec can document reasonable behaviour in the hope that new implementations will adopt it, and even that existing implementations will converge where feasible without breaking compability too much, but the situation differs from the normative specifications. As a concrete example, if Chromium were to migrate |
I don't think that's true. This issue was originally found because of emojis. Emojis have become incredibly commonplace and are used extensively by everybody. I see people using emojis all the time on websites, e.g. YouTube comment section, Facebook, Twitter. 1.5 Billion tweets use emojis. So I think if this was a major compat issue for Safari we would have heard about it. Just think about how popular the iPhone is, and how often people use emojis. |
This bug is specifically about the legacy The bug you link to is with "input" events being generated incorrectly and then handled unusually (it sounds like the single-surrogate DOMStrings are being treated as a complete Unicode code-point, somewhere in rust-dominator) and appears to be on Windows, not macOS. It is the case that |
Yes, that applies to a lot of situations. It is very common for websites to use event listeners to monitor comment textboxes. For example, Twitter monitors the textbox so it can update the "maximum characters allowed".
Incorrect, it is not a dominator or Rust or Wasm bug, it is 100% a browser bug. This was already well established. That bug report is what lead hsivonen to file bug reports against the browsers, which then lead to this spec bug. I've been involved in this entire situation from the very beginning, I am well aware of what is going on.
Yes, which is exactly what this bug is about: Chrome and Firefox on Windows are incorrectly generating 2 events when they should generate 1 event. Safari correctly generates 1 event. So the concern is that if Chrome and Firefox fix their behavior, it could cause compat issues. But because Safari has always had the correct behavior, and using emojis on Safari is very popular, and Safari hasn't had any compat issues, that strongly suggests that it won't cause compat issues for Chrome / Firefox. |
That's true, but that can (and often is) done using events & fields other than
Yes, I don't think there is any debate that some browsers are currently implementing That's a separate issue from
Likewise. :)
Again, this bug is specifically about the legacy |
Historically it hasn't always been two keypress. It depends on the browser. The
When browsers disagree, that makes it easier for the browsers to choose the correct behavior, because there is less concern about compat issues. That has happened many times in the past, where browsers disagreed on the behavior, and so it was easy to align all of the browsers to the correct behavior.
No, the correct behavior is obviously to have 1 event. The only reason for having 2 events is for historical compat reasons. That's why we're discussing the probability of compat issues. If the probability is low, then perhaps the browsers can just fix the bug. That has happened before. You claim the probability of compat issues is high, because non-BMP characters are rarely used. But as I said in my earlier post, that's not true, because emojis are non-BMP and they're commonly used. |
The
Again, the fact that emoji are commonly-used doesn't necessarily mean that they are commonly-used in conjunction with web content that happens to also use the Given that the |
Currently the spec doesn't define the behavior of
Although it's a legacy API, it's still commonly used, so it's still important for its behavior to be consistent among browsers. Ideally the spec should be changed so that If those spec changes cannot be made (for compat reasons), then we just have to accept that. So the big question is: how likely are there to be compat issues if Chrome / Firefox align to Safari's behavior? That will decide what sort of spec changes (if any) need to be made. |
Are you sure you're looking at the latest draft? https://www.w3.org/TR/uievents/#dom-keyboardevent-charcode has a(n admittedly self-contradictory[1]) description of the common behaviour. Specifically note the expectation that a [1] Which is in part what lead to this spec bug :)
While that would be ideal, what's most important is that its behaviour is consistent with what content has previously been lead/forced to accommodate. Historically the There has been a push to use e.g. the presence or absence of fields to detect what's needed (e.g. this was the case historically with
Right; the spec cannot mandate any particular behaviour, in general, since this is a legacy compatibility event. The spec could recommend a behaviour, if an implementation is free of compatibility concerns.
Right; enumerating the four main implementations we have:
To make another specific proposal, I'd suggest the spec:
|
See w3c/webdriver#1741: browsers don’t agree on
keypress
events for keys that map to non-BMP Unicode symbols (i.e. code points beyond U+FFFF).You can reproduce this on https://w3c.github.io/uievents/tools/key-event-viewer.html using a custom keyboard layout. I’m using https://github.com/mathiasbynens/custom.keylayout/tree/main/qwerty which lets me press a key to type
𝌆
(U+1D306), which consists of the surrogate halves U+D834 U+DF06.keypress
event is emitted, withcharCode
/keyCode
/which
set to the full Unicode code point0x1D306
. (This is the behavior I’d expect as a user.)keypress
events are emitted, one for each surrogate half (0xD834
and0xDF06
).keypress
event is emitted.Screenshot showing (from top to bottom) Safari, Firefox, and Chrome:
The text was updated successfully, but these errors were encountered: