Bug 1162818 part.2 Make it possible to set IME selection from outside of IMETextTxn r=ehsan
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 05 Jun 2015 02:06:09 +0900
changeset 247170 e037403d3e8c1e82956046c0b208864079a96b0b
parent 247169 66bab785635f3b108bc88c07228848463a07d7f6
child 247171 75ceb4773c0d6f2576dea5ac37a5bf11eb4f5cde
push id28855
push userkwierso@gmail.com
push dateFri, 05 Jun 2015 01:19:30 +0000
treeherdermozilla-central@227d356ac030 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1162818
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1162818 part.2 Make it possible to set IME selection from outside of IMETextTxn r=ehsan
editor/libeditor/IMETextTxn.cpp
editor/libeditor/IMETextTxn.h
--- a/editor/libeditor/IMETextTxn.cpp
+++ b/editor/libeditor/IMETextTxn.cpp
@@ -150,93 +150,107 @@ ToSelectionType(uint32_t aTextRangeType)
       MOZ_CRASH("Selection type is invalid");
       return nsISelectionController::SELECTION_NORMAL;
   }
 }
 
 nsresult
 IMETextTxn::SetSelectionForRanges()
 {
-  nsRefPtr<Selection> selection = mEditor.GetSelection();
+  return SetIMESelection(mEditor, mTextNode, mOffset,
+                         mStringToInsert.Length(), mRanges);
+}
+
+// static
+nsresult
+IMETextTxn::SetIMESelection(nsEditor& aEditor,
+                            Text* aTextNode,
+                            uint32_t aOffsetInNode,
+                            uint32_t aLengthOfCompositionString,
+                            const TextRangeArray* aRanges)
+{
+  nsRefPtr<Selection> selection = aEditor.GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
 
   nsresult rv = selection->StartBatchChanges();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // First, remove all selections of IME composition.
   static const SelectionType kIMESelections[] = {
     nsISelectionController::SELECTION_IME_RAWINPUT,
     nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT,
     nsISelectionController::SELECTION_IME_CONVERTEDTEXT,
     nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT
   };
 
   nsCOMPtr<nsISelectionController> selCon;
-  mEditor.GetSelectionController(getter_AddRefs(selCon));
+  aEditor.GetSelectionController(getter_AddRefs(selCon));
   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
 
   for (uint32_t i = 0; i < ArrayLength(kIMESelections); ++i) {
     nsCOMPtr<nsISelection> selectionOfIME;
     if (NS_FAILED(selCon->GetSelection(kIMESelections[i],
                                        getter_AddRefs(selectionOfIME)))) {
       continue;
     }
     rv = selectionOfIME->RemoveAllRanges();
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "Failed to remove all ranges of IME selection");
   }
 
   // Set caret position and selection of IME composition with TextRangeArray.
   bool setCaret = false;
-  uint32_t countOfRanges = mRanges ? mRanges->Length() : 0;
+  uint32_t countOfRanges = aRanges ? aRanges->Length() : 0;
 
 #ifdef DEBUG
   // Bounds-checking on debug builds
-  uint32_t maxOffset = mTextNode->Length();
+  uint32_t maxOffset = aTextNode->Length();
 #endif
 
