diff --git a/widget/windows/WinIMEHandler.cpp b/widget/windows/WinIMEHandler.cpp index 6c489e7064a4..35bbced25fb8 100644 --- a/widget/windows/WinIMEHandler.cpp +++ b/widget/windows/WinIMEHandler.cpp @@ -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 diff --git a/widget/windows/nsIMM32Handler.cpp b/widget/windows/nsIMM32Handler.cpp index 33a747b51d80..2fd5ac354994 100644 --- a/widget/windows/nsIMM32Handler.cpp +++ b/widget/windows/nsIMM32Handler.cpp @@ -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 diff --git a/widget/windows/nsIMM32Handler.h b/widget/windows/nsIMM32Handler.h index 656a1bdde4a2..b3a054d44c04 100644 --- a/widget/windows/nsIMM32Handler.h +++ b/widget/windows/nsIMM32Handler.h @@ -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);