Bug 892606 part.3 FakeCharMsg should be marked as consumed and only non-consumed char message should be synthesized r=jimm

This commit is contained in:
Masayuki Nakano 2013-08-14 11:09:38 +09:00
Родитель f29b3580a9
Коммит 890fa71e70
2 изменённых файлов: 64 добавлений и 49 удалений

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

@ -398,10 +398,11 @@ VirtualKey::FillKbdState(PBYTE aKbdState,
NativeKey::NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const ModifierKeyState& aModKeyState,
const FakeCharMsg* aFakeCharMsg) :
nsTArray<FakeCharMsg>* aFakeCharMsgs) :
mWidget(aWidget), mMsg(aKeyOrCharMessage), mDOMKeyCode(0),
mModKeyState(aModKeyState), mVirtualKeyCode(0), mOriginalVirtualKeyCode(0),
mIsFakeCharMsg(false)
mFakeCharMsgs(aFakeCharMsgs && aFakeCharMsgs->Length() ?
aFakeCharMsgs : nullptr)
{
MOZ_ASSERT(aWidget);
KeyboardLayout* keyboardLayout = KeyboardLayout::GetInstance();
@ -417,9 +418,8 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
// Store following WM_*CHAR message into mCharMsg.
if (aFakeCharMsg) {
mCharMsg = aFakeCharMsg->GetCharMsg(mMsg.hwnd);
mIsFakeCharMsg = true;
if (mFakeCharMsgs) {
mCharMsg = mFakeCharMsgs->ElementAt(0).GetCharMsg(mMsg.hwnd);
} else {
MSG msg;
if (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
@ -777,20 +777,16 @@ NativeKey::DispatchKeyEvent(nsKeyEvent& aKeyEvent,
}
bool
NativeKey::HandleKeyDownMessage(bool* aEventDispatched,
bool* aWasKeyDownDefaultPrevented) const
NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
{
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
if (aEventDispatched) {
*aEventDispatched = false;
}
if (aWasKeyDownDefaultPrevented) {
*aWasKeyDownDefaultPrevented = false;
}
bool defaultPrevented = false;
if (mIsFakeCharMsg ||
if (mFakeCharMsgs ||
!RedirectedKeyDownMessageManager::IsRedirectedMessage(mMsg)) {
// Ignore [shift+]alt+space so the OS can handle it.
if (mModKeyState.IsAlt() && !mModKeyState.IsControl() &&
@ -807,11 +803,6 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched,
defaultPrevented = DispatchKeyEvent(keydownEvent, &mMsg);
if (mWidget->Destroyed()) {
// If this was destroyed by the keydown event handler, we shouldn't
// dispatch keypress event on this window.
if (aWasKeyDownDefaultPrevented) {
*aWasKeyDownDefaultPrevented = true;
}
return true;
}
@ -824,7 +815,7 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched,
// application, we shouldn't redirect the message to it because the keydown
// message is processed by us, so, nobody shouldn't process it.
HWND focusedWnd = ::GetFocus();
if (!defaultPrevented && !mIsFakeCharMsg && focusedWnd &&
if (!defaultPrevented && !mFakeCharMsgs && focusedWnd &&
!mWidget->PluginHasFocus() && !isIMEEnabled &&
WinUtils::IsIMEEnabled(mWidget->GetInputContext())) {
RedirectedKeyDownMessageManager::RemoveNextCharMessage(focusedWnd);
@ -847,9 +838,6 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched,
// Return here. We shouldn't dispatch keypress event for this WM_KEYDOWN.
// If it's needed, it will be dispatched after next (redirected)
// WM_KEYDOWN.
if (aWasKeyDownDefaultPrevented) {
*aWasKeyDownDefaultPrevented = true;
}
return true;
}
} else {
@ -861,10 +849,6 @@ NativeKey::HandleKeyDownMessage(bool* aEventDispatched,
}
}
if (aWasKeyDownDefaultPrevented) {
*aWasKeyDownDefaultPrevented = defaultPrevented;
}
RedirectedKeyDownMessageManager::Forget();
// If the key was processed by IME, we shouldn't dispatch keypress event.
@ -1085,7 +1069,10 @@ NativeKey::RemoveFollowingCharMessage() const
{
MOZ_ASSERT(IsFollowedByCharMessage());
if (mIsFakeCharMsg) {
if (mFakeCharMsgs) {
MOZ_ASSERT(!mFakeCharMsgs->ElementAt(0).mConsumed,
"Doesn't assume that it's used for removing two or more char messages");
mFakeCharMsgs->ElementAt(0).mConsumed = true;
return mCharMsg;
}
@ -1107,11 +1094,23 @@ NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
UINT aLastMsg) const
{
MSG msg;
if (mIsFakeCharMsg) {
if (aFirstMsg > WM_CHAR || aLastMsg < WM_CHAR) {
return false;
if (mFakeCharMsgs) {
DebugOnly<bool> found = false;
for (uint32_t i = 0; i < mFakeCharMsgs->Length(); i++) {
FakeCharMsg& fakeCharMsg = mFakeCharMsgs->ElementAt(i);
if (fakeCharMsg.mConsumed) {
continue;
}
MSG fakeMsg = fakeCharMsg.GetCharMsg(mMsg.hwnd);
if (fakeMsg.message < aFirstMsg || fakeMsg.message > aLastMsg) {
continue;
}
fakeCharMsg.mConsumed = true;
msg = fakeMsg;
found = true;
break;
}
msg = mCharMsg;
MOZ_ASSERT(found, "Fake char message must be found");
} else {
WinUtils::GetMessage(&msg, mMsg.hwnd, aFirstMsg, aLastMsg);
}
@ -1127,8 +1126,13 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
{
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
if (mIsFakeCharMsg) {
return RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
if (mFakeCharMsgs) {
for (uint32_t i = 0; i < mFakeCharMsgs->Length(); i++) {
if (RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST)) {
return true;
}
}
return false;
}
// Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
@ -1330,7 +1334,7 @@ NativeKey::DispatchKeyPressEventForFollowingCharMessage() const
MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
const MSG& msg = RemoveFollowingCharMessage();
if (mIsFakeCharMsg) {
if (mFakeCharMsgs) {
if (msg.message == WM_DEADCHAR) {
return false;
}
@ -2310,20 +2314,25 @@ KeyboardLayout::SynthesizeNativeKeyEvent(nsWindowBase* aWidget,
NativeKey nativeKey(aWidget, keyDownMsg, modKeyState);
nativeKey.HandleKeyDownMessage();
} else {
NativeKey::FakeCharMsg fakeMsgForKeyDown = { chars.CharAt(0), scanCode,
makeDeadCharMsg };
NativeKey nativeKey(aWidget, keyDownMsg, modKeyState,
&fakeMsgForKeyDown);
bool dispatched, keyDownDefaultPrevented;
nativeKey.HandleKeyDownMessage(&dispatched, &keyDownDefaultPrevented);
if (!keyDownDefaultPrevented) {
for (uint32_t j = 1; j < chars.Length(); j++) {
NativeKey::FakeCharMsg fakeMsgForChar = { chars.CharAt(j), scanCode,
false };
MSG charMsg = fakeMsgForChar.GetCharMsg(aWidget->GetWindowHandle());
NativeKey nativeKey(aWidget, charMsg, modKeyState);
nativeKey.HandleCharMessage(charMsg);
nsAutoTArray<NativeKey::FakeCharMsg, 10> fakeCharMsgs;
for (uint32_t j = 0; j < chars.Length(); j++) {
NativeKey::FakeCharMsg* fakeCharMsg = fakeCharMsgs.AppendElement();
fakeCharMsg->mCharCode = chars.CharAt(j);
fakeCharMsg->mScanCode = scanCode;
fakeCharMsg->mIsDeadKey = makeDeadCharMsg;
}
NativeKey nativeKey(aWidget, keyDownMsg, modKeyState, &fakeCharMsgs);
bool dispatched;
nativeKey.HandleKeyDownMessage(&dispatched);
// If some char messages are not consumed, let's emulate the widget
// receiving the message directly.
for (uint32_t j = 1; j < fakeCharMsgs.Length(); j++) {
if (fakeCharMsgs[j].mConsumed) {
continue;
}
MSG charMsg = fakeCharMsgs[j].GetCharMsg(aWidget->GetWindowHandle());
NativeKey nativeKey(aWidget, charMsg, modKeyState);
nativeKey.HandleCharMessage(charMsg);
}
}
} else {

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

@ -297,6 +297,12 @@ public:
UINT mCharCode;
UINT mScanCode;
bool mIsDeadKey;
bool mConsumed;
FakeCharMsg() :
mCharCode(0), mScanCode(0), mIsDeadKey(false), mConsumed(false)
{
}
MSG GetCharMsg(HWND aWnd) const
{
@ -314,7 +320,7 @@ public:
NativeKey(nsWindowBase* aWidget,
const MSG& aKeyOrCharMessage,
const ModifierKeyState& aModKeyState,
const FakeCharMsg* aFakeCharMsg = nullptr);
nsTArray<FakeCharMsg>* aFakeCharMsgs = nullptr);
/**
* Handle WM_KEYDOWN message or WM_SYSKEYDOWN message. The instance must be
@ -322,8 +328,7 @@ public:
* Returns true if dispatched keydown event or keypress event is consumed.
* Otherwise, false.
*/
bool HandleKeyDownMessage(bool* aEventDispatched = nullptr,
bool* aWasKeyDownDefaultPrevented = nullptr) const;
bool HandleKeyDownMessage(bool* aEventDispatched = nullptr) const;
/**
* Handles WM_CHAR message or WM_SYSCHAR message. The instance must be
@ -373,7 +378,8 @@ private:
// Please note that the event may not cause any text input even if this
// is true. E.g., it might be dead key state or Ctrl key may be pressed.
bool mIsPrintableKey;
bool mIsFakeCharMsg;
nsTArray<FakeCharMsg>* mFakeCharMsgs;
NativeKey()
{