From 25534ee2c478e442e9f25e9efaa27b90feff2495 Mon Sep 17 00:00:00 2001 From: "masayuki%d-toybox.com" Date: Wed, 16 Aug 2006 16:35:59 +0000 Subject: [PATCH] Bug 271815 GTK2 IM over-the-spot doesn't work with Chinese IM because the editor doesn't return correct caret position r=timeless, sr=roc, a=dveditz git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_0_BRANCH@207598 18797224-902f-48f8-a5cc-f745e15eee43 --- .../libeditor/text/nsPlaintextEditor.cpp | 139 ++++++++++-------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp index 860e7ba971d..30e0188be03 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp @@ -1553,93 +1553,106 @@ nsPlaintextEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList) NS_IMETHODIMP nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply) { - NS_ASSERTION(aTextRangeList, "null ptr"); - if (!aTextRangeList) - return NS_ERROR_NULL_POINTER; - - // workaround for windows ime bug 23558: we get every ime event twice. - // for escape keypress, this causes an empty string to be passed - // twice, which freaks out the editor. This is to detect and avoid that - // situation: - if (aCompositionString.IsEmpty() && !mIMETextNode) + if (!aTextRangeList && !aCompositionString.IsEmpty()) { - return NS_OK; + NS_ERROR("aTextRangeList is null but the composition string is not null"); + return NS_ERROR_NULL_POINTER; } - - mIMETextRangeList = aTextRangeList; nsCOMPtr ps = do_QueryReferent(mPresShellWeak); if (!ps) return NS_ERROR_NOT_INITIALIZED; - // XXX_kin: BEGIN HACK! HACK! HACK! - // XXX_kin: - // XXX_kin: This is lame! The IME stuff needs caret coordinates - // XXX_kin: synchronously, but the editor could be using async - // XXX_kin: updates (reflows and paints) for performance reasons. - // XXX_kin: In order to give IME what it needs, we have to temporarily - // XXX_kin: switch to sync updating during this call so that the - // XXX_kin: nsAutoPlaceHolderBatch can force sync reflows, paints, - // XXX_kin: and selection scrolling, so that we get back accurate - // XXX_kin: caret coordinates. - - PRUint32 flags = 0; - PRBool restoreFlags = PR_FALSE; - - if (NS_SUCCEEDED(GetFlags(&flags)) && - (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)) - { - if (NS_SUCCEEDED(SetFlags(flags & (~nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)))) - restoreFlags = PR_TRUE; - } - - // XXX_kin: END HACK! HACK! HACK! - nsCOMPtr selection; nsresult result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) return result; nsCOMPtr caretP; - - // we need the nsAutoPlaceHolderBatch destructor called before hitting - // GetCaretCoordinates so the states in Frame system sync with content - // therefore, we put the nsAutoPlaceHolderBatch into a inner block + ps->GetCaret(getter_AddRefs(caretP)); + + // We should return caret position if it is possible. Because this event + // dispatcher always expects to be returned the correct caret position. + // But in following cases, we don't need to process the composition string, + // so, we only need to return the caret position. + + // aCompositionString.IsEmpty() && !mIMETextNode: + // Workaround for Windows IME bug 23558: We get every IME event twice. + // For escape keypress, this causes an empty string to be passed + // twice, which freaks out the editor. + + // aCompositionString.IsEmpty() && !aTextRangeList: + // Some Chinese IMEs for Linux are always composition string and text range + // list are empty when listing the Chinese characters. In this case, + // we don't need to process composition string too. See bug 271815. + + if (!aCompositionString.IsEmpty() || (mIMETextNode && aTextRangeList)) { - nsAutoPlaceHolderBatch batch(this, gIMETxnName); + mIMETextRangeList = aTextRangeList; - SetIsIMEComposing(); // We set mIsIMEComposing properly. + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: This is lame! The IME stuff needs caret coordinates + // XXX_kin: synchronously, but the editor could be using async + // XXX_kin: updates (reflows and paints) for performance reasons. + // XXX_kin: In order to give IME what it needs, we have to temporarily + // XXX_kin: switch to sync updating during this call so that the + // XXX_kin: nsAutoPlaceHolderBatch can force sync reflows, paints, + // XXX_kin: and selection scrolling, so that we get back accurate + // XXX_kin: caret coordinates. - result = InsertText(aCompositionString); + PRUint32 flags = 0; + PRBool restoreFlags = PR_FALSE; - mIMEBufferLength = aCompositionString.Length(); - - ps->GetCaret(getter_AddRefs(caretP)); - if (caretP) - caretP->SetCaretDOMSelection(selection); - - // second part of 23558 fix: - if (aCompositionString.IsEmpty()) + if (NS_SUCCEEDED(GetFlags(&flags)) && + (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)) { - mIMETextNode = nsnull; + if (NS_SUCCEEDED(SetFlags( + flags & (~nsIPlaintextEditor::eEditorUseAsyncUpdatesMask)))) + restoreFlags = PR_TRUE; } + + // XXX_kin: END HACK! HACK! HACK! + + // we need the nsAutoPlaceHolderBatch destructor called before hitting + // GetCaretCoordinates so the states in Frame system sync with content + // therefore, we put the nsAutoPlaceHolderBatch into a inner block + { + nsAutoPlaceHolderBatch batch(this, gIMETxnName); + + SetIsIMEComposing(); // We set mIsIMEComposing properly. + + result = InsertText(aCompositionString); + + mIMEBufferLength = aCompositionString.Length(); + + if (caretP) + caretP->SetCaretDOMSelection(selection); + + // second part of 23558 fix: + if (aCompositionString.IsEmpty()) + mIMETextNode = nsnull; + } + + // XXX_kin: BEGIN HACK! HACK! HACK! + // XXX_kin: + // XXX_kin: Restore the previous set of flags! + + if (restoreFlags) + SetFlags(flags); + + // XXX_kin: END HACK! HACK! HACK! } - // XXX_kin: BEGIN HACK! HACK! HACK! - // XXX_kin: - // XXX_kin: Restore the previous set of flags! - - if (restoreFlags) - SetFlags(flags); - - // XXX_kin: END HACK! HACK! HACK! - if (caretP) { - result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, selection, - &(aReply->mCursorPosition), &(aReply->mCursorIsCollapsed), nsnull); + result = caretP->GetCaretCoordinates(nsICaret::eIMECoordinates, + selection, + &(aReply->mCursorPosition), + &(aReply->mCursorIsCollapsed), + nsnull); NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret position"); } - + return result; }