Bug 1263389 NativeKey should initialize WidgetKeyboardEvent::mKeyValue of WM_KEYDOWN of VK_PACKET with following char message r=m_kato

TextEventDispatcher initializes charCode value with mKeyValue (and mKeyNameIndex) of WidgetKeyboardEvent.  Therefore, NativeKey needs to initialize mKeyValue properly at handling WM_KEYDOWN message of VK_PACKET.  However, nobody initializes mCommittedCharsAndModifiers value of VK_PACKET.  Additionally, KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex() returns KEY_NAME_INDEX_Unidentified for it too.

Therefore, this patch creates a path for handling VK_PACKET.  First, makes KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex() returns KEY_NAME_INDEX_USE_STRING.  Next, the constructor of NativeKey initializes mCommittedCharsAndModifiers with following char message.  Additionally, makes sure that VK_PACKET is always handled with following char message even if there is no char message.
This commit is contained in:
Masayuki Nakano 2016-04-25 16:42:59 +09:00
Родитель 4f6a58fd72
Коммит 4b0070a96d
2 изменённых файлов: 70 добавлений и 27 удалений

Просмотреть файл

@ -725,23 +725,6 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
case WM_KEYUP:
case WM_SYSKEYUP:
case MOZ_WM_KEYUP: {
// If the key message is sent from other application like a11y tools, the
// scancode value might not be set proper value. Then, probably the value
// is 0.
// NOTE: If the virtual keycode can be caused by both non-extended key
// and extended key, the API returns the non-extended key's
// scancode. E.g., VK_LEFT causes "4" key on numpad.
// NOTE: Cannot compute scancode from keycode if the key message comes
// from plugin process since active keyboard layout may be
// different.
if (!mScanCode) {
uint16_t scanCodeEx = ComputeScanCodeExFromVirtualKeyCode(mMsg.wParam);
if (scanCodeEx) {
mScanCode = static_cast<uint8_t>(scanCodeEx & 0xFF);
uint8_t extended = static_cast<uint8_t>((scanCodeEx & 0xFF00) >> 8);
mIsExtended = (extended == 0xE0) || (extended == 0xE1);
}
}
// First, resolve the IME converted virtual keycode to its original
// keycode.
if (mMsg.wParam == VK_PROCESSKEY) {
@ -751,6 +734,21 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
mOriginalVirtualKeyCode = static_cast<uint8_t>(mMsg.wParam);
}
// If the key message is sent from other application like a11y tools, the
// scancode value might not be set proper value. Then, probably the value
// is 0.
// NOTE: If the virtual keycode can be caused by both non-extended key
// and extended key, the API returns the non-extended key's
// scancode. E.g., VK_LEFT causes "4" key on numpad.
if (!mScanCode && mOriginalVirtualKeyCode != VK_PACKET) {
uint16_t scanCodeEx = ComputeScanCodeExFromVirtualKeyCode(mMsg.wParam);
if (scanCodeEx) {
mScanCode = static_cast<uint8_t>(scanCodeEx & 0xFF);
uint8_t extended = static_cast<uint8_t>((scanCodeEx & 0xFF00) >> 8);
mIsExtended = (extended == 0xE0) || (extended == 0xE1);
}
}
// Most keys are not distinguished as left or right keys.
bool isLeftRightDistinguishedKey = false;
@ -894,12 +892,35 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState));
mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode);
// Compute some strings which may be inputted by the key with various
// modifier state if this key event won't cause text input actually.
// They will be used for setting alternativeCharCodes in the callback
// method which will be called by TextEventDispatcher.
if (IsKeyDownMessage() && NeedsToHandleWithoutFollowingCharMessages()) {
ComputeInputtingStringWithKeyboardLayout();
if (IsKeyDownMessage()) {
// Compute some strings which may be inputted by the key with various
// modifier state if this key event won't cause text input actually.
// They will be used for setting alternativeCharCodes in the callback
// method which will be called by TextEventDispatcher.
if (NeedsToHandleWithoutFollowingCharMessages()) {
ComputeInputtingStringWithKeyboardLayout();
} else if (mVirtualKeyCode == VK_PACKET) {
// If this is sent by SendInput() API to input a Unicode character,
// we can only know what char will be inputted with following WM_CHAR
// message.
// TODO: We cannot initialize mCommittedCharsAndModifiers for VK_PACKET
// if the message is WM_KEYUP because we don't have preceding
// WM_CHAR message. Therefore, we should dispatch eKeyUp event at
// handling WM_KEYDOWN.
// TODO: Like Edge, we shouldn't dispatch two sets of keyboard events
// for a Unicode character in non-BMP because its key value looks
// broken and not good thing for our editor if only one keydown or
// keypress event's default is prevented. I guess, we should store
// key message information globally and we should wait following
// WM_KEYDOWN if following WM_CHAR is a part of a Unicode character.
MSG followingCharMsg;
if (GetFollowingCharMessage(followingCharMsg, false) &&
followingCharMsg.wParam) {
mCommittedCharsAndModifiers.Append(
static_cast<char16_t>(followingCharMsg.wParam),
mModKeyState.GetModifiers());
}
}
}
}
@ -1603,6 +1624,12 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
return DispatchKeyPressEventForFollowingCharMessage(followingCharMsg);
}
// If WM_KEYDOWN of VK_PACKET isn't followed by WM_CHAR, we don't need to
// dispatch keypress events.
if (mVirtualKeyCode == VK_PACKET) {
return false;
}
if (!mModKeyState.IsControl() && !mModKeyState.IsAlt() &&
!mModKeyState.IsWin() && mIsPrintableKey) {
// If this is simple KeyDown event but next message is not WM_CHAR,
@ -1789,6 +1816,12 @@ NativeKey::NeedsToHandleWithoutFollowingCharMessages() const
return true;
}
// If the keydown message is generated for inputting some Unicode characters
// via SendInput() API, we need to handle it only with WM_*CHAR messages.
if (mVirtualKeyCode == VK_PACKET) {
return false;
}
// Enter and backspace are always handled here to avoid for example the
// confusion between ctrl-enter and ctrl-J.
if (mDOMKeyCode == NS_VK_RETURN || mDOMKeyCode == NS_VK_BACK) {
@ -1889,7 +1922,7 @@ NativeKey::MayBeSameCharMessage(const MSG& aCharMsg1,
}
bool
NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
NativeKey::GetFollowingCharMessage(MSG& aCharMsg, bool aRemove) const
{
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!IsKeyMessageOnPlugin());
@ -1903,7 +1936,7 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
continue;
}
MSG charMsg = fakeCharMsg.GetCharMsg(mMsg.hwnd);
fakeCharMsg.mConsumed = true;
fakeCharMsg.mConsumed = aRemove;
if (!IsCharMessage(charMsg)) {
return false;
}
@ -1925,6 +1958,11 @@ NativeKey::GetFollowingCharMessage(MSG& aCharMsg) const
return false;
}
if (!aRemove) {
aCharMsg = nextKeyMsg;
return true;
}
// On Metrofox, PeekMessage() sometimes returns WM_NULL even if we specify
// the message range. So, if it returns WM_NULL, we should retry to get
// the following char message it was found above.
@ -2509,6 +2547,8 @@ KeyboardLayout::InitNativeKey(NativeKey& aNativeKey,
return;
}
MOZ_ASSERT(virtualKey != VK_PACKET,
"At handling VK_PACKET, we shouldn't refer keyboard layout");
MOZ_ASSERT(aNativeKey.mKeyNameIndex == KEY_NAME_INDEX_USE_STRING,
"Printable key's key name index must be KEY_NAME_INDEX_USE_STRING");
@ -3178,7 +3218,7 @@ KeyboardLayout::ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const
KeyNameIndex
KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
{
if (IsPrintableCharKey(aVirtualKey)) {
if (IsPrintableCharKey(aVirtualKey) || aVirtualKey == VK_PACKET) {
return KEY_NAME_INDEX_USE_STRING;
}

Просмотреть файл

@ -420,8 +420,11 @@ private:
*
* WARNING: Even if this returns true, aCharMsg may be WM_NULL or its
* hwnd may be different window.
*
* @param aRemove true if the found message should be removed from the
* queue. Otherwise, false.
*/
bool GetFollowingCharMessage(MSG& aCharMsg) const;
bool GetFollowingCharMessage(MSG& aCharMsg, bool aRemove = true) const;
/**
* Whether the key event can compute virtual keycode from the scancode value.