Bug 1059643 nsIMM32Handler should handle NOTIFY_IME_OF_MOUSE_BUTTON_EVENT r=emk

This commit is contained in:
Masayuki Nakano 2014-09-11 12:41:15 +09:00
parent 1f4842da80
commit d47b903e09
3 changed files with 68 additions and 45 deletions

View File

@ -204,6 +204,8 @@ IMEHandler::NotifyIME(nsWindow* aWindow,
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
nsIMM32Handler::OnUpdateComposition(aWindow);
return NS_OK;
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
return nsIMM32Handler::OnMouseButtonEvent(aWindow, aIMENotification);
#ifdef NS_ENABLE_TSF
case NOTIFY_IME_OF_BLUR:
// If a plugin gets focus while TSF has focus, we need to notify TSF of

View File

@ -142,7 +142,9 @@ nsIMM32Handler::GetKeyboardCodePage()
nsIMEUpdatePreference
nsIMM32Handler::GetIMEUpdatePreference()
{
return nsIMEUpdatePreference(nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE);
return nsIMEUpdatePreference(
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE |
nsIMEUpdatePreference::NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR);
}
// used for checking the lParam of WM_IME_COMPOSITION
@ -303,18 +305,6 @@ nsIMM32Handler::ProcessMessage(nsWindow* aWindow, UINT msg,
aResult.mResult = 0;
switch (msg) {
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN: {
// We don't need to create the instance of the handler here.
if (!gIMM32Handler) {
return false;
}
return gIMM32Handler->OnMouseEvent(aWindow, lParam,
msg == WM_LBUTTONDOWN ? IMEMOUSE_LDOWN :
msg == WM_MBUTTONDOWN ? IMEMOUSE_MDOWN :
IMEMOUSE_RDOWN, aResult);
}
case WM_INPUTLANGCHANGE:
return ProcessInputLangChangeMessage(aWindow, wParam, lParam, aResult);
case WM_IME_STARTCOMPOSITION:
@ -2045,37 +2035,60 @@ nsIMM32Handler::ResolveIMECaretPos(nsIWidget* aReferenceWidget,
aOutRect.MoveBy(-aNewOriginWidget->WidgetToScreenOffset());
}
bool
nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction,
MSGResult& aResult)
/* static */ nsresult
nsIMM32Handler::OnMouseButtonEvent(nsWindow* aWindow,
const IMENotification& aIMENotification)
{
aResult.mConsumed = false; // always call next wndprc
if (!sWM_MSIME_MOUSE || !mIsComposing ||
!ShouldDrawCompositionStringOurselves()) {
return false;
// We don't need to create the instance of the handler here.
if (!gIMM32Handler) {
return NS_OK;
}
nsIntPoint cursor(LOWORD(lParam), HIWORD(lParam));
WidgetQueryContentEvent charAtPt(true, NS_QUERY_CHARACTER_AT_POINT, aWindow);
aWindow->InitEvent(charAtPt, &cursor);
aWindow->DispatchWindowEvent(&charAtPt);
if (!charAtPt.mSucceeded ||
charAtPt.mReply.mOffset == WidgetQueryContentEvent::NOT_FOUND ||
charAtPt.mReply.mOffset < mCompositionStart ||
charAtPt.mReply.mOffset >
mCompositionStart + mCompositionString.Length()) {
return false;
if (!sWM_MSIME_MOUSE || !IsComposingOnOurEditor() ||
!ShouldDrawCompositionStringOurselves()) {
return NS_OK;
}
// We need to handle only mousedown event.
if (aIMENotification.mMouseButtonEventData.mEventMessage !=
NS_MOUSE_BUTTON_DOWN) {
return NS_OK;
}
// If the character under the cursor is not in the composition string,
// we don't need to notify IME of it.
uint32_t compositionStart = gIMM32Handler->mCompositionStart;
uint32_t compositionEnd =
compositionStart + gIMM32Handler->mCompositionString.Length();
if (aIMENotification.mMouseButtonEventData.mOffset < compositionStart ||
aIMENotification.mMouseButtonEventData.mOffset >= compositionEnd) {
return NS_OK;
}
BYTE button;
switch (aIMENotification.mMouseButtonEventData.mButton) {
case WidgetMouseEventBase::eLeftButton:
button = IMEMOUSE_LDOWN;
break;
case WidgetMouseEventBase::eMiddleButton:
button = IMEMOUSE_MDOWN;
break;
case WidgetMouseEventBase::eRightButton:
button = IMEMOUSE_RDOWN;
break;
default:
return NS_OK;
}
// calcurate positioning and offset
// char : JCH1|JCH2|JCH3
// offset: 0011 1122 2233
// positioning: 2301 2301 2301
nsIntRect cursorInTopLevel, cursorRect(cursor, nsIntSize(0, 0));
ResolveIMECaretPos(aWindow, cursorRect,
aWindow->GetTopLevelWindow(false), cursorInTopLevel);
int32_t cursorXInChar = cursorInTopLevel.x - charAtPt.mReply.mRect.x;
nsIntPoint cursorPos =
aIMENotification.mMouseButtonEventData.mCursorPos.AsIntPoint();
nsIntRect charRect =
aIMENotification.mMouseButtonEventData.mCharRect.AsIntRect();
int32_t cursorXInChar = cursorPos.x - charRect.x;
// The event might hit to zero-width character, see bug 694913.
// The reason might be:
// * There are some zero-width characters are actually.
@ -2084,26 +2097,30 @@ nsIMM32Handler::OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction,
// We should assume that user clicked on right most of the zero-width
// character in such case.
int positioning = 1;
if (charAtPt.mReply.mRect.width > 0) {
positioning = cursorXInChar * 4 / charAtPt.mReply.mRect.width;
if (charRect.width > 0) {
positioning = cursorXInChar * 4 / charRect.width;
positioning = (positioning + 2) % 4;
}
int offset = charAtPt.mReply.mOffset - mCompositionStart;
int offset =
aIMENotification.mMouseButtonEventData.mOffset - compositionStart;
if (positioning < 2) {
offset++;
}
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: OnMouseEvent, x,y=%ld,%ld, offset=%ld, positioning=%ld\n",
cursor.x, cursor.y, offset, positioning));
("IMM32: OnMouseButtonEvent, x,y=%ld,%ld, offset=%ld, positioning=%ld\n",
cursorPos.x, cursorPos.y, offset, positioning));
// send MS_MSIME_MOUSE message to default IME window.
HWND imeWnd = ::ImmGetDefaultIMEWnd(aWindow->GetWindowHandle());
nsIMEContext IMEContext(aWindow->GetWindowHandle());
return ::SendMessageW(imeWnd, sWM_MSIME_MOUSE,
MAKELONG(MAKEWORD(aAction, positioning), offset),
(LPARAM) IMEContext.get()) == 1;
if (::SendMessageW(imeWnd, sWM_MSIME_MOUSE,
MAKELONG(MAKEWORD(button, positioning), offset),
(LPARAM) IMEContext.get()) == 1) {
return NS_SUCCESS_EVENT_CONSUMED;
}
return NS_OK;
}
/* static */ bool

View File

@ -110,6 +110,7 @@ protected:
class nsIMM32Handler
{
typedef mozilla::widget::IMENotification IMENotification;
typedef mozilla::widget::MSGResult MSGResult;
public:
static void Initialize();
@ -145,6 +146,11 @@ public:
static nsIMEUpdatePreference GetIMEUpdatePreference();
// Returns NS_SUCCESS_EVENT_CONSUMED if the mouse button event is consumed by
// IME. Otherwise, NS_OK.
static nsresult OnMouseButtonEvent(nsWindow* aWindow,
const IMENotification& aIMENotification);
protected:
static void EnsureHandlerInstance();
@ -176,8 +182,6 @@ protected:
// On*() methods return true if the caller of message handler shouldn't do
// anything anymore. Otherwise, false.
bool OnMouseEvent(nsWindow* aWindow, LPARAM lParam, int aAction,
MSGResult& aResult);
static bool OnKeyDownEvent(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
MSGResult& aResult);