Gecko Keypress Event

  • Revision slug: Gecko_Keypress_Event
  • Revision title: Gecko Keypress Event
  • Revision id: 167535
  • Created:
  • Creator: Karlt
  • Is current revision? No
  • Comment /* Problem 1 */

Revision Content

{{template.Fx_minversion_header(3)}} Gecko 1.9 key handling changed significantly after Beta 5 ({{template.Bug(359638)}}, {{template.Bug(429510)}} and the bugs on which they depend). The changes were risky so late in the release schedule, but they were necessary for fixing the many key handling bugs.

charCode of DOM keypress event

If a keypress event is fired without any modifier keys (Ctrl/Alt(Option)/Meta(Win/Command)), then the properties of the event are the same as they were in Gecko1.8.1. That is, when the currently selected keyboard layout produces a Unicode character (according to the current state of CapsLock and NumLock), the charCode property contains that character.

When the keypress event includes modifier keys, sometimes the charCode value is replaced with an ASCII character according to the following rules.

The accel key depends on the platform. Ctrl is the accel key on Windows and Linux, while Meta (i.e. Command) is the accel key on Mac.

When the accel key is down, the charCode of a keypress event may be replaced with a character from a Latin keyboard layout only when the original character is not an ASCII character.

This behavior helps the internationalization of web applications that have custom shortcut keys. If Gecko doesn't replace the charCode with an ASCII character, the web application developers would need to consider all non-Latin keyboard layouts (Arabic, Greek, Hebrew, Russian, etc.).

The charCode value depends on the state of CapsLock and NumLock (except they are currently ignored if Alt (Option) is down on Mac - see {{template.Bug(432953)}}). There are also some differences between the platforms, as described in the following sections.

Windows

The charCode is replaced only when Ctrl is down but Alt is not down.

If the OS-provided character cannot be entered without using the Ctrl key, then, Gecko does not replace the character. e.g., Ctrl+Shift+'2' on Persian keyboard layout inputs a ZWNJ, though Shift+'2' inputs '@', and so, if Gecko were to replace the charCode in this case, users would not be able to input ZWNJ ({{template.Bug(414130)}}).

Otherwise, Gecko can replace the charCode with an ASCII character. However, Gecko replaces the charCode only when the key pressed corresponds to a Latin letter (VK_A to VK_Z), numeral (VK_0 to VK_9), Plus sign (VK_OEM_PLUS), or Minus sign key (VK_OEM_MINUS).

Note that replacing the original (non-ASCII) characters on these keys means that there are some accessibility issues for non-Latin keyboard layout users as many non-ASCII characters will not be available for shortcuts. Therefore, web application developers should use only letters, ASCII numerals, plus sign, and minus sign for custom shortcut keys.

Linux

The charCode is replaced only when Ctrl is down but Alt and Meta are not down.

If the character provided by the keyboard layout cannot be entered without Ctrl key, then, Gecko does not replace the character (as on Windows).

Mac

The charCode is replaced when Meta (Command) or Ctrl is down.

If the current keyboard layout is Dvorak-QWERTY layout or a non-Latin layout, the Command key switches the keyboard layout to the US QWERTY keyboard layout temporary. Gecko uses the character from this keyboard layout for the Ctrl key also.

However, when Ctrl is down, Gecko 1.9 currenly only replaces the charCode only when the key corresponds to a basic Latin letter. This behavior is a bug, this behavior will be changed in a future major release ({{template.Bug(432951)}}).

Alternative charCodes for internal

This section documents only Gecko internal keypress event handling, so Web application developers can ignore this section.

Gecko replaces the charCode of DOM keypress events for accelerator key handling, but that is not enough.

Problem 1

The Zoom-in shortcut handler in Firefox is defined as <key key="+" modifiers="accel"/>. However, the Shift key must be used to enter '+' on US keyboard layout, and so the state of the Shift key causes the modifiers not to match those specified in the handler.

For the US keyboard layout, a related handler is defined with <key key="=" modifiers="accel"/>, so that users do not need to use the Shift key to access the Zoom-in shortcut. Of course, this is not much help to users with other keyboard layouts. e.g., on a Japanese keyboard, '+' is entered with Shift+';' ({{template.Bug(339723)}}).

