diff --git a/mozilla/content/events/public/nsIPrivateCompositionEvent.h b/mozilla/content/events/public/nsIPrivateCompositionEvent.h index d9fd5eb31a5..858680203e0 100644 --- a/mozilla/content/events/public/nsIPrivateCompositionEvent.h +++ b/mozilla/content/events/public/nsIPrivateCompositionEvent.h @@ -41,18 +41,19 @@ #include "nsEvent.h" #include "nsISupports.h" -// {ECF6BEF1-5F0C-11d3-9EB3-0060089FE59B} +// {889792DC-22D8-4d1a-AC3D-58AD7DEBA17B} #define NS_IPRIVATECOMPOSITIONEVENT_IID \ -{ 0xecf6bef1, 0x5f0c, 0x11d3, \ -{ 0x9e, 0xb3, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b }} +{ 0x889792dc, 0x22d8, 0x4d1a, \ +{ 0xac, 0x3d, 0x58, 0xad, 0x7d, 0xeb, 0xa1, 0x7b }} class nsIPrivateCompositionEvent : public nsISupports { public: - NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPRIVATECOMPOSITIONEVENT_IID) + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPRIVATECOMPOSITIONEVENT_IID) - NS_IMETHOD GetCompositionReply(struct nsTextEventReply** aReply) = 0; - NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply) = 0; + NS_IMETHOD GetCompositionReply(struct nsTextEventReply** aReply) = 0; + NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply) = 0; + NS_IMETHOD GetQueryCaretRectReply(nsQueryCaretRectEventReply** aReply) = 0; }; #endif // nsIPrivateCompositionEvent_h__ diff --git a/mozilla/content/events/src/nsDOMUIEvent.cpp b/mozilla/content/events/src/nsDOMUIEvent.cpp index ee50c7a4f56..276aa6527fd 100644 --- a/mozilla/content/events/src/nsDOMUIEvent.cpp +++ b/mozilla/content/events/src/nsDOMUIEvent.cpp @@ -468,6 +468,18 @@ nsDOMUIEvent::GetReconversionReply(nsReconversionEventReply** aReply) return NS_ERROR_FAILURE; } +NS_METHOD +nsDOMUIEvent::GetQueryCaretRectReply(nsQueryCaretRectEventReply** aReply) +{ + if (mEvent->eventStructType == NS_QUERYCARETRECT_EVENT) + { + *aReply = &(NS_STATIC_CAST(nsQueryCaretRectEvent*, mEvent)->theReply); + return NS_OK; + } + aReply = nsnull; + return NS_ERROR_FAILURE; +} + nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsGUIEvent *aEvent) diff --git a/mozilla/content/events/src/nsDOMUIEvent.h b/mozilla/content/events/src/nsDOMUIEvent.h index 09ba588072a..eaa00dbc6a1 100644 --- a/mozilla/content/events/src/nsDOMUIEvent.h +++ b/mozilla/content/events/src/nsDOMUIEvent.h @@ -64,6 +64,7 @@ public: // nsIPrivateCompositionEvent interface NS_IMETHOD GetCompositionReply(nsTextEventReply** aReply); NS_IMETHOD GetReconversionReply(nsReconversionEventReply** aReply); + NS_IMETHOD GetQueryCaretRectReply(nsQueryCaretRectEventReply** aReply); // Forward to nsDOMEvent NS_FORWARD_TO_NSDOMEVENT diff --git a/mozilla/content/events/src/nsEventListenerManager.cpp b/mozilla/content/events/src/nsEventListenerManager.cpp index bece924e072..3158f687323 100644 --- a/mozilla/content/events/src/nsEventListenerManager.cpp +++ b/mozilla/content/events/src/nsEventListenerManager.cpp @@ -206,7 +206,9 @@ static const EventDispatchData sCompositionEvents[] = { { NS_COMPOSITION_QUERY, HANDLER(&nsIDOMCompositionListener::HandleQueryComposition), NS_EVENT_BITS_COMPOSITION_QUERY }, { NS_RECONVERSION_QUERY, HANDLER(&nsIDOMCompositionListener::HandleQueryReconversion), - NS_EVENT_BITS_COMPOSITION_RECONVERSION } + NS_EVENT_BITS_COMPOSITION_RECONVERSION }, + { NS_QUERYCARETRECT, HANDLER(&nsIDOMCompositionListener::HandleQueryCaretRect), + NS_EVENT_BITS_COMPOSITION_QUERYCARETRECT } }; static const EventDispatchData sTextEvents[] = { @@ -1642,6 +1644,7 @@ nsEventListenerManager::CreateEvent(nsPresContext* aPresContext, case NS_GUI_EVENT: case NS_COMPOSITION_EVENT: case NS_RECONVERSION_EVENT: + case NS_QUERYCARETRECT_EVENT: return NS_NewDOMUIEvent(aDOMEvent, aPresContext, NS_STATIC_CAST(nsGUIEvent*,aEvent)); case NS_KEY_EVENT: return NS_NewDOMKeyboardEvent(aDOMEvent, aPresContext, NS_STATIC_CAST(nsKeyEvent*,aEvent)); diff --git a/mozilla/content/events/src/nsEventListenerManager.h b/mozilla/content/events/src/nsEventListenerManager.h index 40fcfcb1cb2..8c273fc4682 100644 --- a/mozilla/content/events/src/nsEventListenerManager.h +++ b/mozilla/content/events/src/nsEventListenerManager.h @@ -273,11 +273,12 @@ protected: #define NS_EVENT_BITS_TEXT_TEXT 0x01 //nsIDOMCompositionListener -#define NS_EVENT_BITS_COMPOSITION_NONE 0x00 -#define NS_EVENT_BITS_COMPOSITION_START 0x01 -#define NS_EVENT_BITS_COMPOSITION_END 0x02 -#define NS_EVENT_BITS_COMPOSITION_QUERY 0x04 -#define NS_EVENT_BITS_COMPOSITION_RECONVERSION 0x08 +#define NS_EVENT_BITS_COMPOSITION_NONE 0x00 +#define NS_EVENT_BITS_COMPOSITION_START 0x01 +#define NS_EVENT_BITS_COMPOSITION_END 0x02 +#define NS_EVENT_BITS_COMPOSITION_QUERY 0x04 +#define NS_EVENT_BITS_COMPOSITION_RECONVERSION 0x08 +#define NS_EVENT_BITS_COMPOSITION_QUERYCARETRECT 0x10 //nsIDOMFocusListener #define NS_EVENT_BITS_FOCUS_NONE 0x00 diff --git a/mozilla/dom/public/coreEvents/nsIDOMCompositionListener.h b/mozilla/dom/public/coreEvents/nsIDOMCompositionListener.h index 69e675157e7..409ee57e7d0 100644 --- a/mozilla/dom/public/coreEvents/nsIDOMCompositionListener.h +++ b/mozilla/dom/public/coreEvents/nsIDOMCompositionListener.h @@ -60,5 +60,6 @@ public: NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent) = 0; NS_IMETHOD HandleQueryComposition(nsIDOMEvent* aCompositionEvent) = 0; NS_IMETHOD HandleQueryReconversion(nsIDOMEvent* aCompositionEvent) = 0; + NS_IMETHOD HandleQueryCaretRect(nsIDOMEvent* aCompositionEvent) = 0; }; #endif // nsIDOMCompositionListener_h__ diff --git a/mozilla/editor/idl/nsIEditorIMESupport.idl b/mozilla/editor/idl/nsIEditorIMESupport.idl index 3cbc3f40d0c..60cdfb417ed 100644 --- a/mozilla/editor/idl/nsIEditorIMESupport.idl +++ b/mozilla/editor/idl/nsIEditorIMESupport.idl @@ -42,65 +42,75 @@ class nsIPrivateTextRangeList; struct nsTextEventReply; struct nsReconversionEventReply; +struct nsQueryCaretRectEventReply; %} [ptr] native nsIPrivateTextRangeListPtr(nsIPrivateTextRangeList); [ptr] native nsTextEventReplyPtr(nsTextEventReply); [ptr] native nsReconversionEventReplyPtr(nsReconversionEventReply); +[ptr] native nsQueryCaretRectEventReplyPtr(nsQueryCaretRectEventReply); -[scriptable, uuid(fe489b4d-d2f6-4215-ab33-6afd66388416)] +[scriptable, uuid(205b3e49-aa58-499e-880b-aacab9dede01)] interface nsIEditorIMESupport : nsISupports { /** - * BeginComposition(nsTextEventReply* aReply) Handles the start of inline input composition. + * beginComposition(nsTextEventReply* aReply) Handles the start of inline input composition. */ - [noscript] void BeginComposition(in nsTextEventReplyPtr aReply); + [noscript] void beginComposition(in nsTextEventReplyPtr aReply); /** - * SetCompositionString() Sets the inline input composition string. - * BeginComposition must be called prior to this. + * setCompositionString() Sets the inline input composition string. + * beginComposition must be called prior to this. */ - [noscript] void SetCompositionString(in DOMString aCompositionString, in nsIPrivateTextRangeListPtr aTextRange, in nsTextEventReplyPtr aReply); + [noscript] void setCompositionString(in DOMString aCompositionString, in nsIPrivateTextRangeListPtr aTextRange, in nsTextEventReplyPtr aReply); /** - * EndComposition() Handles the end of inline input composition. + * endComposition() Handles the end of inline input composition. */ - void EndComposition(); + void endComposition(); /** - * QueryComposition() Get the composition position + * queryComposition() Get the composition position */ - [noscript] void QueryComposition(in nsTextEventReplyPtr aReply); + + [noscript] void queryComposition(in nsTextEventReplyPtr aReply); /** - * ForceCompositionEnd() force the composition end + * forceCompositionEnd() force the composition end */ - void ForceCompositionEnd(); + void forceCompositionEnd(); /** - * GetReconvertionString() Get the reconvertion string + * getReconversionString() Get the reconvertion string */ - [noscript] void GetReconversionString(in nsReconversionEventReplyPtr aReply); - + + [noscript] void getReconversionString(in nsReconversionEventReplyPtr aReply); + /** * Notify for IME when the editor got focus. */ - [noscript] void NotifyIMEOnFocus(); - + void notifyIMEOnFocus(); + /** * Notify for IME when the editor lost focus. */ - [noscript] void NotifyIMEOnBlur(); + void notifyIMEOnBlur(); + + /** + * getQueryCaretRect() Get the query caret rect + */ + + [noscript] void getQueryCaretRect(in nsQueryCaretRectEventReplyPtr aReply); }; diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index c9dbc13bbcb..c71cb386973 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -2167,6 +2167,34 @@ nsEditor::GetReconversionString(nsReconversionEventReply* aReply) return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP +nsEditor::GetQueryCaretRect(nsQueryCaretRectEventReply* aReply) +{ + nsCOMPtr selection; + nsresult rv = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv)) + return rv; + + if (!mPresShellWeak) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr ps = do_QueryReferent(mPresShellWeak); + if (!ps) + return NS_ERROR_NOT_INITIALIZED; + + nsCOMPtr caretP; + rv = ps->GetCaret(getter_AddRefs(caretP)); + + if (NS_FAILED(rv) || !caretP) + return rv; + + PRBool cursorIsCollapsed; + rv = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, + &aReply->mCaretRect, &cursorIsCollapsed, nsnull); + + return rv; +} + #ifdef XP_MAC #pragma mark - #pragma mark public nsEditor methods diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index 454d9923786..773a4f03179 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -843,6 +843,24 @@ nsTextEditorCompositionListener::HandleQueryReconversion(nsIDOMEvent* aReconvers return mEditor->GetReconversionString(eventReply); } +nsresult +nsTextEditorCompositionListener::HandleQueryCaretRect(nsIDOMEvent* aQueryCaretRectEvent) +{ +#ifdef DEBUG_IME + printf("nsTextEditorCompositionListener::HandleQueryCaretRect\n"); +#endif + nsCOMPtr pCompositionEvent = do_QueryInterface(aQueryCaretRectEvent); + if (!pCompositionEvent) + return NS_ERROR_FAILURE; + + nsQueryCaretRectEventReply* eventReply; + nsresult rv = pCompositionEvent->GetQueryCaretRectReply(&eventReply); + if (NS_FAILED(rv)) + return rv; + + return mEditor->GetQueryCaretRect(eventReply); +} + /* * Factory functions */ diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.h b/mozilla/editor/libeditor/text/nsEditorEventListeners.h index fb2a3a164b4..27346ca8207 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.h +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.h @@ -146,6 +146,7 @@ public: NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent); NS_IMETHOD HandleQueryComposition(nsIDOMEvent* aCompositionEvent); NS_IMETHOD HandleQueryReconversion(nsIDOMEvent* aReconvertionEvent); + NS_IMETHOD HandleQueryCaretRect(nsIDOMEvent* aQueryCaretRectEvent); /*END implementations of textevent handler interface*/ protected: diff --git a/mozilla/editor/ui/composer/content/ComposerCommands.js b/mozilla/editor/ui/composer/content/ComposerCommands.js index 89a114ef63c..c5e26accf99 100644 --- a/mozilla/editor/ui/composer/content/ComposerCommands.js +++ b/mozilla/editor/ui/composer/content/ComposerCommands.js @@ -929,7 +929,7 @@ function OutputFileWithPersistAPI(editorDoc, aDestinationLocation, aRelatedFiles var editor = GetCurrentEditor(); try { var imeEditor = editor.QueryInterface(Components.interfaces.nsIEditorIMESupport); - imeEditor.ForceCompositionEnd(); + imeEditor.forceCompositionEnd(); } catch (e) {} var isLocalFile = false; diff --git a/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.cpp b/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.cpp index 6f84432b86d..15fbe15474c 100644 --- a/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.cpp +++ b/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.cpp @@ -1211,6 +1211,13 @@ nsTypeAheadFind::HandleQueryReconversion(nsIDOMEvent* aCompositionEvent) } +NS_IMETHODIMP +nsTypeAheadFind::HandleQueryCaretRect(nsIDOMEvent* aCompositionEvent) +{ + return NS_OK; +} + + nsresult nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, PRBool aIsRepeatingSameChar, PRBool aIsLinksOnly, diff --git a/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.h b/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.h index 9d7a7129ba5..52f8ecff10c 100644 --- a/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.h +++ b/mozilla/extensions/typeaheadfind/src/nsTypeAheadFind.h @@ -115,6 +115,7 @@ public: NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent); NS_IMETHOD HandleQueryComposition(nsIDOMEvent* aCompositionEvent); NS_IMETHOD HandleQueryReconversion(nsIDOMEvent* aCompositionEvent); + NS_IMETHOD HandleQueryCaretRect(nsIDOMEvent* aCompositionEvent); // ----- nsIScrollPositionListener -------------------- NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 8a79f17a652..15086d88e76 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -2174,6 +2174,12 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS ((nsCompositionEvent*)aEvent)->theReply.mCursorPosition.width=NSTwipsToIntPixels(((nsCompositionEvent*)aEvent)->theReply.mCursorPosition.width,t2p); ((nsCompositionEvent*)aEvent)->theReply.mCursorPosition.height=NSTwipsToIntPixels(((nsCompositionEvent*)aEvent)->theReply.mCursorPosition.height,t2p); } + if(aEvent->message==NS_QUERYCARETRECT) { + ((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.x=NSTwipsToIntPixels(((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.x,t2p); + ((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.y=NSTwipsToIntPixels(((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.y,t2p); + ((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.width=NSTwipsToIntPixels(((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.width,t2p); + ((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.height=NSTwipsToIntPixels(((nsQueryCaretRectEvent*)aEvent)->theReply.mCaretRect.height,t2p); + } } break; diff --git a/mozilla/widget/public/nsEvent.h b/mozilla/widget/public/nsEvent.h index 34f393a9cec..9e80c740982 100644 --- a/mozilla/widget/public/nsEvent.h +++ b/mozilla/widget/public/nsEvent.h @@ -79,5 +79,6 @@ struct nsMenuEvent; struct nsTextEventReply; struct nsReconversionEventReply; +struct nsQueryCaretRectEventReply; #endif // nsEvent_h__ diff --git a/mozilla/widget/public/nsGUIEvent.h b/mozilla/widget/public/nsGUIEvent.h index bb53927e9c5..628a3009cf8 100644 --- a/mozilla/widget/public/nsGUIEvent.h +++ b/mozilla/widget/public/nsGUIEvent.h @@ -91,6 +91,7 @@ class nsIURI; #define NS_POPUPBLOCKED_EVENT 25 #define NS_BEFORE_PAGE_UNLOAD_EVENT 26 #define NS_UI_EVENT 27 +#define NS_QUERYCARETRECT_EVENT 28 #define NS_EVENT_FLAG_NONE 0x0000 #define NS_EVENT_FLAG_INIT 0x0001 @@ -317,6 +318,10 @@ class nsIURI; #define NS_UI_FOCUSIN (NS_UI_EVENT_START + 1) #define NS_UI_FOCUSOUT (NS_UI_EVENT_START + 2) +// query caret rect events +#define NS_QUERYCARETRECT_START 2600 +#define NS_QUERYCARETRECT (NS_QUERYCARETRECT_START) + /** * Return status for event processors, nsEventStatus, is defined in * nsEvent.h. @@ -728,6 +733,26 @@ struct nsReconversionEvent : public nsInputEvent nsReconversionEventReply theReply; }; +struct nsQueryCaretRectEventReply { + nsQueryCaretRectEventReply() + { + } + + nsRect mCaretRect; +}; + +struct nsQueryCaretRectEvent : public nsInputEvent +{ + nsQueryCaretRectEvent(PRUint32 msg = 0, + nsIWidget *w = nsnull, + PRUint8 structType = NS_QUERYCARETRECT_EVENT) + : nsInputEvent(msg, w, structType) + { + } + + nsQueryCaretRectEventReply theReply; +}; + /** * MenuItem event * @@ -887,6 +912,7 @@ enum nsDragDropEventStatus { ((evnt)->message == NS_COMPOSITION_START) || \ ((evnt)->message == NS_COMPOSITION_END) || \ ((evnt)->message == NS_RECONVERSION_QUERY) || \ + ((evnt)->message == NS_QUERYCARETRECT) || \ ((evnt)->message == NS_COMPOSITION_QUERY)) #define NS_IS_FOCUS_EVENT(evnt) \ diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index c47fcf7f38d..bbf684d4100 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -70,6 +70,7 @@ #include "nsColor.h" #include "nsTransform2D.h" #include "nsIEventQueue.h" +#include "nsNativeCharsetUtils.h" #include // unknwn.h is needed to build with WIN32_LEAN_AND_MEAN @@ -245,6 +246,7 @@ long nsWindow::sIMECursorPosition = 0; PRUnichar* nsWindow::sIMEReconvertUnicode = NULL; RECT* nsWindow::sIMECompCharPos = nsnull; +PRInt32 nsWindow::sIMECaretHeight = 0; BOOL nsWindow::sIsRegistered = FALSE; BOOL nsWindow::sIsPopupClassRegistered = FALSE; @@ -489,7 +491,16 @@ typedef struct tagRECONVERTSTRING { DWORD dwTargetStrOffset; } RECONVERTSTRING, FAR * LPRECONVERTSTRING; +typedef struct tagIMECHARPOSITION { + DWORD dwSize; + DWORD dwCharPos; + POINT pt; + UINT cLineHeight; + RECT rcDocument; +} IMECHARPOSITION, *PIMECHARPOSITION; + #define IMR_RECONVERTSTRING 0x0004 +#define IMR_QUERYCHARPOSITION 0x0006 #define WM_IME_REQUEST 0x0288 #endif @@ -5786,7 +5797,6 @@ nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr) nsTextEvent event(NS_TEXT_TEXT, this); nsPoint point(0, 0); - CANDIDATEFORM candForm; InitEvent(event, &point); @@ -5814,6 +5824,7 @@ nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr) // if (event.theReply.mCursorPosition.width || event.theReply.mCursorPosition.height) { + CANDIDATEFORM candForm; candForm.dwIndex = 0; candForm.dwStyle = CFS_EXCLUDE; candForm.ptCurrentPos.x = event.theReply.mCursorPosition.x; @@ -5829,6 +5840,13 @@ nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr) } NS_IMM_SETCANDIDATEWINDOW(hIMEContext, &candForm); + + COMPOSITIONFORM compForm; + compForm.dwStyle = CFS_POINT; + compForm.ptCurrentPos.x = event.theReply.mCursorPosition.x; + compForm.ptCurrentPos.y = event.theReply.mCursorPosition.y; + NS_IMM_SETCOMPOSITIONWINDOW(hIMEContext, &compForm); + // somehow the "Intellegent ABC IME" in Simplified Chinese // window listen to the caret position to decide where to put the // candidate window @@ -5855,6 +5873,7 @@ nsWindow::HandleTextEvent(HIMC hIMEContext,PRBool aCheckAttr) sIMECompCharPos[sIMECursorPosition].top = event.theReply.mCursorPosition.y; sIMECompCharPos[sIMECursorPosition].bottom = event.theReply.mCursorPosition.YMost(); } + sIMECaretHeight = event.theReply.mCursorPosition.height; } else { // for some reason we don't know yet, theReply may contain invalid result // need more debugging in nsCaret to find out the reason @@ -5899,6 +5918,12 @@ nsWindow::HandleStartComposition(HIMC hIMEContext) NS_IMM_SETCANDIDATEWINDOW(hIMEContext, &candForm); + COMPOSITIONFORM compForm; + compForm.dwStyle = CFS_POINT; + compForm.ptCurrentPos.x = event.theReply.mCursorPosition.x + IME_X_OFFSET; + compForm.ptCurrentPos.y = event.theReply.mCursorPosition.y + IME_Y_OFFSET; + NS_IMM_SETCOMPOSITIONWINDOW(hIMEContext, &compForm); + sIMECompCharPos = (RECT*)PR_MALLOC(IME_MAX_CHAR_POS*sizeof(RECT)); if (sIMECompCharPos) { memset(sIMECompCharPos, -1, sizeof(RECT)*IME_MAX_CHAR_POS); @@ -5906,6 +5931,7 @@ nsWindow::HandleStartComposition(HIMC hIMEContext) sIMECompCharPos[0].top = event.theReply.mCursorPosition.y; sIMECompCharPos[0].bottom = event.theReply.mCursorPosition.YMost(); } + sIMECaretHeight = event.theReply.mCursorPosition.height; } else { // for some reason we don't know yet, theReply may contain invalid result // need more debugging in nsCaret to find out the reason @@ -5939,6 +5965,7 @@ nsWindow::HandleEndComposition(void) NS_RELEASE(event.widget); PR_FREEIF(sIMECompCharPos); sIMECompCharPos = nsnull; + sIMECaretHeight = 0; sIMEIsComposing = PR_FALSE; } @@ -6454,6 +6481,9 @@ BOOL nsWindow::OnIMERequest(WPARAM aIMR, LPARAM aData, LRESULT *oResult, PRBool case IMR_RECONVERTSTRING: result = OnIMEReconvert(aData, oResult, aUseUnicode); break; + case IMR_QUERYCHARPOSITION: + result = OnIMEQueryCharPosition(aData, oResult, aUseUnicode); + break; } return result; @@ -6552,6 +6582,83 @@ PRBool nsWindow::OnIMEReconvert(LPARAM aData, LRESULT *oResult, PRBool aUseUnico return result; } +//========================================================================== +PRBool nsWindow::OnIMEQueryCharPosition(LPARAM aData, LRESULT *oResult, PRBool aUseUnicode) +{ +#ifdef DEBUG_IME + printf("OnIMEQueryCharPosition\n"); +#endif + IMECHARPOSITION* pCharPosition = (IMECHARPOSITION*)aData; + if (!pCharPosition || + pCharPosition->dwSize < sizeof(IMECHARPOSITION) || + ::GetFocus() != mWnd) { + *oResult = FALSE; + return PR_FALSE; + } + + if (!sIMEIsComposing) { // Including |!sIMECompUnicode| and |!sIMECompUnicode->IsEmpty|. + if (pCharPosition->dwCharPos != 0) { + *oResult = FALSE; + return PR_FALSE; + } + nsPoint point(0, 0); + nsQueryCaretRectEvent event(NS_QUERYCARETRECT, this); + InitEvent(event, &point); + DispatchWindowEvent(&event); + NS_RELEASE(event.widget); + + nsRect screenRect, widgetRect(event.theReply.mCaretRect); + WidgetToScreen(widgetRect, screenRect); + pCharPosition->pt.x = screenRect.x; + pCharPosition->pt.y = screenRect.y; + + pCharPosition->cLineHeight = event.theReply.mCaretRect.height; + + ::GetWindowRect(mWnd, &pCharPosition->rcDocument); + + *oResult = TRUE; + return PR_TRUE; + } + + long charPosition; + if (aUseUnicode || pCharPosition->dwCharPos == 0) { + if (pCharPosition->dwCharPos > sIMECompUnicode->Length()) { + *oResult = FALSE; + return PR_FALSE; + } + charPosition = pCharPosition->dwCharPos; + } else { + nsCAutoString strIMECompAnsi; + NS_CopyUnicodeToNative(*sIMECompUnicode, strIMECompAnsi); + if (pCharPosition->dwCharPos > strIMECompAnsi.Length()) { + *oResult = FALSE; + return PR_FALSE; + } + charPosition = ::MultiByteToWideChar(gCurrentKeyboardCP, MB_PRECOMPOSED, + strIMECompAnsi.get(), pCharPosition->dwCharPos, NULL, 0); + } + // We only support insertion at the cursor position or at the leftmost position. + // Because sIMECompCharPos may be broken by user converting the string. + // But leftmost position and cursor position is always correctly. + if ((charPosition != 0 && charPosition != sIMECursorPosition) || + charPosition > IME_MAX_CHAR_POS) { + *oResult = FALSE; + return PR_FALSE; + } + POINT pt; + pt.x = sIMECompCharPos[charPosition].left; + pt.y = sIMECompCharPos[charPosition].top; + ::ClientToScreen(mWnd, &pt); + pCharPosition->pt = pt; + + pCharPosition->cLineHeight = sIMECaretHeight; + + ::GetWindowRect(mWnd, &pCharPosition->rcDocument); + + *oResult = TRUE; + return PR_TRUE; +} + //========================================================================== BOOL nsWindow::OnIMESelect(BOOL aSelected, WORD aLangID) { diff --git a/mozilla/widget/src/windows/nsWindow.h b/mozilla/widget/src/windows/nsWindow.h index 2977307efd3..16e4ba753ec 100644 --- a/mozilla/widget/src/windows/nsWindow.h +++ b/mozilla/widget/src/windows/nsWindow.h @@ -452,6 +452,7 @@ protected: BOOL OnIMESetContext(BOOL aActive, LPARAM& aISC); BOOL OnIMEStartComposition(); BOOL OnIMEReconvert(LPARAM aData, LRESULT *oResult, PRBool aUseUnicode); + BOOL OnIMEQueryCharPosition(LPARAM aData, LRESULT *oResult, PRBool aUseUnicode); void GetCompositionString(HIMC aHIMC, DWORD aIndex, nsString* aStrUnicode, nsCString* aStrAnsi); @@ -508,6 +509,7 @@ protected: // For describing composing frame static RECT* sIMECompCharPos; + static PRInt32 sIMECaretHeight; nsSize mLastSize; static nsWindow* gCurrentWindow;