Bug 1036008 - Use alternative ASCII capable keyboard layout information to decide keyCode even if the key produces an ASCII punctuation character r=smaug

Gecko decides keyCode from an ASCII character which is produced by the key
by itself or with Shift on active keyboard layout or alternative ASCII capable
keyboard layout if active keyboard layout isn't ASCII capable.  However, we've
ignored alternative ASCII capable keyboard layout's character if both the
key itself and with Shift don't produce ASCII alphabet nor ASCII numeral,
i.e., ASCII punctuation characters are not used in alternative ASCII capable
keyboard layout because of avoiding mapping a keyCode value to 2 or more keys.

However, setting 0 to keyCode value makes Firefox unusable with some web
applications which are aware of neither KeyboardEvent.key nor
KeyboardEvent.code.  So, even if we map same keyCode value to a key, we should
avoid setting keyCode value to 0 as far as possible.

This patch's approach is, we behave same keyCode value as the alternative ASCII
capable keyCode is selected when computed keyCode value of active keyboard
layout is 0.  This means that we will make some language users whose keyboard
layout for their language is not ASCII capable can use global web services
which support US keyboard layout of Firefox since the new keyCode values
are mostly computed with US layout on Windows or actual alternative ASCII
capable keyboard layout on macOS and Linux.  In other words, we cannot improve
compatibility with web applications which don't support Firefox  by this patch
since our keyCode values are really different from Chrome's.  So, unfortunately,
if we'd use exactly same keyCode computation as Chromium, we'd break
compatibility with existing web applications which are aware of Firefox since
it's necessary to check UA name or something before using keyCode values.

Note that the most important difference between Windows and the others is,
such keyCode value is computed with alternative ASCII capable keyboard
layout on macOS and Linux but only on Windows, it's computed with OEM virtual
keycode.  This means that only on Windows, the keyCode value may be different
from actual alternative ASCII capable keyboard layout's keyCode.

MozReview-Commit-ID: As289r9wp6i
This commit is contained in:
Masayuki Nakano
2018-02-16 15:54:07 +09:00
parent 7c4a938629
commit 75c48dde4c
7 changed files with 222 additions and 51 deletions

View File

@@ -4721,7 +4721,75 @@ KeyboardLayout::ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const
uniChars = GetUniCharsAndModifiers(aNativeKeyCode, modKeyState);
if (uniChars.Length() != 1 ||
uniChars.CharAt(0) < ' ' || uniChars.CharAt(0) > 0x7F) {
return 0;
// In this case, we've returned 0 in this case for long time because
// we decided that we should avoid setting same keyCode value to 2 or
// more keys since active keyboard layout may have a key to input the
// punctuation with different key. However, setting keyCode to 0
// makes some web applications which are aware of neither
// KeyboardEvent.key nor KeyboardEvent.code not work with Firefox
// when user selects non-ASCII capable keyboard layout such as
// Russian and Thai layout. So, let's decide keyCode value with
// major keyboard layout's key which causes the OEM keycode.
// Actually, this maps same keyCode value to 2 keys on Russian
// keyboard layout. "Period" key causes VK_OEM_PERIOD but inputs
// Yu of Cyrillic and "Slash" key causes VK_OEM_2 (same as US
// keyboard layout) but inputs "." (period of ASCII). Therefore,
// we return DOM_VK_PERIOD which is same as VK_OEM_PERIOD for
// "Period" key. On the other hand, we use same keyCode value for
// "Slash" key too because it inputs ".".
CodeNameIndex code;
switch (aNativeKeyCode) {
case VK_OEM_1:
code = CODE_NAME_INDEX_Semicolon;
break;
case VK_OEM_PLUS:
code = CODE_NAME_INDEX_Equal;
break;
case VK_OEM_COMMA:
code = CODE_NAME_INDEX_Comma;
break;
case VK_OEM_MINUS:
code = CODE_NAME_INDEX_Minus;
break;
case VK_OEM_PERIOD:
code = CODE_NAME_INDEX_Period;
break;
case VK_OEM_2:
code = CODE_NAME_INDEX_Slash;
break;
case VK_OEM_3:
code = CODE_NAME_INDEX_Backquote;
break;
case VK_OEM_4:
code = CODE_NAME_INDEX_BracketLeft;
break;
case VK_OEM_5:
code = CODE_NAME_INDEX_Backslash;
break;
case VK_OEM_6:
code = CODE_NAME_INDEX_BracketRight;
break;
case VK_OEM_7:
code = CODE_NAME_INDEX_Quote;
break;
case VK_OEM_8:
// Use keyCode value for "Backquote" key on UK keyboard layout.
code = CODE_NAME_INDEX_Backquote;
break;
case VK_OEM_102:
// Use keyCode value for "IntlBackslash" key.
code = CODE_NAME_INDEX_IntlBackslash;
break;
case VK_ABNT_C1: // "/" of ABNT.
// Use keyCode value for "IntlBackslash" key on ABNT keyboard
// layout.
code = CODE_NAME_INDEX_IntlBackslash;
break;
default:
MOZ_ASSERT_UNREACHABLE("Handle all OEM keycode values");
return 0;
}
return WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(code);
}
}
return WidgetUtils::ComputeKeyCodeFromChar(uniChars.CharAt(0));