Problem 2

The access keys for the menu items are specified with the localized characters on some localized builds. These localized access keys work fine with the keyboard layout of the locale. However, same user cannot use access keys on En-US build that includes nightly builds ({{template.Bug(399939)}}).

Problem 3

The non-Latin keyboard layout users cannot use the Latin alphabet access keys on web contents ({{template.Bug(399939)}}).

Problem 4

Shift key is need to access the access keys of web contents on Windows and Linux. Therefore, the users cannot use some characters that are inputted without Shift key. So, the unusable characters depend on the keyboard layout ({{template.Bug(359638)}}).

Solution

There are following rules:

  • The key handlers should be able to know the all meanings of the event.
  • The inner element handler should consume the non-exact matching key event even if the outer element handler can match exactly ({{template.Bug(433192)}}).
  • At access key handling, the handlers should ignore the Shift key state. However, the character that can be inputted without Shift key is preferred.
  • At shortcut key handling, if the event is fired with Shift key, but the alternative charCode is not a case changeable character (i.e., it is not an alphabet), then, Shift key state should be ignored if there are not exact matching handler. (When Alt key of Mac is pressed, the behavior should be similar, but it is not implemented on Gecko 1.9, See {{template.Bug(306585)}}).
  • At shortcut key handling, if the inputted character is case changeable character (i.e., an alphabet), the Shift key should not be ignored always. I.e., Ctrl+Shift+'C' should not execute Ctrl+'C'.
  • At shortcut key handling, when Shift key is not pressed and the character without Shift key is not numeric but the character with Shift key is numeric, the key may be the numeric keys of AZERTY keyboard layout (E.g., French), then the numeric should be a low priority shortcut key candidate ({{template.Bug(429219)}}).

So, these conditions are too complex. And the handling rules will be improved if we find new problems. Therefore, XUL application developers should use key element for handling a shortcut key, so, they should not handle it on keypress event themselves. And also they should use accesskey attribute for access keys, so, they should not also handle it on keypress event too.

So, if XUL application developers handle themselves, they also need to change the handling code every time when the rules are changed. That is not smart implementation.

Implementation

The native keypress event has all meanings of the key. They are set to nsKeyEvent::alternativeCharCodes in nsGUIEvent.h. However, the most Gecko developers should not access to this directly. The priority between the alternative charCodes are too complex. The most Gecko developers should use nsContentUtils::GetAccelKeyCandidates() for shortcut keys handling, and nsContentUtils::GetAccessKeyCandidates() for access keys handling (See nsContentUtils.h and nsContentUtils.cpp).

Revision Source

