Bug 974318 part.1 Add WidgetTextEvent::mRanges which is an array class of TextRange r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 04 Mar 2014 22:48:26 +0900
changeset 188969 3ea20343a2ce46a27f46599e7744dfe2881150bf
parent 188968 8fbd6850f6a28f98a0f9a394655ace7fb8c24239
child 188970 5abcc356d54aa646eb0461ed4844e358ec728191
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs974318
milestone30.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 974318 part.1 Add WidgetTextEvent::mRanges which is an array class of TextRange r=smaug
dom/base/CompositionStringSynthesizer.cpp
dom/base/CompositionStringSynthesizer.h
dom/events/TextComposition.cpp
dom/events/nsDOMTextEvent.cpp
widget/EventForwards.h
widget/TextEvents.h
widget/TextRange.h
widget/nsGUIEventIPC.h
--- a/dom/base/CompositionStringSynthesizer.cpp
+++ b/dom/base/CompositionStringSynthesizer.cpp
@@ -18,28 +18,29 @@ namespace dom {
 
 NS_IMPL_ISUPPORTS1(CompositionStringSynthesizer,
                    nsICompositionStringSynthesizer)
 
 CompositionStringSynthesizer::CompositionStringSynthesizer(
                                 nsPIDOMWindow* aWindow)
 {
   mWindow = do_GetWeakReference(aWindow);
+  mClauses = new TextRangeArray();
   ClearInternal();
 }
 
 CompositionStringSynthesizer::~CompositionStringSynthesizer()
 {
 }
 
 void
 CompositionStringSynthesizer::ClearInternal()
 {
   mString.Truncate();
-  mClauses.Clear();
+  mClauses->Clear();
   mCaret.mRangeType = 0;
 }
 
 nsIWidget*
 CompositionStringSynthesizer::GetWidget()
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   if (!window) {
@@ -79,20 +80,20 @@ CompositionStringSynthesizer::AppendClau
 
   switch (aAttribute) {
     case ATTR_RAWINPUT:
     case ATTR_SELECTEDRAWTEXT:
     case ATTR_CONVERTEDTEXT:
     case ATTR_SELECTEDCONVERTEDTEXT: {
       TextRange textRange;
       textRange.mStartOffset =
-        mClauses.IsEmpty() ? 0 : mClauses[mClauses.Length() - 1].mEndOffset;
+        mClauses->IsEmpty() ? 0 : mClauses->LastElement().mEndOffset;
       textRange.mEndOffset = textRange.mStartOffset + aLength;
       textRange.mRangeType = aAttribute;
-      mClauses.AppendElement(textRange);
+      mClauses->AppendElement(textRange);
       return NS_OK;
     }
     default:
       return NS_ERROR_INVALID_ARG;
   }
 }
 
 NS_IMETHODIMP
@@ -113,37 +114,37 @@ CompositionStringSynthesizer::DispatchEv
   NS_ENSURE_ARG_POINTER(aDefaultPrevented);
   nsCOMPtr<nsIWidget> widget = GetWidget();
   NS_ENSURE_TRUE(widget && !widget->Destroyed(), NS_ERROR_NOT_AVAILABLE);
 
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  if (!mClauses.IsEmpty() &&
-      mClauses[mClauses.Length()-1].mEndOffset != mString.Length()) {
+  if (!mClauses->IsEmpty() &&
+      mClauses->LastElement().mEndOffset != mString.Length()) {
     NS_WARNING("Sum of length of the all clauses must be same as the string "
                "length");
     ClearInternal();
     return NS_ERROR_ILLEGAL_VALUE;
   }
   if (mCaret.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
     if (mCaret.mEndOffset > mString.Length()) {
       NS_WARNING("Caret position is out of the composition string");
       ClearInternal();
       return NS_ERROR_ILLEGAL_VALUE;
     }
-    mClauses.AppendElement(mCaret);
+    mClauses->AppendElement(mCaret);
   }
 
   WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
   textEvent.time = PR_IntervalNow();
   textEvent.theText = mString;
-  textEvent.rangeCount = mClauses.Length();
-  textEvent.rangeArray = mClauses.Elements();
+  textEvent.rangeCount = mClauses->Length();
+  textEvent.rangeArray = mClauses->Elements();
 
   // XXX How should we set false for this on b2g?
   textEvent.mFlags.mIsSynthesizedForTests = true;
 
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv = widget->DispatchEvent(&textEvent, status);
   *aDefaultPrevented = (status == nsEventStatus_eConsumeNoDefault);
 
--- a/dom/base/CompositionStringSynthesizer.h
+++ b/dom/base/CompositionStringSynthesizer.h
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_compositionstringsynthesizer_h__
 #define mozilla_dom_compositionstringsynthesizer_h__
 
 #include "nsICompositionStringSynthesizer.h"
 #include "nsString.h"
-#include "nsTArray.h"
 #include "nsWeakReference.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TextRange.h"
 
 class nsIWidget;
 class nsPIDOMWindow;
 
 namespace mozilla {
@@ -27,17 +26,17 @@ public:
   ~CompositionStringSynthesizer();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOMPOSITIONSTRINGSYNTHESIZER
 
 private:
   nsWeakPtr mWindow; // refers an instance of nsPIDOMWindow
   nsString mString;
-  nsAutoTArray<TextRange, 10> mClauses;
+  nsRefPtr<TextRangeArray> mClauses;
   TextRange mCaret;
 
   nsIWidget* GetWidget();
   void ClearInternal();
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -108,27 +108,18 @@ TextComposition::NotityUpdateComposition
       // Unknown offset
       NS_WARNING("Cannot get start offset of IME composition");
       mCompositionStartOffset = 0;
     }
     mCompositionTargetOffset = mCompositionStartOffset;
   } else if (aEvent->eventStructType != NS_TEXT_EVENT) {
     return;
   } else {
-    WidgetTextEvent* textEvent = aEvent->AsTextEvent();
-    mCompositionTargetOffset = mCompositionStartOffset;
-
-    for (uint32_t i = 0; i < textEvent->rangeCount; i++) {
-      TextRange& range = textEvent->rangeArray[i];
-      if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT ||
-          range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) {
-        mCompositionTargetOffset += range.mStartOffset;
-        break;
-      }
-    }
+    mCompositionTargetOffset =
+      mCompositionStartOffset + aEvent->AsTextEvent()->TargetClauseOffset();
   }
 
   NotifyIME(NOTIFY_IME_OF_COMPOSITION_UPDATE);
 }
 
 void
 TextComposition::DispatchCompositionEventRunnable(uint32_t aEventMessage,
                                                   const nsAString& aData)
