Bug 855975 part.13 widget::NativeKey should manage following WM_*CHAR message if it's initialized with WM_*KEYDOWN r=jimm

This commit is contained in:
Masayuki Nakano 2013-05-29 15:34:48 +09:00
parent c8623ab9ad
commit 77f6812c7f
3 changed files with 72 additions and 31 deletions

View File

@ -387,23 +387,39 @@ VirtualKey::FillKbdState(PBYTE aKbdState,
NativeKey::NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const ModifierKeyState& aModKeyState) :
const ModifierKeyState& aModKeyState,
const nsFakeCharMessage* aFakeCharMessage) :
mWidget(aWidget), mMsg(aKeyOrCharMessage), mDOMKeyCode(0),
mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0)
mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
mIsFakeCharMsg(false)
{
MOZ_ASSERT(aWidget);
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
mKeyboardLayout = keyboardLayout->GetLayout();
mScanCode = WinUtils::GetScanCode(mMsg.lParam);
mIsExtended = WinUtils::IsExtendedScanCode(mMsg.lParam);
memset(&mCharMsg, 0, sizeof(MSG));
// On WinXP and WinServer2003, we cannot compute the virtual keycode for
// extended keys due to the API limitation.
bool canComputeVirtualKeyCodeFromScanCode =
(!mIsExtended || WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION);
switch (mMsg.message) {
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
// Store following WM_*CHAR message into mCharMsg.
if (aFakeCharMessage) {
mCharMsg = aFakeCharMessage->GetCharMessage(mMsg.hwnd);
mIsFakeCharMsg = true;
} else {
MSG msg;
if (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD) &&
(msg.message == WM_CHAR || msg.message == WM_SYSCHAR ||
msg.message == WM_DEADCHAR)) {
mCharMsg = msg;
}
}
case WM_KEYUP:
case WM_SYSKEYUP: {
// First, resolve the IME converted virtual keycode to its original
// keycode.
@ -549,7 +565,9 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
keyboardLayout->InitNativeKey(*this, mModKeyState);
mIsDeadKey = keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState);
mIsDeadKey =
(mCharMsg.message == WM_DEADCHAR ||
keyboardLayout->IsDeadKey(mOriginalVirtualKeyCode, mModKeyState));
mIsPrintableKey = KeyboardLayout::IsPrintableCharKey(mOriginalVirtualKeyCode);
}
@ -940,16 +958,39 @@ NativeKey::NeedsToHandleWithoutFollowingCharMessages() const
return IsPrintableKey();
}
const MSG&
NativeKey::RemoveFollowingCharMessage() const
{
MOZ_ASSERT(IsFollowedByCharMessage());
if (mIsFakeCharMsg) {
return mCharMsg;
}
MSG msg;
if (!WinUtils::GetMessage(&msg, mMsg.hwnd,
mCharMsg.message, mCharMsg.message)) {
MOZ_NOT_REACHED("We lost the following char message");
return mCharMsg;
}
MOZ_ASSERT(mCharMsg.message == msg.message &&
mCharMsg.wParam == msg.wParam &&
mCharMsg.lParam == msg.lParam);
return mCharMsg;
}
void
NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg,
const nsFakeCharMessage* aFakeCharMessage) const
NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
UINT aLastMsg) const
{
MSG msg;
if (aFakeCharMessage) {
if (mIsFakeCharMsg) {
if (aFirstMsg > WM_CHAR || aLastMsg < WM_CHAR) {
return;
}
msg = aFakeCharMessage->GetCharMessage(mMsg.hwnd);
msg = mCharMsg;
} else {
WinUtils::GetMessage(&msg, mMsg.hwnd, aFirstMsg, aLastMsg);
}
@ -959,8 +1000,7 @@ NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg,
bool
NativeKey::DispatchKeyPressEventsAndDiscardsCharMessages(
const UniCharsAndModifiers& aInputtingChars,
const EventFlags& aExtraFlags,
const nsFakeCharMessage* aFakeCharMessage) const
const EventFlags& aExtraFlags) const
{
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
@ -970,9 +1010,8 @@ NativeKey::DispatchKeyPressEventsAndDiscardsCharMessages(
// * Some keyboard layouts may map up to 4 characters to the single key
bool anyCharMessagesRemoved = false;
if (aFakeCharMessage) {
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST,
aFakeCharMessage);
if (mIsFakeCharMsg) {
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
anyCharMessagesRemoved = true;
} else {
MSG msg;
@ -989,7 +1028,7 @@ NativeKey::DispatchKeyPressEventsAndDiscardsCharMessages(
if (!anyCharMessagesRemoved &&
mDOMKeyCode == NS_VK_BACK && IsIMEDoingKakuteiUndo()) {
MOZ_ASSERT(!aFakeCharMessage);
MOZ_ASSERT(!mIsFakeCharMsg);
RemoveMessageAndDispatchPluginEvent(WM_CHAR, WM_CHAR);
}

View File

@ -283,7 +283,8 @@ class MOZ_STACK_CLASS NativeKey
public:
NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const ModifierKeyState& aModKeyState);
const ModifierKeyState& aModKeyState,
const nsFakeCharMessage* aFakeCharMessage = nullptr);
uint32_t GetDOMKeyCode() const { return mDOMKeyCode; }
KeyNameIndex GetKeyNameIndex() const { return mKeyNameIndex; }
@ -297,6 +298,12 @@ public:
{
return (mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
}
bool IsFollowedByCharMessage() const
{
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
return (mCharMsg.message != 0);
}
const MSG& RemoveFollowingCharMessage() const;
bool IsDeadKey() const { return mIsDeadKey; }
/**
* IsPrintableKey() returns true if the key may be a printable key without
@ -357,8 +364,7 @@ public:
*/
bool DispatchKeyPressEventsAndDiscardsCharMessages(
const UniCharsAndModifiers& aInputtingChars,
const EventFlags& aExtraFlags,
const nsFakeCharMessage* aFakeCharMessage) const;
const EventFlags& aExtraFlags) const;
/**
* Checkes whether the key event down message is handled without following
@ -394,6 +400,10 @@ private:
nsRefPtr<nsWindowBase> mWidget;
HKL mKeyboardLayout;
MSG mMsg;
// mCharMsg stores WM_*CHAR message following WM_*KEYDOWN message.
// If mMsg isn't WM_*KEYDOWN message or WM_*KEYDOWN but there is no following
// WM_*CHAR message, the message member is 0.
MSG mCharMsg;
uint32_t mDOMKeyCode;
KeyNameIndex mKeyNameIndex;
@ -416,6 +426,7 @@ private:
bool mIsExtended;
bool mIsDeadKey;
bool mIsPrintableKey;
bool mIsFakeCharMsg;
NativeKey()
{
@ -437,8 +448,7 @@ private:
/*
* Dispatches a plugin event after the specified message is removed.
*/
void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg,
const nsFakeCharMessage* aFakeCharMessage = nullptr) const;
void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg) const;
};
class KeyboardLayout

