Bug 807241 Use ITfMessagePump and ITfKeystrokeMgr r=jimm

This commit is contained in:
Masayuki Nakano 2013-03-18 13:41:24 +09:00
Родитель 59579d6d63
Коммит 8818d46337
11 изменённых файлов: 185 добавлений и 34 удалений

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

@ -11,6 +11,7 @@
#endif // #ifdef NS_ENABLE_TSF
#include "nsWindow.h"
#include "WinUtils.h"
namespace mozilla {
namespace widget {
@ -98,6 +99,18 @@ IMEHandler::IsIMEEnabled(IMEState::Enabled aIMEState)
aIMEState == mozilla::widget::IMEState::PLUGIN);
}
// static
bool
IMEHandler::ProcessRawKeyMessage(const MSG& aMsg)
{
#ifdef NS_ENABLE_TSF
if (IsTSFAvailable()) {
return nsTextStore::ProcessRawKeyMessage(aMsg);
}
#endif // #ifdef NS_ENABLE_TSF
return false; // noting to do in IMM mode.
}
// static
bool
IMEHandler::ProcessMessage(nsWindow* aWindow, UINT aMessage,
@ -369,13 +382,13 @@ IMEHandler::IsDoingKakuteiUndo(HWND aWnd)
// https://bugzilla.mozilla.gr.jp/show_bug.cgi?id=2885 (written in Japanese)
// https://bugzilla.mozilla.org/show_bug.cgi?id=194559 (written in English)
MSG startCompositionMsg, compositionMsg, charMsg;
return ::PeekMessageW(&startCompositionMsg, aWnd,
WM_IME_STARTCOMPOSITION, WM_IME_STARTCOMPOSITION,
PM_NOREMOVE | PM_NOYIELD) &&
::PeekMessageW(&compositionMsg, aWnd, WM_IME_COMPOSITION,
WM_IME_COMPOSITION, PM_NOREMOVE | PM_NOYIELD) &&
::PeekMessageW(&charMsg, aWnd, WM_CHAR, WM_CHAR,
PM_NOREMOVE | PM_NOYIELD) &&
return WinUtils::PeekMessage(&startCompositionMsg, aWnd,
WM_IME_STARTCOMPOSITION, WM_IME_STARTCOMPOSITION,
PM_NOREMOVE | PM_NOYIELD) &&
WinUtils::PeekMessage(&compositionMsg, aWnd, WM_IME_COMPOSITION,
WM_IME_COMPOSITION, PM_NOREMOVE | PM_NOYIELD) &&
WinUtils::PeekMessage(&charMsg, aWnd, WM_CHAR, WM_CHAR,
PM_NOREMOVE | PM_NOYIELD) &&
startCompositionMsg.wParam == 0x0 &&
startCompositionMsg.lParam == 0x0 &&
compositionMsg.wParam == 0x0 &&

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

@ -48,6 +48,13 @@ public:
static bool IsIMEEnabled(const InputContext& aInputContext);
static bool IsIMEEnabled(IMEState::Enabled aIMEState);
/**
* ProcessRawKeyMessage() message is called before calling TranslateMessage()
* and DispatchMessage(). If this returns true, the message is consumed.
* Then, caller must not perform TranslateMessage() nor DispatchMessage().
*/
static bool ProcessRawKeyMessage(const MSG& aMsg);
/**
* When the message is not needed to handle anymore by the caller, this
* returns true. Otherwise, false.

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

@ -27,6 +27,11 @@
#include "nsIObserver.h"
#include "imgIEncoder.h"
#ifdef NS_ENABLE_TSF
#include <textstor.h>
#include "nsTextStore.h"
#endif // #ifdef NS_ENABLE_TSF
namespace mozilla {
namespace widget {
@ -68,6 +73,42 @@ WinUtils::GetWindowsVersion()
return static_cast<WinVersion>(version);
}
/* static */
bool
WinUtils::PeekMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
UINT aLastMessage, UINT aOption)
{
#ifdef NS_ENABLE_TSF
ITfMessagePump* msgPump = nsTextStore::GetMessagePump();
if (msgPump) {
BOOL ret = FALSE;
HRESULT hr = msgPump->PeekMessageW(aMsg, aWnd, aFirstMessage, aLastMessage,
aOption, &ret);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
return ret;
}
#endif // #ifdef NS_ENABLE_TSF
return ::PeekMessageW(aMsg, aWnd, aFirstMessage, aLastMessage, aOption);
}
/* static */
bool
WinUtils::GetMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
UINT aLastMessage)
{
#ifdef NS_ENABLE_TSF
ITfMessagePump* msgPump = nsTextStore::GetMessagePump();
if (msgPump) {
BOOL ret = FALSE;
HRESULT hr = msgPump->GetMessageW(aMsg, aWnd, aFirstMessage, aLastMessage,
&ret);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
return ret;
}
#endif // #ifdef NS_ENABLE_TSF
return ::GetMessageW(aMsg, aWnd, aFirstMessage, aLastMessage);
}
/* static */
bool
WinUtils::GetRegistryKey(HKEY aRoot,

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

@ -49,6 +49,16 @@ public:
};
static WinVersion GetWindowsVersion();
/**
* PeekMessage() and GetMessage() are wrapper methods for PeekMessageW(),
* GetMessageW(), ITfMessageMgr::PeekMessageW() and
* ITfMessageMgr::GetMessageW().
* Don't call the native APIs directly. You MUST use these methods instead.
*/
static bool PeekMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
UINT aLastMessage, UINT aOption);
static bool GetMessage(LPMSG aMsg, HWND aWnd, UINT aFirstMessage,
UINT aLastMessage);
/**
* Gets the value of a string-typed registry value.
*

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

@ -7,6 +7,7 @@
#include "nsAppShell.h"
#include "nsToolkit.h"
#include "nsThreadUtils.h"
#include "WinUtils.h"
#include "WinTaskbar.h"
#include "WinMouseScrollHandler.h"
#include "nsWindowDefs.h"
@ -15,6 +16,8 @@
#include "mozilla/widget/AudioSession.h"
#include "mozilla/HangMonitor.h"
using namespace mozilla::widget;
const PRUnichar* kAppShellEventId = L"nsAppShell:EventID";
const PRUnichar* kTaskbarButtonEventId = L"TaskbarButtonCreated";
@ -47,17 +50,20 @@ static bool PeekUIMessage(MSG* aMsg)
// it may make different modifier key state or mouse cursor position between
// them.
if (mozilla::widget::MouseScrollHandler::IsWaitingInternalMessage() &&
::PeekMessageW(aMsg, NULL, MOZ_WM_MOUSEWHEEL_FIRST,
MOZ_WM_MOUSEWHEEL_LAST, PM_REMOVE)) {
WinUtils::PeekMessage(aMsg, NULL, MOZ_WM_MOUSEWHEEL_FIRST,
MOZ_WM_MOUSEWHEEL_LAST, PM_REMOVE)) {
return true;
}
MSG keyMsg, imeMsg, mouseMsg, *pMsg = 0;
bool haveKeyMsg, haveIMEMsg, haveMouseMsg;
haveKeyMsg = ::PeekMessageW(&keyMsg, NULL, WM_KEYFIRST, WM_IME_KEYLAST, PM_NOREMOVE);
haveIMEMsg = ::PeekMessageW(&imeMsg, NULL, NS_WM_IMEFIRST, NS_WM_IMELAST, PM_NOREMOVE);
haveMouseMsg = ::PeekMessageW(&mouseMsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE);
haveKeyMsg = WinUtils::PeekMessage(&keyMsg, NULL, WM_KEYFIRST,
WM_IME_KEYLAST, PM_NOREMOVE);
haveIMEMsg = WinUtils::PeekMessage(&imeMsg, NULL, NS_WM_IMEFIRST,
NS_WM_IMELAST, PM_NOREMOVE);
haveMouseMsg = WinUtils::PeekMessage(&mouseMsg, NULL, WM_MOUSEFIRST,
WM_MOUSELAST, PM_NOREMOVE);
if (haveKeyMsg) {
pMsg = &keyMsg;
@ -78,7 +84,8 @@ static bool PeekUIMessage(MSG* aMsg)
return false;
}
return ::PeekMessageW(aMsg, NULL, pMsg->message, pMsg->message, PM_REMOVE);
return WinUtils::PeekMessage(aMsg, NULL, pMsg->message,
pMsg->message, PM_REMOVE);
}
/*static*/ LRESULT CALLBACK
@ -223,7 +230,7 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
// Give priority to keyboard and mouse messages.
if (uiMessage ||
PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
gotMessage = true;
if (msg.message == WM_QUIT) {
::PostQuitMessage(msg.wParam);
@ -234,6 +241,12 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
mozilla::HangMonitor::NotifyActivity(
uiMessage ? mozilla::HangMonitor::kUIActivity :
mozilla::HangMonitor::kActivityNoUIAVail);
if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST &&
IMEHandler::ProcessRawKeyMessage(msg)) {
continue; // the message is consumed.
}
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}

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