--- a/dom/events/nsDOMTextEvent.cpp
+++ b/dom/events/nsDOMTextEvent.cpp
@@ -34,23 +34,23 @@ nsDOMTextEvent::nsDOMTextEvent(mozilla::
   WidgetTextEvent* te = mEvent->AsTextEvent();
   mText = te->theText;
 
   //
   // build the range list -- ranges need to be DOM-ified since the
   // IME transaction will hold a ref, the widget representation
   // isn't persistent
   //
-  mTextRange = new nsPrivateTextRangeList(te->rangeCount);
+  mTextRange = new nsPrivateTextRangeList(te->RangeCount());
   if (mTextRange) {
     uint16_t i;
 
     for(i = 0; i < te->rangeCount; i++) {
       nsRefPtr<nsPrivateTextRange> tempPrivateTextRange = new
-        nsPrivateTextRange(te->rangeArray[i]);
+        nsPrivateTextRange(te->mRanges->ElementAt(i));
 
       if (tempPrivateTextRange) {
         mTextRange->AppendTextRange(tempPrivateTextRange);
       }
     }
   }
 }
 
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -64,13 +64,13 @@ struct EventFlags;
 
 // TextEvents.h
 struct AlternativeCharCode;
 
 // TextRange.h
 struct TextRangeStyle;
 struct TextRange;
 
