Bug 1300003 part.5 Remove odd WM_CHAR messages which are caused by ATOK or WXG (both of them are Japanese IME) r=m_kato

NativeKey removes odd WM_CHAR messages which are caused by ATOK or WXG if the user tries to do "Kakutei-Undo" (meaning "undo the last commit") after dispatching eKeyDown event.

However, NativeKey should remove them from the queue first because there are some problems:

* If focus is moved during dispatching an eKeyDown event, we'll fail to remove the messages from the queue.
* If dispatching eKeyDown advance native event loop due to entering to a modal loop or dosing synchronous XHR, the message pattern is broken before removing the odd messages from the queue.

After removing the odd char messages, NativeKey should store them with mRemovedOddCharMsgs because NativeKey needs to dispatch them to focused windowless plugin.

Note that this patch also fixes a bug of the loop to remove the odd WM_CHAR messages.  Old code removes only one WM_CHAR messages, but we need to remove all WM_CHAR messages before WM_KEYUP.  This must be a regression.

MozReview-Commit-ID: I60bcIx2SFS

--HG--
extra : rebase_source : 19d0e70d9f39e6d0476c62def5e0a2dc1e0ab444
This commit is contained in:
Masayuki Nakano 2016-09-14 16:20:53 +09:00
Родитель c0ad8a8fb2
Коммит 050c1b4088
2 изменённых файлов: 61 добавлений и 18 удалений

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

@ -1112,6 +1112,8 @@ NativeKey::NativeKey(nsWindowBase* aWidget,
mCommittedCharsAndModifiers.Append(ch, mModKeyState.GetModifiers());
}
}
// Remove odd char messages if there are.
RemoveFollowingOddCharMessages();
}
}
@ -1281,6 +1283,47 @@ NativeKey::IsIMEDoingKakuteiUndo() const
compositionMsg.time <= charMsg.time;
}
void
NativeKey::RemoveFollowingOddCharMessages()
{
MOZ_ASSERT(IsKeyDownMessage());
// If the keydown message is synthesized for automated tests, there is
// nothing to do here.
if (mFakeCharMsgs) {
return;
}
// If there are some following char messages before another key message,
// there is nothing to do here.
if (!mFollowingCharMsgs.IsEmpty()) {
return;
}
// If the handling key isn't Backspace, there is nothing to do here.
if (mOriginalVirtualKeyCode != VK_BACK) {
return;
}
// If we don't see the odd message pattern, there is nothing to do here.
if (!IsIMEDoingKakuteiUndo()) {
return;
}
// Otherwise, we need to remove odd WM_CHAR messages for ATOK or WXG (both
// of them are Japanese IME).
MSG msg;
while (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_CHAR, WM_CHAR,
PM_REMOVE | PM_NOYIELD)) {
if (msg.message != WM_CHAR) {
MOZ_RELEASE_ASSERT(msg.message == WM_NULL,
"Unexpected message was removed");
continue;
}
mRemovedOddCharMsgs.AppendElement(msg);
}
}
UINT
NativeKey::GetScanCodeWithExtendedFlag() const
{
@ -2350,9 +2393,7 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
MOZ_ASSERT(IsKeyDownMessage());
MOZ_ASSERT(!IsKeyMessageOnPlugin());
bool anyCharMessagesRemoved = false;
for (size_t i = 0; i < mFollowingCharMsgs.Length(); ++i) {
anyCharMessagesRemoved = true;
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(mFollowingCharMsgs[i]);
@ -2361,23 +2402,15 @@ NativeKey::DispatchPluginEventsAndDiscardsCharMessages() const
}
}
if (!mFakeCharMsgs && !anyCharMessagesRemoved &&
mDOMKeyCode == NS_VK_BACK && IsIMEDoingKakuteiUndo()) {
// This is for a hack for ATOK and WXG. So, PeekMessage() must scceed!
MSG msg;
while (WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_CHAR, WM_CHAR,
PM_REMOVE | PM_NOYIELD)) {
if (msg.message != WM_CHAR) {
MOZ_RELEASE_ASSERT(msg.message == WM_NULL,
"Unexpected message was removed");
continue;
}
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(msg);
return mWidget->Destroyed();
// Dispatch odd char messages which are caused by ATOK or WXG (both of them
// are Japanese IME) and removed by RemoveFollowingOddCharMessages().
for (size_t i = 0; i < mRemovedOddCharMsgs.Length(); ++i) {
MOZ_RELEASE_ASSERT(!mWidget->Destroyed(),
"NativeKey tries to dispatch a plugin event on destroyed widget");
mWidget->DispatchPluginEvent(mRemovedOddCharMsgs[i]);
if (mWidget->Destroyed() || IsFocusedWindowChanged()) {
return true;
}
MOZ_CRASH("NativeKey failed to get WM_CHAR for ATOK or WXG");
}
return false;

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

@ -267,6 +267,10 @@ private:
// WM_SYSDEADCHAR message which follows WM_KEYDOWN.
// Note that the stored messaged are already removed from the queue.
nsTArray<MSG> mFollowingCharMsgs;
// mRemovedOddCharMsgs stores WM_CHAR messages which are caused by ATOK or
// WXG (they are Japanese IME) when the user tries to do "Kakutei-undo"
// (it means "undo the last commit").
nsTArray<MSG> mRemovedOddCharMsgs;
// If dispatching eKeyDown or eKeyPress event causes focus change,
// the instance shouldn't handle remaning char messages. For checking it,
// this should store first focused window.
@ -376,6 +380,12 @@ private:
// The result is one of nsIDOMKeyEvent::DOM_KEY_LOCATION_*.
uint32_t GetKeyLocation() const;
/**
* RemoveFollowingOddCharMessages() removes odd WM_CHAR messages from the
* queue when IsIMEDoingKakuteiUndo() returns true.
*/
void RemoveFollowingOddCharMessages();
/**
* "Kakutei-Undo" of ATOK or WXG (both of them are Japanese IME) causes
* strange WM_KEYDOWN/WM_KEYUP/WM_CHAR message pattern. So, when this