@ -526,9 +526,9 @@ nsIMM32Handler::OnIMEEndComposition(nsWindow* aWindow)
// composition. Then, we should ignore the message and commit the composition
// string at following WM_IME_COMPOSITION.
MSG compositionMsg;
if (::PeekMessageW(&compositionMsg, aWindow->GetWindowHandle(),
WM_IME_STARTCOMPOSITION, WM_IME_COMPOSITION,
PM_NOREMOVE) &&
if (WinUtils::PeekMessage(&compositionMsg, aWindow->GetWindowHandle(),
WM_IME_STARTCOMPOSITION, WM_IME_COMPOSITION,
PM_NOREMOVE) &&
compositionMsg.message == WM_IME_COMPOSITION &&
IS_COMMITTING_LPARAM(compositionMsg.lParam)) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
@ -1012,11 +1012,11 @@ nsIMM32Handler::HandleComposition(nsWindow* aWindow,
if (!mIsComposing) {
MSG msg1, msg2;
HWND wnd = aWindow->GetWindowHandle();
if (::PeekMessageW(&msg1, wnd, WM_IME_STARTCOMPOSITION, WM_IME_COMPOSITION,
PM_NOREMOVE) &&
if (WinUtils::PeekMessage(&msg1, wnd, WM_IME_STARTCOMPOSITION,
WM_IME_COMPOSITION, PM_NOREMOVE) &&
msg1.message == WM_IME_STARTCOMPOSITION &&
::PeekMessageW(&msg2, wnd, WM_IME_ENDCOMPOSITION, WM_IME_COMPOSITION,
PM_NOREMOVE) &&
WinUtils::PeekMessage(&msg2, wnd, WM_IME_ENDCOMPOSITION,
WM_IME_COMPOSITION, PM_NOREMOVE) &&
msg2.message == WM_IME_COMPOSITION) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: HandleComposition, Ignores due to find a WM_IME_STARTCOMPOSITION\n"));

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

@ -132,6 +132,8 @@ private:
/******************************************************************/
ITfThreadMgr* nsTextStore::sTsfThreadMgr = NULL;
ITfMessagePump* nsTextStore::sMessagePump = NULL;
ITfKeystrokeMgr* nsTextStore::sKeystrokeMgr = NULL;
ITfDisplayAttributeMgr* nsTextStore::sDisplayAttrMgr = NULL;
ITfCategoryMgr* nsTextStore::sCategoryMgr = NULL;
DWORD nsTextStore::sTsfClientId = 0;
@ -579,9 +581,9 @@ nsTextStore::Destroy(void)
// But by that time the text store is already destroyed,
// so try to get the message early
MSG msg;
if (::PeekMessageW(&msg, mWidget->GetWindowHandle(),
sFlushTIPInputMessage, sFlushTIPInputMessage,
PM_REMOVE)) {
if (WinUtils::PeekMessage(&msg, mWidget->GetWindowHandle(),
sFlushTIPInputMessage, sFlushTIPInputMessage,
PM_REMOVE)) {
::DispatchMessageW(&msg);
}
}
@ -3156,6 +3158,16 @@ nsTextStore::Initialize(void)
if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, NULL,
CLSCTX_INPROC_SERVER, IID_ITfThreadMgr,
reinterpret_cast<void**>(&sTsfThreadMgr)))) {
DebugOnly<HRESULT> hr =
sTsfThreadMgr->QueryInterface(IID_ITfMessagePump,
reinterpret_cast<void**>(&sMessagePump));
MOZ_ASSERT(SUCCEEDED(hr));
MOZ_ASSERT(sMessagePump);
hr =
sTsfThreadMgr->QueryInterface(IID_ITfKeystrokeMgr,
reinterpret_cast<void**>(&sKeystrokeMgr));
MOZ_ASSERT(SUCCEEDED(hr));
MOZ_ASSERT(sKeystrokeMgr);
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::Initialize() succeeded to "
"create the thread manager, activating..."));
@ -3216,6 +3228,11 @@ nsTextStore::Initialize(void)
NS_LITERAL_STRING("Flush TIP Input Message").get());
}
if (!sTsfThreadMgr) {
NS_IF_RELEASE(sMessagePump);
NS_IF_RELEASE(sKeystrokeMgr);
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::Initialize(), sTsfThreadMgr=0x%p, "
"sTsfClientId=0x%08X, sTsfTextStore=0x%p, sDisplayAttrMgr=0x%p, "
@ -3237,9 +3254,40 @@ nsTextStore::Terminate(void)
if (sTsfThreadMgr) {
sTsfThreadMgr->Deactivate();
NS_RELEASE(sTsfThreadMgr);
NS_RELEASE(sMessagePump);
NS_RELEASE(sKeystrokeMgr);
}
}
// static
bool
nsTextStore::ProcessRawKeyMessage(const MSG& aMsg)
{
if (!sKeystrokeMgr) {
return false; // not in TSF mode
}
if (aMsg.message == WM_KEYDOWN) {
BOOL eaten;
HRESULT hr = sKeystrokeMgr->TestKeyDown(aMsg.wParam, aMsg.lParam, &eaten);
if (FAILED(hr) || !eaten) {
return false;
}
hr = sKeystrokeMgr->KeyDown(aMsg.wParam, aMsg.lParam, &eaten);
return SUCCEEDED(hr) && eaten;
}
if (aMsg.message == WM_KEYUP) {
BOOL eaten;
HRESULT hr = sKeystrokeMgr->TestKeyUp(aMsg.wParam, aMsg.lParam, &eaten);
if (FAILED(hr) || !eaten) {
return false;
}
hr = sKeystrokeMgr->KeyUp(aMsg.wParam, aMsg.lParam, &eaten);
return SUCCEEDED(hr) && eaten;
}
return false;
}
/******************************************************************/
/* nsTextStore::Composition */
/******************************************************************/

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