-typedef TextRange* TextRangeArray;
+class TextRangeArray;
 
 } // namespace mozilla
 
 #endif // mozilla_EventForwards_h__
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -216,40 +216,63 @@ public:
   // The composition string or the commit string.
   nsString theText;
   // Count of rangeArray.
   uint32_t rangeCount;
   // Pointer to the first item of the ranges (clauses).
   // Note that the range array may not specify a caret position; in that
   // case there will be no range of type NS_TEXTRANGE_CARETPOSITION in the
   // array.
-  TextRangeArray rangeArray;
+  TextRange* rangeArray;
   // Indicates whether the event signifies printable text.
   // XXX This is not a standard, and most platforms don't set this properly.
   //     So, perhaps, we can get rid of this.
   bool isChar;
 
+  nsRefPtr<TextRangeArray> mRanges;
+
   void AssignTextEventData(const WidgetTextEvent& aEvent, bool aCopyTargets)
   {
     AssignGUIEventData(aEvent, aCopyTargets);
 
     isChar = aEvent.isChar;
 
     // Currently, we don't need to copy the other members because they are
     // for internal use only (not available from JS).
   }
 
+  // XXX This copies all ranges from legacy member to new member.
+  //     This will be removed later.
+  void EnsureRanges()
+  {
+    if (mRanges || !rangeCount) {
+      return;
+    }
+    mRanges = new TextRangeArray();
+    for (uint32_t i = 0; i < rangeCount; i++) {
+      mRanges->AppendElement(rangeArray[i]);
+    }
+  }
+
   bool IsComposing() const
   {
-    for (uint32_t i = 0; i < rangeCount; i++) {
-      if (rangeArray[i].IsClause()) {
-        return true;
-      }
-    }
-    return false;
+    const_cast<WidgetTextEvent*>(this)->EnsureRanges();
+    return mRanges && mRanges->IsComposing();
+  }
+
+  uint32_t TargetClauseOffset() const
+  {
+    const_cast<WidgetTextEvent*>(this)->EnsureRanges();
+    return mRanges ? mRanges->TargetClauseOffset() : 0;
+  }
+
+  uint32_t RangeCount() const
+  {
+    const_cast<WidgetTextEvent*>(this)->EnsureRanges();
+    return mRanges ? mRanges->Length() : 0;
   }
 };
 
 /******************************************************************************
  * mozilla::WidgetCompositionEvent
  ******************************************************************************/
 
 class WidgetCompositionEvent : public WidgetGUIEvent
--- a/widget/TextRange.h
+++ b/widget/TextRange.h
@@ -3,18 +3,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_TextRage_h_
 #define mozilla_TextRage_h_
 
 #include <stdint.h>
 
+#include "nsAutoPtr.h"
 #include "nsColor.h"
 #include "nsStyleConsts.h"
+#include "nsTArray.h"
 
 namespace mozilla {
 
 /******************************************************************************
  * mozilla::TextRangeStyle
  ******************************************************************************/
 
 struct TextRangeStyle
@@ -154,17 +156,42 @@ struct TextRange
                  mRangeType <= NS_TEXTRANGE_SELECTEDCONVERTEDTEXT,
                "Invalid range type");
     return mRangeType != NS_TEXTRANGE_CARETPOSITION;
   }
 };
 
 /******************************************************************************
  * mozilla::TextRangeArray
- *
- * XXX This should be replaced with nsTArray<TextRange>.
  ******************************************************************************/
+class TextRangeArray MOZ_FINAL : public nsAutoTArray<TextRange, 10>
+{
+  NS_INLINE_DECL_REFCOUNTING(TextRangeArray)
 
-typedef TextRange* TextRangeArray;
+public:
+  bool IsComposing() const
+  {
+    for (uint32_t i = 0; i < Length(); ++i) {
+      if (ElementAt(i).IsClause()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Returns target clase offset.  If there are selected clauses, this returns
+  // the first selected clause offset.  Otherwise, 0.
+  uint32_t TargetClauseOffset() const
+  {
+    for (uint32_t i = 0; i < Length(); ++i) {
+      const TextRange& range = ElementAt(i);
+      if (range.mRangeType == NS_TEXTRANGE_SELECTEDRAWTEXT ||
+          range.mRangeType == NS_TEXTRANGE_SELECTEDCONVERTEDTEXT) {
+        return range.mStartOffset;
+      }
+    }
+    return 0;
+  }
+};
 
 } // namespace mozilla
 
 #endif // mozilla_TextRage_h_
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -374,55 +374,107 @@ struct ParamTraits<mozilla::TextRange>
     return ReadParam(aMsg, aIter, &aResult->mStartOffset) &&
            ReadParam(aMsg, aIter, &aResult->mEndOffset) &&
            ReadParam(aMsg, aIter, &aResult->mRangeType) &&
            ReadParam(aMsg, aIter, &aResult->mRangeStyle);
   }
 };
 
 template<>