<p>{{template.Fx_minversion_header(3)}}
Gecko 1.9 key handling changed significantly after Beta 5 ({{template.Bug(359638)}}, {{template.Bug(429510)}} and the bugs on which they depend). The changes were risky so late in the release schedule, but they were necessary for fixing the many key handling bugs.
</p>
<h3 name="charCode_of_DOM_keypress_event"> <code>charCode</code> of DOM keypress event </h3>
<p>If a keypress event is fired without any modifier keys (<kbd>Ctrl</kbd>/<kbd>Alt</kbd>(<kbd>Option</kbd>)/<kbd>Meta</kbd>(<kbd>Win</kbd>/<kbd>Command</kbd>)), then the properties of the event are the same as they were in Gecko1.8.1.  That is, when the currently selected keyboard layout produces a Unicode character (according to the current state of <kbd>CapsLock</kbd> and <kbd>NumLock</kbd>), the <code>charCode</code> property contains that character.
</p><p>When the keypress event includes modifier keys, sometimes the <code>charCode</code> value is replaced with an ASCII character according to the following rules.
</p><p>The accel key depends on the platform. <kbd>Ctrl</kbd> is the accel key on Windows and Linux, while <kbd>Meta</kbd> (i.e. <kbd>Command</kbd>) is the accel key on Mac.
</p><p>When the accel key is down, the <code>charCode</code> of a keypress event may be replaced with a character from a Latin keyboard layout <b>only</b> when the original character is not an ASCII character.
</p><p>This behavior helps the internationalization of web applications that have custom shortcut keys. If Gecko doesn't replace the <code>charCode</code> with an ASCII character, the web application developers would need to consider all non-Latin keyboard layouts (Arabic, Greek, Hebrew, Russian, etc.).
</p><p>The <code>charCode</code> value depends on the state of <kbd>CapsLock</kbd> and <kbd>NumLock</kbd> (except they are currently ignored if <kbd>Alt</kbd> (<kbd>Option</kbd>) is down on Mac - see {{template.Bug(432953)}}).  There are also some differences between the platforms, as described in the following sections.
</p>
<h4 name="Windows"> Windows </h4>
<p>The <code>charCode</code> is replaced only when <kbd>Ctrl</kbd> is down but <kbd>Alt</kbd> is <b>not</b> down.
</p><p>If the OS-provided character cannot be entered without using the <kbd>Ctrl</kbd> key, then, Gecko does not replace the character. e.g., <kbd>Ctrl+Shift+'2'</kbd> on Persian keyboard layout inputs a ZWNJ, though <kbd>Shift+'2'</kbd> inputs '@', and so, if Gecko were to replace the <code>charCode</code> in this case, users would not be able to input ZWNJ ({{template.Bug(414130)}}).
</p><p>Otherwise, Gecko can replace the <code>charCode</code> with an ASCII character. However, Gecko replaces the <code>charCode</code> only when the key pressed corresponds to a Latin letter (<code>VK_A</code> to <code>VK_Z</code>), numeral (<code>VK_0</code> to <code>VK_9</code>), Plus sign (<code>VK_OEM_PLUS</code>), or Minus sign key (<code>VK_OEM_MINUS</code>).
</p><p>Note that replacing the original (non-ASCII) characters on these keys means that there are some accessibility issues for non-Latin keyboard layout users as many non-ASCII characters will not be available for shortcuts.  Therefore, web application developers should use only letters, ASCII numerals, plus sign, and minus sign for custom shortcut keys.
</p>
<h4 name="Linux"> Linux </h4>
<p>The <code>charCode</code> is replaced only when <kbd>Ctrl</kbd> is down but <kbd>Alt</kbd> and <kbd>Meta</kbd> are <b>not</b> down.
</p><p>If the character provided by the keyboard layout cannot be entered without <kbd>Ctrl</kbd> key, then, Gecko does not replace the character (as on Windows).
</p>
<h4 name="Mac"> Mac </h4>
<p>The <code>charCode</code> is replaced when <kbd>Meta</kbd> (<kbd>Command</kbd>) or <kbd>Ctrl</kbd> is down.
</p><p>If the current keyboard layout is Dvorak-QWERTY layout or a non-Latin layout, the <kbd>Command</kbd> key switches the keyboard layout to the US QWERTY keyboard layout temporary.  Gecko uses the character from this keyboard layout for the <kbd>Ctrl</kbd> key also.
</p><p>However, when <kbd>Ctrl</kbd> is down, Gecko 1.9 currenly only replaces the <code>charCode</code> only when the key corresponds to a basic Latin letter. This behavior is a bug, this behavior will be changed in a future major release ({{template.Bug(432951)}}).
</p>
<h3 name="Alternative_charCodes_for_internal"> Alternative <code>charCode</code>s for internal </h3>
<p>This section documents only Gecko internal keypress event handling, so Web application developers can ignore this section.
</p><p>Gecko replaces the <code>charCode</code> of DOM keypress events for accelerator key handling, but that is not enough.
</p>
<h4 name="Problem_1"> Problem 1 </h4>
<p>The Zoom-in shortcut handler in Firefox is defined as <code>&lt;key key="+" modifiers="accel"/&gt;</code>. However, the <kbd>Shift</kbd> key must be used to enter <kbd>'+'</kbd> on US keyboard layout, and so the state of the Shift key causes the modifiers not to match those specified in the handler.
</p><p>For the US keyboard layout, a related handler is defined with <code>&lt;key key="=" modifiers="accel"/&gt;</code>, so that users do not need to use the Shift key to access the Zoom-in shortcut.  Of course, this is not much help to users with other keyboard layouts.  e.g., on a Japanese keyboard, <kbd>'+'</kbd> is entered with <kbd>Shift+';'</kbd> ({{template.Bug(339723)}}).
</p>
<h4 name="Problem_2"> Problem 2 </h4>
<p>The access keys for the menu items are specified with the localized characters on some localized builds. These localized access keys work fine with the keyboard layout of the locale. However, same user cannot use access keys on En-US build that includes nightly builds ({{template.Bug(399939)}}).
</p>
<h4 name="Problem_3"> Problem 3 </h4>
<p>The non-Latin keyboard layout users cannot use the Latin alphabet access keys on web contents ({{template.Bug(399939)}}).
</p>
<h4 name="Problem_4"> Problem 4 </h4>
<p><kbd>Shift</kbd> key is need to access the access keys of web contents on Windows and Linux. Therefore, the users cannot use some characters that are inputted without <kbd>Shift</kbd> key. So, the unusable characters depend on the keyboard layout ({{template.Bug(359638)}}).
</p>
<h4 name="Solution"> Solution </h4>
<p>There are following rules:
</p>
<ul><li> The key handlers should be able to know the all meanings of the event.
</li><li> The inner element handler should consume the non-exact matching key event even if the outer element handler can match exactly ({{template.Bug(433192)}}).
</li><li> At access key handling, the handlers should ignore the <kbd>Shift</kbd> key state. However, the character that can be inputted without <kbd>Shift</kbd> key is preferred.
</li><li> At shortcut key handling, if the event is fired with <kbd>Shift</kbd> key, but the alternative <code>charCode</code> is not a case changeable character (i.e., it is not an alphabet), then, <kbd>Shift</kbd> key state should be ignored if there are not exact matching handler. (When <kbd>Alt</kbd> key of Mac is pressed, the behavior should be similar, but it is not implemented on Gecko 1.9, See {{template.Bug(306585)}}).
</li><li> At shortcut key handling, if the inputted character is case changeable character (i.e., an alphabet), the <kbd>Shift</kbd> key should not be ignored always. I.e., <kbd>Ctrl+Shift+'C'</kbd> should not execute <kbd>Ctrl+'C'</kbd>.
</li><li> At shortcut key handling, when <kbd>Shift</kbd> key is not pressed and the character without <kbd>Shift</kbd> key is not numeric but the character with <kbd>Shift</kbd> key is numeric, the key may be the numeric keys of AZERTY keyboard layout (E.g., French), then the numeric should be a low priority shortcut key candidate ({{template.Bug(429219)}}).
</li></ul>
<p>So, these conditions are too complex. And the handling rules will be improved if we find new problems. Therefore, XUL application developers should use <code>key</code> element for handling a shortcut key, so, they should <b>not</b> handle it on <code>keypress</code> event themselves. And also they should use <code>accesskey</code> attribute for access keys, so, they should <b>not</b> also handle it on <code>keypress</code> event too.
</p><p>So, if XUL application developers handle themselves, they also need to change the handling code <b>every time</b> when the rules are changed. That is not smart implementation.
</p>
<h4 name="Implementation"> Implementation </h4>
<p>The native keypress event has all meanings of the key. They are set to <code>nsKeyEvent::alternativeCharCodes</code> in <a class="external" href="http://mxr.mozilla.org/mozilla/source/widget/public/nsGUIEvent.h">nsGUIEvent.h</a>. However, the most Gecko developers should not access to this directly. The priority between the alternative <code>charCode</code>s are too complex. The most Gecko developers should use <code>nsContentUtils::GetAccelKeyCandidates()</code> for shortcut keys handling, and <code>nsContentUtils::GetAccessKeyCandidates()</code> for access keys handling (See <a class="external" href="http://mxr.mozilla.org/mozilla/source/content/base/public/nsContentUtils.h">nsContentUtils.h</a> and <a class="external" href="http://mxr.mozilla.org/mozilla/source/content/base/src/nsContentUtils.cpp">nsContentUtils.cpp</a>).
</p>
Revert to this revision