@ -96,6 +96,9 @@ protected:
public:
static void Initialize(void);
static void Terminate(void);
static bool ProcessRawKeyMessage(const MSG& aMsg);
static void SetIMEOpenState(bool);
static bool GetIMEOpenState(void);
@ -162,6 +165,11 @@ public:
}
}
static ITfMessagePump* GetMessagePump()
{
return sMessagePump;
}
static void* GetTextStore()
{
return static_cast<void*>(sTsfTextStore);
@ -630,6 +638,10 @@ protected:
// TSF thread manager object for the current application
static ITfThreadMgr* sTsfThreadMgr;
// sMessagePump is QI'ed from sTsfThreadMgr
static ITfMessagePump* sMessagePump;
// sKeystrokeMgr is QI'ed from sTsfThreadMgr
static ITfKeystrokeMgr* sKeystrokeMgr;
// TSF display attribute manager
static ITfDisplayAttributeMgr* sDisplayAttrMgr;
// TSF category manager

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

@ -3806,7 +3806,7 @@ void nsWindow::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
}
msg = aFakeCharMessage->GetCharMessage(mWnd);
} else {
::GetMessageW(&msg, mWnd, aFirstMsg, aLastMsg);
WinUtils::GetMessage(&msg, mWnd, aFirstMsg, aLastMsg);
}
DispatchPluginEvent(msg);
}
@ -5639,10 +5639,10 @@ void nsWindow::PostSleepWakeNotification(const bool aIsSleepMode)
void nsWindow::RemoveNextCharMessage(HWND aWnd)
{
MSG msg;
if (::PeekMessageW(&msg, aWnd,
WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD) &&
if (WinUtils::PeekMessage(&msg, aWnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD) &&
(msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) {
::GetMessageW(&msg, aWnd, msg.message, msg.message);
WinUtils::GetMessage(&msg, aWnd, msg.message, msg.message);
}
}
@ -6564,7 +6564,8 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
extraFlags.mDefaultPrevented = noDefault;
MSG msg;
BOOL gotMsg = aFakeCharMessage ||
::PeekMessageW(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
WinUtils::PeekMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD);
// Enter and backspace are always handled here to avoid for example the
// confusion between ctrl-enter and ctrl-J.
if (DOMKeyCode == NS_VK_RETURN || DOMKeyCode == NS_VK_BACK ||
@ -6591,7 +6592,8 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
anyCharMessagesRemoved = true;
gotMsg = ::PeekMessageW (&msg, mWnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
gotMsg = WinUtils::PeekMessage(&msg, mWnd, WM_KEYFIRST, WM_KEYLAST,
PM_NOREMOVE | PM_NOYIELD);
}
}
@ -6633,7 +6635,7 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg,
}
// If prevent default set for keydown, do same for keypress
::GetMessageW(&msg, mWnd, msg.message, msg.message);
WinUtils::GetMessage(&msg, mWnd, msg.message, msg.message);
if (msg.message == WM_DEADCHAR) {
if (!PluginHasFocus())

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

@ -10,7 +10,9 @@
#include "MetroApp.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "WinUtils.h"
using namespace mozilla::widget;
using namespace mozilla::widget::winrt;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@ -140,14 +142,14 @@ MetroAppShell::ProcessNextNativeEvent(bool mayWait)
MSG msg;
if (mayWait) {
if (!PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (!WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
WaitMessage();
}
ProcessOneNativeEventIfPresent();
return true;
}
if (PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
ProcessOneNativeEventIfPresent();
return true;
}

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

@ -119,7 +119,10 @@ namespace {
// processed.
Log(L" Inputs sent. Waiting for input messages to clear");
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
while (WinUtils::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (nsTextStore::ProcessRawKeyMessage(msg)) {
continue; // the message is consumed by TSF
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
Log(L" Dispatched 0x%x 0x%x 0x%x", msg.message, msg.wParam, msg.lParam);