Bug 466487 ATOK (Japanese IME) fails to eat key message r=jimm

This commit is contained in:
Masayuki Nakano 2010-06-02 11:14:11 +09:00
parent 808f77ab65
commit cd4afec48b
3 changed files with 94 additions and 8 deletions

View File

@ -42,6 +42,7 @@
#include "nsThreadUtils.h"
#include "WinTaskbar.h"
#include "nsString.h"
#include "nsIMM32Handler.h"
// For skidmark code
#include <windows.h>
@ -81,7 +82,7 @@ static BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd)
MSG msg1, msg2, *lpMsg;
BOOL b1, b2;
b1 = ::PeekMessageW(&msg1, NULL, WM_KEYFIRST, WM_IME_KEYLAST, PM_NOREMOVE);
b2 = ::PeekMessageW(&msg2, NULL, WM_IME_SETCONTEXT, WM_IME_KEYUP, PM_NOREMOVE);
b2 = ::PeekMessageW(&msg2, NULL, NS_WM_IMEFIRST, NS_WM_IMELAST, PM_NOREMOVE);
if (b1 || b2) {
if (b1 && b2) {
if (msg1.time < msg2.time)
@ -92,6 +93,9 @@ static BOOL PeekKeyAndIMEMessage(LPMSG msg, HWND hwnd)
lpMsg = &msg1;
else
lpMsg = &msg2;
if (!nsIMM32Handler::CanOptimizeKeyAndIMEMessages(lpMsg)) {
return false;
}
return ::PeekMessageW(msg, hwnd, lpMsg->message, lpMsg->message, PM_REMOVE);
}

View File

@ -90,6 +90,8 @@ static UINT sWM_MSIME_MOUSE = 0; // mouse message for MSIME 98/2000
PRPackedBool nsIMM32Handler::sIsComposingOnPlugin = PR_FALSE;
PRPackedBool nsIMM32Handler::sIsStatusChanged = PR_FALSE;
PRPackedBool nsIMM32Handler::sIsIME = PR_TRUE;
PRPackedBool nsIMM32Handler::sIsIMEOpening = PR_FALSE;
#ifndef WINCE
UINT nsIMM32Handler::sCodePage = 0;
@ -196,9 +198,10 @@ nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
(PWSTR)&sCodePage, sizeof(sCodePage) / sizeof(WCHAR));
sIMEProperty = ::ImmGetProperty(aKeyboardLayout, IGP_PROPERTY);
sIsIME = ::ImmIsIME(aKeyboardLayout);
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: InitKeyboardLayout, aKeyboardLayout=%08x, sCodePage=%lu, sIMEProperty=%08x\n",
aKeyboardLayout, sCodePage, sIMEProperty));
("IMM32: InitKeyboardLayout, aKeyboardLayout=%08x, sCodePage=%lu, sIMEProperty=%08x sIsIME=%s\n",
aKeyboardLayout, sCodePage, sIMEProperty, sIsIME ? "TRUE" : "FALSE"));
#endif
}
@ -212,6 +215,21 @@ nsIMM32Handler::GetKeyboardCodePage()
#endif
}
/* static */ PRBool
nsIMM32Handler::CanOptimizeKeyAndIMEMessages(MSG *aNextKeyOrIMEMessage)
{
#ifdef WINCE
return PR_TRUE;
#else
// If IME is opening right now, we shouldn't optimize the key and IME message
// order because ATOK (Japanese IME of third party) has some problem with the
// optimization. When it finishes opening completely, it eats all key
// messages in the message queue. And it causes starting composition. So,
// we shouldn't eat the key messages before ATOK.
return !sIsIMEOpening;
#endif
}
// used for checking the lParam of WM_IME_COMPOSITION
#define IS_COMPOSING_LPARAM(lParam) \
@ -273,6 +291,21 @@ nsIMM32Handler::ProcessMessage(nsWindow* aWindow, UINT msg,
// if the new window handle is not focused, probably, we should not start
// the composition, however, such case should not be, it's just bad scenario.
if (sIsIMEOpening) {
switch (msg) {
case WM_INPUTLANGCHANGE:
case WM_IME_STARTCOMPOSITION:
case WM_IME_COMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_CHAR:
case WM_IME_SELECT:
case WM_IME_SETCONTEXT:
// For safety, we should reset sIsIMEOpening when we receive unexpected
// message.
sIsIMEOpening = PR_FALSE;
}
}
if (aWindow->PluginHasFocus()) {
return ProcessMessageForPlugin(aWindow, msg, wParam, lParam, aRetValue,
aEatMessage);
@ -337,6 +370,8 @@ nsIMM32Handler::ProcessMessage(nsWindow* aWindow, UINT msg,
case WM_IME_SETCONTEXT:
aEatMessage = OnIMESetContext(aWindow, wParam, lParam);
return PR_TRUE;
case WM_KEYDOWN:
return OnKeyDownEvent(aWindow, wParam, lParam, aEatMessage);
default:
return PR_FALSE;
};
@ -365,6 +400,20 @@ nsIMM32Handler::ProcessMessageForPlugin(nsWindow* aWindow, UINT msg,
case WM_IME_ENDCOMPOSITION:
sIsComposingOnPlugin = PR_FALSE;
return PR_FALSE;
case WM_IME_NOTIFY:
if (wParam == IMN_SETOPENSTATUS) {
// finished being opening
sIsIMEOpening = PR_FALSE;
}
return PR_FALSE;
case WM_KEYDOWN:
if (wParam == VK_PROCESSKEY) {
// If we receive when IME isn't open, it means IME is opening right now.
nsIMEContext IMEContext(aWindow->GetWindowHandle());
sIsIMEOpening = IMEContext.IsValid() &&
::ImmGetOpenStatus(IMEContext.get());
}
return PR_FALSE;
}
return PR_FALSE;
}
@ -543,6 +592,7 @@ nsIMM32Handler::OnIMENotify(nsWindow* aWindow,
aWindow->GetWindowHandle()));
break;
case IMN_SETOPENSTATUS:
sIsIMEOpening = PR_FALSE;
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: OnIMENotify, hWnd=%08x, IMN_SETOPENSTATUS\n",
aWindow->GetWindowHandle()));
@ -1675,3 +1725,25 @@ nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction)
}
#endif // ENABLE_IME_MOUSE_HANDLING
/* static */ PRBool
nsIMM32Handler::OnKeyDownEvent(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
PRBool &aEatMessage)
{
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: OnKeyDownEvent, hWnd=%08x, wParam=%08x, lParam=%08x\n",
aWindow->GetWindowHandle(), wParam, lParam));
aEatMessage = PR_FALSE;
switch (wParam) {
case VK_PROCESSKEY:
// If we receive when IME isn't open, it means IME is opening right now.
if (sIsIME) {
nsIMEContext IMEContext(aWindow->GetWindowHandle());
sIsIMEOpening =
IMEContext.IsValid() && !::ImmGetOpenStatus(IMEContext.get());
}
return PR_FALSE;
default:
return PR_FALSE;
}
}

