Bug 1137572 part.5 Implement TextEventDispatcher::SetPendingComposition() for some platforms whose clause information may overlap each other or the order may not be from start to the end r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 16 Mar 2016 13:47:48 +0900
changeset 328759 f31b1e7194143f36ab1e6f0355b9b1b1a11cec0a
parent 328758 06d5532f051f5a0c6796443d0c1794700c6667b6
child 328760 5482d679c1a8b7c55657d50086f8eb6a59ef9ad9
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1137572
milestone48.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 1137572 part.5 Implement TextEventDispatcher::SetPendingComposition() for some platforms whose clause information may overlap each other or the order may not be from start to the end r=smaug
widget/TextEventDispatcher.cpp
widget/TextEventDispatcher.h
--- a/widget/TextEventDispatcher.cpp
+++ b/widget/TextEventDispatcher.cpp
@@ -571,16 +571,73 @@ TextEventDispatcher::PendingComposition:
 {
   mCaret.mStartOffset = aOffset;
   mCaret.mEndOffset = mCaret.mStartOffset + aLength;
   mCaret.mRangeType = NS_TEXTRANGE_CARETPOSITION;
   return NS_OK;
 }
 
 nsresult
+TextEventDispatcher::PendingComposition::Set(const nsAString& aString,
+                                             const TextRangeArray* aRanges)
+{
+  Clear();
+
+  nsAutoString str(aString);
+  // Don't expose CRLF to web contents, instead, use LF.
+  str.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), NS_LITERAL_STRING("\n"));
+  nsresult rv = SetString(str);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!aRanges || aRanges->IsEmpty()) {
+    // Create dummy range if aString isn't empty.
+    if (!aString.IsEmpty()) {
+      rv = AppendClause(str.Length(), NS_TEXTRANGE_RAWINPUT);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+    return NS_OK;
+  }
+
+  // Adjust offsets in the ranges for XP linefeed character (only \n).
+  // XXX Following code is the safest approach.  However, it wastes performance.
+  //     For ensuring the clauses do not overlap each other, we should redesign
+  //     TextRange later.
+  for (uint32_t i = 0; i < aRanges->Length(); ++i) {
+    TextRange range = aRanges->ElementAt(i);
+    TextRange nativeRange = range;
+    if (nativeRange.mStartOffset > 0) {
+      nsAutoString preText(Substring(aString, 0, nativeRange.mStartOffset));
+      preText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
+                               NS_LITERAL_STRING("\n"));
+      range.mStartOffset = preText.Length();
+    }
+    if (nativeRange.Length() == 0) {
+      range.mEndOffset = range.mStartOffset;
+    } else {
+      nsAutoString clause(
+        Substring(aString, nativeRange.mStartOffset, nativeRange.Length()));
+      clause.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
+                              NS_LITERAL_STRING("\n"));
+      range.mEndOffset = range.mStartOffset + clause.Length();
+    }
+    if (range.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
+      mCaret = range;
+    } else {
+      EnsureClauseArray();
+      mClauses->AppendElement(range);
+    }
+  }
+  return NS_OK;
+}
+
+nsresult
 TextEventDispatcher::PendingComposition::Flush(TextEventDispatcher* aDispatcher,
                                                nsEventStatus& aStatus)
 {
   aStatus = nsEventStatus_eIgnore;
 
   nsresult rv = aDispatcher->GetState();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
--- a/widget/TextEventDispatcher.h
+++ b/widget/TextEventDispatcher.h
@@ -168,16 +168,34 @@ public:
    */
   nsresult SetCaretInPendingComposition(uint32_t aOffset,
                                         uint32_t aLength)
   {
     return mPendingComposition.SetCaret(aOffset, aLength);
   }
 
   /**
+   * SetPendingComposition() is useful if native IME handler already creates
+   * array of clauses and/or caret information.
+   *
+   * @param aString         Composition string.  This may include native line
+   *                        breakers since they will be replaced with XP line
+   *                        breakers automatically.
+   * @param aRanges         This should include the ranges of clauses and/or
+   *                        a range of caret.  Note that this method allows
+   *                        some ranges overlap each other and the range order
+   *                        is not from start to end.
+   */
+  nsresult SetPendingComposition(const nsAString& aString,
+                                 const TextRangeArray* aRanges)
+  {
+    return mPendingComposition.Set(aString, aRanges);
+  }
+
+  /**
    * FlushPendingComposition() sends the pending composition string
    * to the widget of the store DOM window.  Before calling this, IME needs to
    * set pending composition string with SetPendingCompositionString(),
    * AppendClauseToPendingComposition() and/or
    * SetCaretInPendingComposition().
    */
   nsresult FlushPendingComposition(nsEventStatus& aStatus)
   {
@@ -252,16 +270,17 @@ private:
   // automatically.
   class PendingComposition
   {
   public:
     PendingComposition();
     nsresult SetString(const nsAString& aString);
     nsresult AppendClause(uint32_t aLength, uint32_t aAttribute);
     nsresult SetCaret(uint32_t aOffset, uint32_t aLength);
+    nsresult Set(const nsAString& aString, const TextRangeArray* aRanges);
     nsresult Flush(TextEventDispatcher* aDispatcher, nsEventStatus& aStatus);
     void Clear();
 
   private:
     nsString mString;
     RefPtr<TextRangeArray> mClauses;
     TextRange mCaret;