Richly interactive web sites, games and remote desktop/application streaming experiences want to provide an immersive, full screen experience. To accomplish this, sites need access to special keys and keyboard shortcuts while they are in full screen mode so that they can be used for navigation, menus or gaming functionality. Some examples of the keys that may be required are Escape, Alt+Tab, Cmd+`, and Ctrl+N.
By default, these keys are not available to the web application because they are captured by the browser or the underlying operating system. The Keyboard Lock API enables websites to capture and use all available keys allowed by the OS.
2. Keyboard Lock API 2.1. Navigator Interfacepartial interface Navigator {
[SecureContext, SameObject] readonly attribute Keyboard keyboard
;
};
2.2. Keyboard Interface
[SecureContext, Exposed=Window] interfaceKeyboard
: EventTarget { Promise<undefined>lock
(optional sequence<DOMString>keyCodes
= []); undefinedunlock
(); };
The keyboard object has enable keyboard lock, which is a boolean that is set to true when Keyboard Lock is enabled. By default, this is set to false.
The keyboard object has reserved key codes, which is a set of DOMStrings, each of which is a valid key code attribute value as defined in [UIEvents-Code]. By default this set is empty (which would capture all keys if enable keyboard lock was enabled).
The keyboard object has a keyboard lock task queue which is initialized to the result of starting a new parallel queue.
Note: The Keyboard
interface inherits from EventTarget
because it needs to be able to handle some keyboard-releated events like layoutchange
.
When lock()
is called, the user agent must run the following steps:
Let p be a new Promise.
If not currently executing in the currently active top-level browsing context, then
Reject p with an "InvalidStateError
" DOMException
.
Enqueue the following steps to the keyboard lock task queue:
Reset reserved key codes to be an empty set.
If the optional keyCodes
argument is present, run the following substeps:
For each string key in keyCodes
:
If key is not a valid key code attribute value, then
Set enable keyboard lock to be false.
Reject p with an "InvalidAccessError
" DOMException
.
Append key to reserved key codes.
If enable keyboard lock is currently false, run the following substeps:
Optionally, register a system key press handler.
Set enable keyboard lock to be true.
If there is a pending lock()
task in the keyboard lock task queue, then
Set enable keyboard lock to be false.
Reject the p with an "AbortError
" DOMException.
Resolve p.
Return p.
Note: If lock()
is called multiple times without an intervening call to unlock()
, then only the keyCodes
specified in the last request call will be in effect. If a second call to lock()
is made before the first one has finished, then the first one will be rejected with "AbortError
".
To capture all keys, simply call
lock()
with no arguments:
navigator.keyboard.lock();
To capture the "W", "A", "S", and "D" keys, call
lock()
with a list that contains the
key code attribute valuefor each of these keys:
navigator.keyboard.lock(["KeyW", "KeyA", "KeyS", "KeyD"]);
This will capture these keys regardless of which modifiers are used with the key press. Assuming a standard US QWERTY layout, registering KeyW will ensure that "W", Shift+"W", Control+"W", Control+Shift+"W", and all other key modifier combinations with "W" will be sent to the app. Similarly for KeyA, KeyS and KeyD.
Note that requesting a key is not a guarantee that all modified versions will be made available to the app. As an example, consider
Deletenavigator.keyboard.lock(["Delete"]);
While this will make most Delete key presses available (e.g., Shift+Delete, Control+Delete, Shift+Control+Delete), on Windows it will not make available the “secure attention sequence” Control+Alt+Delete.
3. Handling Keyboard Key Presses 3.1. System Key Press Handler A system key press handler is an platform-specific handler that can be used to filter keys at the platform level. Since Keyboard Lock feature is intended to provide access to key presses that are not normally made available to the browser (for example, Cmd/Alt-Tab), most platforms will require a special handler to be set up.The system key press handler must have the following properties:
It must process key presses before any user agent keyboard shortcuts are handled.
Wherever possible, it should process key presses before any system keyboard shortcuts are processed.
To register a system key press handler, the user agent will need to follow the platform-specific steps to add a low-level hook that will be called whenever the platform begins to process a new key press.
The exact process for adding a system key press handler varies from platform to platform. For examples of how to register a low-level hook to process key presses on common platforms, see [LowLevelKeyboardProc] for Windows, [QuartzEventServices] for Mac OS X and [GrabKeyboard] for X Windows.
Note: If the user agent already has a key press handler registered for another purpose, then it can optionally extend that handler to support the Keyboard Lock feature (assuming it meets the requirements mentioned above).
3.1.2. UnregisteringTo unregister the system key press handler, the user agent will need to follow the platform-specific steps to remove the (previously added) low-level hook for processing new key press.
As with registering system key press handlers, the process for unregistering system key press handlers is also platform-specific. See the references listed in § 3.1.1 Registering for more details and examples.
3.2. Handling Keyboard EventsIn response to the user pressing a key, if a system key press handler has been registered, it should run the following steps:
Let isFullscreen be set to true if the fullscreen element of the currently focused area of a top-level browsing context is non-null (see [Fullscreen]).
Note: The fullscreen element would not have focus, for example, if there was a system dialog being displayed with focus.
If isFullscreen and enable keyboard lock are all set to true, then run the following substeps:
Let keyEvent be the key event for the new key press.
Let code be the value of the code
attribute of keyEvent.
If reserved key codes is empty or if code is listed in reserved key codes, then run the following substeps:
If code is equal to "Escape", then run the following substeps:
Optionally overlay a message on the screen telling the user that they can Hold the Escape key to exit from fullscreen.
If the key is held for 2 seconds, then exit from the keyboard handler and pass the key on to the user agent for normal processing (which will exit fullscreen (and pointer lock, if active)).
Dispatch keyEvent directly to the fullsceen document or element, bypassing any normal user agent processing.
Else, handle the key event as it normally would be handled, either by dispatching a key event or performing the usual keyboard shortcut action.
Note: This API operates on a "best effort" basis. It is not required that a conforming implementation be able to override the OS default behaviour for every possible key combination. Specifically, most platforms have a “secure attention sequence” (e.g., Ctrl-Alt-Del on Windows) that applications cannot override; this specification does not supersede that.
Note: When implementing this API, user agents should take care not to change the order in which keyboard events are dispatched to the page. Keys that are included in the set of reserved key codes must be dispatched in the same relative order that they would have been sent had they not been included in the set.
4. Integration With Other Web Platform APIs[Fullscreen] and [PointerLock] are APIs that allow the page to temporarily take control of part of the user’s experience (screen and mouse cursor, respectively). Because of the concern for abuse of these features, they provide an "escape" or "unlock" gesture that the user can rely on to exit those features. By default, this gesture is pressing the Escape key, which is one of the keys that can be captured by this API.
4.1. Special Considerations with the Escape KeyBecause of the special actions associated with the Escape key, when the lock()
request includes the Escape key, the user agent may need to make additional changes to the UX to account for the changed behavior.
For example, if the user agent shows a user message "Press ESC to exit fullscreen" when Javascript-initiated fullscreen is activated, then that message will need to be updated when keyboard lock is in effect to read "Press and hold ESC to exit fullscreen".
If keyboard lock is activated after fullscreen is already in effect, then the user my see multiple messages about how to exit fullscreen. For this reason, we recommend that developers call lock()
before they enter fullscreen:
navigator.keyboard.lock(); document.documentElement.requestFullscreen();
A similar concern with multiple user messages exists when exiting keyboard lock and fullscreen, so it is recommended to call them in the reverse order:
document.exitFullscreen(); navigator.keyboard.unlock();
In general, developers should only include the Escape key in the set of locked keys if they actually have need for that key. And it is recommended that, if the Escape key is locked, the developer should maintain its primary meaning of allowing the user to exit their current state.
4.2. Fullscreen ConsiderationsThere are two different types of fullscreen available in modern user agents: JavaScript-initiated fullscreen (via the [Fullscreen] API) and user-initiated fullscreen (when the user enters fullscreen using a keyboard shortcut). The user-initiated fullscreen is often referred to as "F11" fullscreen since that is a common key shortcut used to enter and exit fullscreen mode.
F11 fullscreen and JavaScript (JS) fullscreen do not behave the same way. When a user enters F11 fullscreen, they can only exit it via the same keyboard shortcut that they used to enter it -- the exitFullscreen() function will not work in this case. In addition, fullscreen events that are normally fired for JS fullscreen are not sent for F11 fullscreen.
Because of these differences (and because there is no standard shortcut for F11 fullscreen), the Keyboard Lock API is only valid when the a JavaScript-initiated fullscreen is active. During F11 fullscreen, no Keyboard Lock processing of keyboard events will take place.
5. Pointer Lock ConsiderationsOther than the UX changes noted earlier, there are no changes to the operation of Pointer Lock.
When Pointer Lock is enabled outside of fullscreen, then Keyboard Lock cannot be enabled.
When Pointer Lock, Keyboard Lock and Fullscreen are all enabled, then the behavior is unchanged unless Keyboard Lock includes the Escape key. In that case, the only chages are to the UX (as noted above).
6. Mobile Device ConsiderationsSince this is a keyboard-focused API and mobile devices do not commonly have physical keyboards, this API will not typically be present or supported on mobile devices.
However, mobile devices may choose to support this API if it makes sense to do so when a physical keyboard is connected.
7. Security ConsiderationsOne concern with this API is that it could be used to grab all of the keys and (in conjunction with the [Fullscreen] and [PointerLock] API) prevent the user from exiting the web page.
To prevent this, the user agent MUST provide a way for the user to exit from keyboard lock even if all of the keys are requested by the API.
This specification requires support for allowing a long (more than 2 second) Escape key press to trigger an exit from Keyboard Lock. In addition, user agents may choose to also provide alternate ways to exit Keyboard Lock.
8. Privacy ConsiderationsNot applicable. This API does not use or reveal any personal information about the current user.
9. AcknowledgementsThanks to the following people for the discussions that lead to the creation of this proposal:
Jon Dahlke (Google), Joe Downing (Google)
Conformance Document conventionsConformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.
All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example"
, like this:
This is an example of an informative example.
Informative notes begin with the word “Note” and are set apart from the normative text with class="note"
, like this:
Note, this is an informative note.
Conformant AlgorithmsRequirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.
Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3