View File

@ -61,6 +61,9 @@ struct nsIntRect;
#define ENABLE_IME_MOUSE_HANDLING 1
#endif // WINCE
#define NS_WM_IMEFIRST WM_IME_SETCONTEXT
#define NS_WM_IMELAST WM_IME_KEYUP
class nsIMEContext
{
public:
@ -123,6 +126,8 @@ public:
static void NotifyEndStatusChange() { sIsStatusChanged = PR_FALSE; }
static PRBool CanOptimizeKeyAndIMEMessages(MSG *aNextKeyOrIMEMessage);
protected:
static void EnsureHandlerInstance();
@ -138,6 +143,14 @@ protected:
nsIMM32Handler();
~nsIMM32Handler();
// The result of following On*Event methods means "The message was processed,
// don't process the message in the caller (nsWindow)".
#ifdef ENABLE_IME_MOUSE_HANDLING
PRBool OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction);
#endif // ENABLE_IME_MOUSE_HANDLING
static PRBool OnKeyDownEvent(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
PRBool &aEatMessage);
// The result of On* methods mean "eat this message" when it's TRUE.
PRBool OnIMEStartComposition(nsWindow* aWindow);
PRBool OnIMEComposition(nsWindow* aWindow, WPARAM wParam, LPARAM lParam);
@ -229,16 +242,13 @@ protected:
static PRPackedBool sIsComposingOnPlugin;
static PRPackedBool sIsStatusChanged;
static PRPackedBool sIsIME;
static PRPackedBool sIsIMEOpening;
#ifndef WINCE
static UINT sCodePage;
static DWORD sIMEProperty;
#endif // #ifndef WINCE
#ifdef ENABLE_IME_MOUSE_HANDLING
PRBool OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction);
#endif // ENABLE_IME_MOUSE_HANDLING
};
#endif // nsIMM32Handler_h__