-  // The mStringToInsert may be truncated if maxlength attribute value doesn't
-  // allow input of all text of this composition. So, we can get actual length
-  // of the inserted string from it.
-  uint32_t insertedLength = mStringToInsert.Length();
+  // NOTE: composition string may be truncated when it's committed and
+  //       maxlength attribute value doesn't allow input of all text of this
+  //       composition.
   for (uint32_t i = 0; i < countOfRanges; ++i) {
-    const TextRange& textRange = mRanges->ElementAt(i);
+    const TextRange& textRange = aRanges->ElementAt(i);
 
     // Caret needs special handling since its length may be 0 and if it's not
     // specified explicitly, we need to handle it ourselves later.
     if (textRange.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
       NS_ASSERTION(!setCaret, "The ranges already has caret position");
       NS_ASSERTION(!textRange.Length(), "nsEditor doesn't support wide caret");
       int32_t caretOffset = static_cast<int32_t>(
-        mOffset + std::min(textRange.mStartOffset, insertedLength));
+        aOffsetInNode +
+          std::min(textRange.mStartOffset, aLengthOfCompositionString));
       MOZ_ASSERT(caretOffset >= 0 &&
                  static_cast<uint32_t>(caretOffset) <= maxOffset);
-      rv = selection->Collapse(mTextNode, caretOffset);
+      rv = selection->Collapse(aTextNode, caretOffset);
       setCaret = setCaret || NS_SUCCEEDED(rv);
       NS_ASSERTION(setCaret, "Failed to collapse normal selection");
       continue;
     }
 
     // If the clause length is 0, it should be a bug.
     if (!textRange.Length()) {
       NS_WARNING("Any clauses must not be empty");
       continue;
     }
 
     nsRefPtr<nsRange> clauseRange;
     int32_t startOffset = static_cast<int32_t>(
-      mOffset + std::min(textRange.mStartOffset, insertedLength));
+      aOffsetInNode +
+        std::min(textRange.mStartOffset, aLengthOfCompositionString));
     MOZ_ASSERT(startOffset >= 0 &&
                static_cast<uint32_t>(startOffset) <= maxOffset);
     int32_t endOffset = static_cast<int32_t>(
-      mOffset + std::min(textRange.mEndOffset, insertedLength));
+      aOffsetInNode +
+        std::min(textRange.mEndOffset, aLengthOfCompositionString));
     MOZ_ASSERT(endOffset >= startOffset &&
                static_cast<uint32_t>(endOffset) <= maxOffset);
-    rv = nsRange::CreateRange(mTextNode, startOffset,
-                              mTextNode, endOffset,
+    rv = nsRange::CreateRange(aTextNode, startOffset,
+                              aTextNode, endOffset,
                               getter_AddRefs(clauseRange));
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to create a DOM range for a clause of composition");
       break;
     }
 
     // Set the range of the clause to selection.
     nsCOMPtr<nsISelection> selectionOfIME;
@@ -266,20 +280,21 @@ IMETextTxn::SetSelectionForRanges()
       NS_WARNING("Failed to set selection style");
       break; // but this is unexpected...
     }
   }
 
   // If the ranges doesn't include explicit caret position, let's set the
   // caret to the end of composition string.
   if (!setCaret) {
-    int32_t caretOffset = static_cast<int32_t>(mOffset + insertedLength);
+    int32_t caretOffset =
+      static_cast<int32_t>(aOffsetInNode + aLengthOfCompositionString);
     MOZ_ASSERT(caretOffset >= 0 &&
                static_cast<uint32_t>(caretOffset) <= maxOffset);
-    rv = selection->Collapse(mTextNode, caretOffset);
+    rv = selection->Collapse(aTextNode, caretOffset);
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "Failed to set caret at the end of composition string");
   }
 
   rv = selection->EndBatchChanges();
   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes");
 
   return rv;
--- a/editor/libeditor/IMETextTxn.h
+++ b/editor/libeditor/IMETextTxn.h
@@ -49,31 +49,37 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_EDITTXN
 
   NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
 
   void MarkFixed();
 
+  static nsresult SetIMESelection(nsEditor& aEditor,
+                                  Text* aTextNode,
+                                  uint32_t aOffsetInNode,
+                                  uint32_t aLengthOfCompositionString,
+                                  const TextRangeArray* aRanges);
+
 private:
   ~IMETextTxn();
 
   nsresult SetSelectionForRanges();
 
   /** The text element to operate upon */
   nsRefPtr<Text> mTextNode;
 
   /** The offsets into mTextNode where the insertion should be placed */
   uint32_t mOffset;
 
   uint32_t mReplaceLength;
 
   /** The range list **/
-  nsRefPtr<mozilla::TextRangeArray> mRanges;
+  nsRefPtr<TextRangeArray> mRanges;
 
   /** The text to insert into mTextNode at mOffset */
   nsString mStringToInsert;
 
   /** The editor, which is used to get the selection controller */
   nsEditor& mEditor;
 
   bool mFixed;