View File

@ -6358,7 +6358,7 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
nsFakeCharMessage* aFakeCharMessage)
{
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
NativeKey nativeKey(this, aMsg, aModKeyState);
NativeKey nativeKey(this, aMsg, aModKeyState, aFakeCharMessage);
UniCharsAndModifiers inputtingChars =
nativeKey.GetCommittedCharsAndModifiers();
uint32_t DOMKeyCode = nativeKey.GetDOMKeyCode();
@ -6453,18 +6453,12 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
if (nativeKey.NeedsToHandleWithoutFollowingCharMessages()) {
return nativeKey.DispatchKeyPressEventsAndDiscardsCharMessages(
inputtingChars, extraFlags, aFakeCharMessage);
inputtingChars, extraFlags);
}
MSG msg;
BOOL gotMsg = aFakeCharMessage ||
WinUtils::PeekMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD);
if (gotMsg &&
(aFakeCharMessage || msg.message == WM_CHAR ||
msg.message == WM_SYSCHAR || msg.message == WM_DEADCHAR)) {
if (nativeKey.IsFollowedByCharMessage()) {
const MSG& msg = nativeKey.RemoveFollowingCharMessage();
if (aFakeCharMessage) {
MSG msg = aFakeCharMessage->GetCharMessage(mWnd);
if (msg.message == WM_DEADCHAR) {
return false;
}
@ -6493,8 +6487,6 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
}
// If prevent default set for keydown, do same for keypress
WinUtils::GetMessage(&msg, mWnd, msg.message, msg.message);
if (msg.message == WM_DEADCHAR) {
if (!PluginHasFocus())
return false;