w3c / uievents

UI Events
https://w3c.github.io/uievents/
Other
147 stars 52 forks source link

Proposal: Add KeyboardEvent.unmodifiedKey #229

Open adrianholovaty opened 5 years ago

adrianholovaty commented 5 years ago

A web app I work on, Soundslice, lets people add custom keyboard shortcuts. The shortcut-customization UI uses KeyboardEvent.key to display which key combination you've entered, and it uses the value of KeyboardEvent.key internally to save the user's custom shortcuts. More info on the specific product feature is here.

This generally works OK, but we have a problem with modifier keys. If you try to enter Option g as a shortcut (i.e., the Option key plus the g key), KeyboardEvent.key returns the copyright symbol "©" (on my particular keyboard locale). That's because KeyboardEvent.key returns the string that would result from your keypress according to the modifier keys and keyboard locale.

I understand the reasoning for this, and in fact it's the whole point of KeyboardEvent.key as opposed to KeyboardEvent.code — but neither key nor code nicely handle this particular use case of custom keyboard shortcuts. A person creating a keyboard shortcut is thinking about the literal keys — Option G in this case — not the resulting character string.

At first glance, that suggests we should be using KeyboardEvent.code. The problem there is: we also want the keyboard layout to be honored. On an AZERTY keyboard, hitting the "A" key sets KeyboardEvent.code to KeyQ and KeyboardEvent.key to a — the latter is what we want.

This essentially means there is no consistent cross-platform or cross-locale way of checking for keyboard events with the Option modifier set.

In short, I believe this use case would be handled elegantly if KeyboardEvent had an unmodifiedKey attribute. This would be the same value as KeyboardEvent.key (i.e., taking keyboard locale into account), but without taking any modifier keys into account. This gives us the best of both worlds — the keyboard locale handling from KeyboardEvent.key and the physical-key-centric approach of KeyboardEvent.code.

If there's an existing way to accomplish this, I'd of course love to hear it! Thanks for reading. :)

garykac commented 5 years ago

The proposed solution for this problem is Keyboard Map: https://wicg.github.io/keyboard-map/

(Link to original proposal: https://github.com/WICG/keyboard-map/blob/master/proposal.md)

For this, you would record the code for the shortcut, and then use the KeyboardMap API to get the key name that you can show to the user. Note that the key name is restricted to ASCII-capable layouts.

adrianholovaty commented 5 years ago

@garykac Thanks very much! I wasn't aware of the Keyboard Map proposal.

I've just given it a read, along with the original proposal/explainer, and it would indeed solve the problem for our use case — assuming that the privacy repercussions don't render the API unusable. I'm concerned that, if browsers require a permission prompt (as mentioned in Privacy Mitigations), this would be out of context, overly confusing and annoying.

Our app, a music notation editor, displays the default keyboard shortcuts directly in context, in tooltips for each of the dozens of UI buttons:

Screenshot

As it stands, I guess we'd need to show the permission prompt at the time of page load, which would be confusing because it wouldn't be directly tied to an obvious keyboard-shortcut user action.

Granted, this is a theoretical argument, because the spec leaves the permission-prompt question to browser implementations. But couldn't we sidestep that problem entirely if we provided the data in the KeyboardEvent itself, reducing the fingerprinting/privacy risk? As the proposal says, "similar fingerprinting can still be attempted, but it is more difficult since it would require the user to interact with the page by typing characters and analyze the resulting KeyboardEvents."

garykac commented 5 years ago

You can try it out for yourself since there is an implementation in Chrome (enabled since Chrome 69):

MDN docs: https://developer.mozilla.org/en-US/docs/Web/API/Keyboard_API ChromeStatus: https://chromestatus.com/features/6730004075380736 Mozilla's tracking bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1469017 WebKit tracking bug: https://bugs.webkit.org/show_bug.cgi?id=186680

Including it automatically in the KeyboardEvent means that there wouldn't be an obvious place for the UA to ask for permission (should it choose to do that).