Open Bug 1599021 Opened 5 years ago Updated 4 years ago

Dead key leads to illegal KeyboardEvent.key value

Categories

(Core :: DOM: Events, defect, P3)

70 Branch
defect

Tracking

()

UNCONFIRMED

People

(Reporter: tszynalski, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0

Steps to reproduce:

  1. Switch to the French keyboard layout.
  2. Go to https://w3c.github.io/uievents/tools/key-event-viewer.html
  3. Press the key to the right of "P" -- on US keyboards this is "[". On the French layout this is the ^ dead key.
  4. Press K (or another key which does NOT form a valid dead key combination)

Of course the problem occurs on any keyboard layout with dead keys.

Actual results:

The .key property for the keydown event is "^k".

This is incorrect according to https://www.w3.org/TR/uievents-key/#select-an-appropriate-key-attribute-value because "^k" is not a valid key string.

Expected results:

I think it's a gap in the spec, but you could make the case that .key should be == "k" -- if you take the view that K actually types only "k" while the previous dead key types "^" (although delayed). This is the behavior in Chrome.

This issue makes it impossible (or at least difficult) to detect when the user pressed K (or another key) if K was typed after a dead key. (Unless you use deprecated properties.)

Component: Untriaged → DOM: Events
Product: Firefox → Core

yeah, I can reproduce this.

Flags: needinfo?(masayuki)
Priority: -- → P3

Well, but on Windows, both accent character and (invalid) base character should be input by the operation. Therefore, we follow the behavior and we set both characters to key of keydown event. Unless we discard the traditional behavior on Windows, only setting k is invalid. I'm not sure whether the Chrome's behavior is better (or okay) or worse for dead key users on Windows.

This issue makes it impossible (or at least difficult) to detect when the user pressed K (or another key) if K was typed after a dead key. (Unless you use deprecated properties.)

How about event.key.charAt(event.key.length - 1) or event.key.endsWith(), or using loop for every character of KeyboardEvent.key? Note that setting 2 more more characters to KeyboardEvent.key is valid if a keydown inputs 2 or more characters.

Flags: needinfo?(masayuki)

I understand your logic, but do you acknowledge that a keystring such as "^k" is against the spec? It's not a legal keystring.

I think Chromium's logic is that the second keypress is responsible only for "k". The "^" is the effect of the previous keydown event.

The solution you suggested won't work, because KeyboardEvent.key can be something like "F2", "Enter" or "Alt". I suppose I could determine all the possible dead key characters on all possible layouts (which is error-prone -- it's hard to check all the layouts) and then if key.length == 2 and key[0] is one of those characters, I could assume that key[1] is the character I'm looking for. It feels like a hack, though.

The new KeyboardEvent API was supposed to make this stuff easier, not harder. Right now, it's just easier to use the old "keypress" event. Let's hope it never disappears :)

(In reply to Tomasz P. Szynalski from comment #3)

I understand your logic, but do you acknowledge that a keystring such as "^k" is against the spec? It's not a legal keystring.

Hmm, the "key string" definition has been modified after we implemented. Previously, it was defined as just inputting string.

I think Chromium's logic is that the second keypress is responsible only for "k". The "^" is the effect of the previous keydown event.

Oh, I tested it again with Chrome, then, I see both accent character and base character input. I'm not sure what's different from yesterday...

Indeed, we can change our behavior, but I'm not sure whether the spec has been changed intentionally or not. Actually, Edge behaves as same as us. (The spec is based on IE9, and we implemented on all platforms with requesting changing a lot of the draft, then, Chrome implemented it.)

The solution you suggested won't work, because KeyboardEvent.key can be something like "F2", "Enter" or "Alt". I suppose I could determine all the possible dead key characters on all possible layouts (which is error-prone -- it's hard to check all the layouts) and then if key.length == 2 and key[0] is one of those characters, I could assume that key[1] is the character I'm looking for. It feels like a hack, though.

I think that your code does not work also key value which begins with a surrogate pair. I suggested to make all key names prefixed, but it was rejected because it was too late.

The new KeyboardEvent API was supposed to make this stuff easier, not harder. Right now, it's just easier to use the old "keypress" event. Let's hope it never disappears :)

From the point of view of spec editors, they said, "use beforeinput event for text input handling". I'm currently working on implementing it.

Indeed, we can change our behavior, but I'm not sure whether the spec has been changed intentionally or not. Actually, Edge behaves as same as us.

I understand your doubts about the spec, but please note that Edge will be replaced by a Chromium-based browser in a few months. It's quite likely that Firefox will be the only browser with this behavior (Safari handles dead keys differently -- using composition events).

Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.