+struct ParamTraits<mozilla::TextRangeArray>
+{
+  typedef mozilla::TextRangeArray paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.Length());
+    for (uint32_t index = 0; index < aParam.Length(); index++) {
+      WriteParam(aMsg, aParam[index]);
+    }
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    uint32_t length;
+    if (!ReadParam(aMsg, aIter, &length)) {
+      return false;
+    }
+    for (uint32_t index = 0; index < length; index++) {
+      mozilla::TextRange textRange;
+      if (!ReadParam(aMsg, aIter, &textRange)) {
+        aResult->Clear();
+        return false;
+      }
+      aResult->AppendElement(textRange);
+    }
+    return true;
+  }
+};
+
+template<>
 struct ParamTraits<mozilla::WidgetTextEvent>
 {
   typedef mozilla::WidgetTextEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetGUIEvent>(aParam));
     WriteParam(aMsg, aParam.mSeqno);
     WriteParam(aMsg, aParam.theText);
     WriteParam(aMsg, aParam.isChar);
     WriteParam(aMsg, aParam.rangeCount);
+    bool hasRanges = !!aParam.mRanges;
+    WriteParam(aMsg, hasRanges);
     for (uint32_t index = 0; index < aParam.rangeCount; index++)
       WriteParam(aMsg, aParam.rangeArray[index]);
+    if (hasRanges) {
+      WriteParam(aMsg, *aParam.mRanges.get());
+    }
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
+    bool hasRanges;
     if (!ReadParam(aMsg, aIter,
                    static_cast<mozilla::WidgetGUIEvent*>(aResult)) ||
         !ReadParam(aMsg, aIter, &aResult->mSeqno) ||
         !ReadParam(aMsg, aIter, &aResult->theText) ||
         !ReadParam(aMsg, aIter, &aResult->isChar) ||
-        !ReadParam(aMsg, aIter, &aResult->rangeCount))
+        !ReadParam(aMsg, aIter, &aResult->rangeCount) ||
+        !ReadParam(aMsg, aIter, &hasRanges)) {
       return false;
+    }
 
     if (!aResult->rangeCount) {
       aResult->rangeArray = nullptr;
-      return true;
+    } else {
+      aResult->rangeArray = new mozilla::TextRange[aResult->rangeCount];
+      if (!aResult->rangeArray) {
+        return false;
+      }
+
+      for (uint32_t index = 0; index < aResult->rangeCount; index++) {
+        if (!ReadParam(aMsg, aIter, &aResult->rangeArray[index])) {
+          Free(*aResult);
+          return false;
+        }
+      }
     }
 
-    aResult->rangeArray = new mozilla::TextRange[aResult->rangeCount];
-    if (!aResult->rangeArray)
-      return false;
-
-    for (uint32_t index = 0; index < aResult->rangeCount; index++)
-      if (!ReadParam(aMsg, aIter, &aResult->rangeArray[index])) {
-        Free(*aResult);
+    if (!hasRanges) {
+      aResult->mRanges = nullptr;
+    } else {
+      aResult->mRanges = new mozilla::TextRangeArray();
+      if (!aResult->mRanges) {
         return false;
       }
+      if (!ReadParam(aMsg, aIter, aResult->mRanges.get())) {
+        return false;
+      }
+    }
     return true;
   }
 
   static void Free(const paramType& aResult)
   {
     if (aResult.rangeArray)
       delete [] aResult.rangeArray;
   }