Bug 842927 part.3 Implement D3E KeyboardEvent.key on Windows (Desktop) r=smaug+jimm

This commit is contained in:
Masayuki Nakano 2013-04-24 12:49:47 +09:00
parent a14e2178fc
commit 877ab22109
3 changed files with 112 additions and 36 deletions

View File

@ -384,7 +384,8 @@ VirtualKey::FillKbdState(PBYTE aKbdState,
NativeKey::NativeKey(const KeyboardLayout& aKeyboardLayout,
nsWindow* aWindow,
const MSG& aKeyOrCharMessage) :
mDOMKeyCode(0), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0)
mDOMKeyCode(0), mMessage(aKeyOrCharMessage.message),
mVirtualKeyCode(0), mOriginalVirtualKeyCode(0)
{
mScanCode = WinUtils::GetScanCode(aKeyOrCharMessage.lParam);
mIsExtended = WinUtils::IsExtendedScanCode(aKeyOrCharMessage.lParam);
@ -392,7 +393,7 @@ NativeKey::NativeKey(const KeyboardLayout& aKeyboardLayout,
// extended keys due to the API limitation.
bool canComputeVirtualKeyCodeFromScanCode =
(!mIsExtended || WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION);
switch (aKeyOrCharMessage.message) {
switch (mMessage) {
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
@ -540,6 +541,8 @@ NativeKey::NativeKey(const KeyboardLayout& aKeyboardLayout,
mDOMKeyCode =
aKeyboardLayout.ConvertNativeKeyCodeToDOMKeyCode(mOriginalVirtualKeyCode);
mKeyNameIndex =
aKeyboardLayout.ConvertNativeKeyCodeToKeyNameIndex(mOriginalVirtualKeyCode);
}
UINT
@ -659,48 +662,66 @@ KeyboardLayout::IsDeadKey(uint8_t aVirtualKey,
VirtualKey::ModifiersToShiftState(aModKeyState.GetModifiers()));
}
UniCharsAndModifiers
KeyboardLayout::OnKeyDown(uint8_t aVirtualKey,
const ModifierKeyState& aModKeyState)
void
KeyboardLayout::InitNativeKey(NativeKey& aNativeKey,
const ModifierKeyState& aModKeyState)
{
if (mPendingKeyboardLayout) {
LoadLayout(mPendingKeyboardLayout);
}
int32_t virtualKeyIndex = GetKeyIndex(aVirtualKey);
uint8_t virtualKey = aNativeKey.GetOriginalVirtualKeyCode();
int32_t virtualKeyIndex = GetKeyIndex(virtualKey);
if (virtualKeyIndex < 0) {
// Does not produce any printable characters, but still preserves the
// dead-key state.
return UniCharsAndModifiers();
return;
}
bool isKeyDown = aNativeKey.IsKeyDownMessage();
uint8_t shiftState =
VirtualKey::ModifiersToShiftState(aModKeyState.GetModifiers());
if (mVirtualKeys[virtualKeyIndex].IsDeadKey(shiftState)) {
if (mActiveDeadKey < 0) {
// Dead-key state activated. No characters generated.
mActiveDeadKey = aVirtualKey;
mDeadKeyShiftState = shiftState;
return UniCharsAndModifiers();
if ((isKeyDown && mActiveDeadKey < 0) ||
(!isKeyDown && mActiveDeadKey == virtualKey)) {
// First dead key event doesn't generate characters.
if (isKeyDown) {
// Dead-key state activated at keydown.
mActiveDeadKey = virtualKey;
mDeadKeyShiftState = shiftState;
}
UniCharsAndModifiers deadChars =
mVirtualKeys[virtualKeyIndex].GetNativeUniChars(shiftState);
NS_ASSERTION(deadChars.mLength == 1,
"dead key must generate only one character");
aNativeKey.mKeyNameIndex =
WidgetUtils::GetDeadKeyNameIndex(deadChars.mChars[0]);
return;
}
// Dead-key followed by another dead-key. Reset dead-key state and
// return both dead-key characters.
int32_t activeDeadKeyIndex = GetKeyIndex(mActiveDeadKey);
UniCharsAndModifiers result =
UniCharsAndModifiers prevDeadChars =
mVirtualKeys[activeDeadKeyIndex].GetUniChars(mDeadKeyShiftState);
result += mVirtualKeys[virtualKeyIndex].GetUniChars(shiftState);
DeactivateDeadKeyState();
return result;
UniCharsAndModifiers newChars =
mVirtualKeys[virtualKeyIndex].GetUniChars(shiftState);
// But keypress events should be fired for each committed character.
aNativeKey.mCommittedCharsAndModifiers = prevDeadChars + newChars;
if (isKeyDown) {
DeactivateDeadKeyState();
}
return;
}
UniCharsAndModifiers baseChars =
mVirtualKeys[virtualKeyIndex].GetUniChars(shiftState);
if (mActiveDeadKey < 0) {
// No dead-keys are active. Just return the produced characters.
return baseChars;
aNativeKey.mCommittedCharsAndModifiers = baseChars;
return;
}
// Dead-key was active. See if pressed base character does produce
@ -712,20 +733,25 @@ KeyboardLayout::OnKeyDown(uint8_t aVirtualKey,
if (compositeChar) {
// Active dead-key and base character does produce exactly one
// composite character.
UniCharsAndModifiers result;
result.Append(compositeChar, baseChars.mModifiers[0]);
DeactivateDeadKeyState();
return result;
aNativeKey.mCommittedCharsAndModifiers.Append(compositeChar,
baseChars.mModifiers[0]);
if (isKeyDown) {
DeactivateDeadKeyState();
}
return;
}
// There is no valid dead-key and base character combination.
// Return dead-key character followed by base character.
UniCharsAndModifiers result =
UniCharsAndModifiers deadChars =
mVirtualKeys[activeDeadKeyIndex].GetUniChars(mDeadKeyShiftState);
result += baseChars;
DeactivateDeadKeyState();
// But keypress events should be fired for each committed character.
aNativeKey.mCommittedCharsAndModifiers = deadChars + baseChars;
if (isKeyDown) {
DeactivateDeadKeyState();
}
return result;
return;
}
UniCharsAndModifiers
@ -1254,6 +1280,24 @@ KeyboardLayout::ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const
return 0;
}
KeyNameIndex
KeyboardLayout::ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const
{
switch (aVirtualKey) {
#define NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, aKeyNameIndex) \
case aNativeKey: return aKeyNameIndex;
#include "NativeKeyToDOMKeyName.h"
#undef NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX
default:
return IsPrintableCharKey(aVirtualKey) ? KEY_NAME_INDEX_PrintableKey :
KEY_NAME_INDEX_Unidentified;
}
}
/*****************************************************************************
* mozilla::widget::DeadKeyTable
*****************************************************************************/

View File

@ -271,7 +271,8 @@ public:
class NativeKey {
public:
NativeKey() :
mDOMKeyCode(0), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
mDOMKeyCode(0), mKeyNameIndex(KEY_NAME_INDEX_Unidentified),
mMessage(0), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
mScanCode(0), mIsExtended(false)
{
}
@ -281,25 +282,48 @@ public:
const MSG& aKeyOrCharMessage);
uint32_t GetDOMKeyCode() const { return mDOMKeyCode; }
KeyNameIndex GetKeyNameIndex() const { return mKeyNameIndex; }
const UniCharsAndModifiers& GetCommittedCharsAndModifiers() const
{
return mCommittedCharsAndModifiers;
}
// The result is one of nsIDOMKeyEvent::DOM_KEY_LOCATION_*.
uint32_t GetKeyLocation() const;
UINT GetMessage() const { return mMessage; }
bool IsKeyDownMessage() const
{
return (mMessage == WM_KEYDOWN || mMessage == WM_SYSKEYDOWN);
}
WORD GetScanCode() const { return mScanCode; }
uint8_t GetVirtualKeyCode() const { return mVirtualKeyCode; }
uint8_t GetOriginalVirtualKeyCode() const { return mOriginalVirtualKeyCode; }
private:
uint32_t mDOMKeyCode;
KeyNameIndex mKeyNameIndex;
// The message which the instance was initialized with.
UINT mMessage;
// mVirtualKeyCode distinguishes left key or right key of modifier key.
uint8_t mVirtualKeyCode;
// mOriginalVirtualKeyCode doesn't distinguish left key or right key of
// modifier key. However, if the given keycode is VK_PROCESS, it's resolved
// to a keycode before it's handled by IME.
uint8_t mOriginalVirtualKeyCode;
// mCommittedChars indicates the inputted characters which is committed by
// the key. If dead key fail to composite a character, mCommittedChars
// indicates both the dead characters and the base characters.
UniCharsAndModifiers mCommittedCharsAndModifiers;
WORD mScanCode;
bool mIsExtended;
UINT GetScanCodeWithExtendedFlag() const;
friend class KeyboardLayout;
};
class KeyboardLayout
@ -357,12 +381,13 @@ public:
const ModifierKeyState& aModKeyState) const;
/**
* OnKeyDown() must be called when actually widget receives WM_KEYDOWN
* message. This method is stateful. This saves current dead key state
* and computes current inputted character(s).
* InitNativeKey() must be called when actually widget receives WM_KEYDOWN or
* WM_KEYUP. This method is stateful. This saves current dead key state at
* WM_KEYDOWN. Additionally, computes current inputted character(s) and set
* them to the aNativeKey.
*/
UniCharsAndModifiers OnKeyDown(uint8_t aVirtualKey,
const ModifierKeyState& aModKeyState);
void InitNativeKey(NativeKey& aNativeKey,
const ModifierKeyState& aModKeyState);
/**
* LoadLayout() loads the keyboard layout. If aLoadLater is true,
@ -372,6 +397,12 @@ public:
uint32_t ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const;
/**
* ConvertNativeKeyCodeToKeyNameIndex() returns KeyNameIndex value for
* non-printable keys (except some special keys like space key).
*/
KeyNameIndex ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const;
HKL GetLayout() const
{
return mPendingKeyboardLayout ? mPendingKeyboardLayout : mKeyboardLayout;

View File

@ -3622,6 +3622,7 @@ void nsWindow::InitKeyEvent(nsKeyEvent& aKeyEvent,
{
nsIntPoint point(0, 0);
InitEvent(aKeyEvent, &point);
aKeyEvent.mKeyNameIndex = aNativeKey.GetKeyNameIndex();
aKeyEvent.location = aNativeKey.GetKeyLocation();
aModKeyState.InitInputEvent(aKeyEvent);
}
@ -5654,6 +5655,7 @@ LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, bool *aEventDispatched)
// if a child window didn't handle it (for example Alt+Space in a content window)
ModifierKeyState modKeyState;
NativeKey nativeKey(gKbdLayout, this, aMsg);
gKbdLayout.InitNativeKey(nativeKey, modKeyState);
return OnChar(aMsg, nativeKey, modKeyState, aEventDispatched);
}
@ -6461,12 +6463,9 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
nsFakeCharMessage* aFakeCharMessage)
{
NativeKey nativeKey(gKbdLayout, this, aMsg);
UINT virtualKeyCode = nativeKey.GetOriginalVirtualKeyCode();
gKbdLayout.InitNativeKey(nativeKey, aModKeyState);
UniCharsAndModifiers inputtingChars =
gKbdLayout.OnKeyDown(virtualKeyCode, aModKeyState);
// Use only DOMKeyCode for XP processing.
// Use virtualKeyCode for gKbdLayout and native processing.
nativeKey.GetCommittedCharsAndModifiers();
uint32_t DOMKeyCode = nativeKey.GetDOMKeyCode();
#ifdef DEBUG
@ -6554,6 +6553,7 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
return noDefault;
}
UINT virtualKeyCode = nativeKey.GetOriginalVirtualKeyCode();
bool isDeadKey = gKbdLayout.IsDeadKey(virtualKeyCode, aModKeyState);
EventFlags extraFlags;
extraFlags.mDefaultPrevented = noDefault;
@ -6830,6 +6830,7 @@ LRESULT nsWindow::OnKeyUp(const MSG &aMsg,
*aEventDispatched = true;
nsKeyEvent keyupEvent(true, NS_KEY_UP, this);
NativeKey nativeKey(gKbdLayout, this, aMsg);
gKbdLayout.InitNativeKey(nativeKey, aModKeyState);
keyupEvent.keyCode = nativeKey.GetDOMKeyCode();
InitKeyEvent(keyupEvent, nativeKey, aModKeyState);
// Set defaultPrevented of the key event if the VK_MENU is not a system key