Bug 1310912 - Part 4. RangeUpdater should be called on DoTransaction. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Sat, 12 Nov 2016 14:56:33 +0900
changeset 365176 62a4cc7525bce189c40d69b630c79f1e3dce92a3
parent 365175 6e763c7787816780d2be2100310ca6eea5e4fdbf
child 365177 856c6ccb09a1295222fbd62b67d03a85c76a5f98
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-beta@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1310912
milestone52.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 1310912 - Part 4. RangeUpdater should be called on DoTransaction. r=masayuki Although PlaceholderTransaction will use the selection on Merge, it is too late to use UpdateRange. Because RangeUpdater will be used after DoTransaction is finished. So we should update selection on DoTransaction. Also, part 1 fix doesn't update selection correctly via RangeUpdater when IME composition is multiple node. MozReview-Commit-ID: 9so9tR8uQ6t
editor/libeditor/CompositionTransaction.cpp
editor/libeditor/CompositionTransaction.h
editor/libeditor/EditorBase.cpp
editor/libeditor/InsertTextTransaction.cpp
editor/libeditor/InsertTextTransaction.h
--- a/editor/libeditor/CompositionTransaction.cpp
+++ b/editor/libeditor/CompositionTransaction.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "CompositionTransaction.h"
 
 #include "mozilla/EditorBase.h"         // mEditorBase
+#include "mozilla/SelectionState.h"     // RangeUpdater
 #include "mozilla/dom/Selection.h"      // local var
 #include "mozilla/dom/Text.h"           // mTextNode
 #include "nsAString.h"                  // params
 #include "nsDebug.h"                    // for NS_ASSERTION, etc
 #include "nsError.h"                    // for NS_SUCCEEDED, NS_FAILED, etc
 #include "nsIPresShell.h"               // nsISelectionController constants
 #include "nsRange.h"                    // local var
 #include "nsQueryObject.h"              // for do_QueryObject
@@ -20,23 +21,25 @@ namespace mozilla {
 using namespace dom;
 
 CompositionTransaction::CompositionTransaction(
                           Text& aTextNode,
                           uint32_t aOffset,
                           uint32_t aReplaceLength,
                           TextRangeArray* aTextRangeArray,
                           const nsAString& aStringToInsert,
-                          EditorBase& aEditorBase)
+                          EditorBase& aEditorBase,
+                          RangeUpdater* aRangeUpdater)
   : mTextNode(&aTextNode)
   , mOffset(aOffset)
   , mReplaceLength(aReplaceLength)
   , mRanges(aTextRangeArray)
   , mStringToInsert(aStringToInsert)
   , mEditorBase(aEditorBase)
+  , mRangeUpdater(aRangeUpdater)
   , mFixed(false)
 {
   MOZ_ASSERT(mTextNode->TextLength() >= mOffset);
 }
 
 CompositionTransaction::~CompositionTransaction()
 {
 }
@@ -63,34 +66,38 @@ CompositionTransaction::DoTransaction()
   NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
 
   // Advance caret: This requires the presentation shell to get the selection.
   if (mReplaceLength == 0) {
     nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+    mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
   } else {
     uint32_t replaceableLength = mTextNode->TextLength() - mOffset;
     nsresult rv =
       mTextNode->ReplaceData(mOffset, mReplaceLength, mStringToInsert);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+    mRangeUpdater->SelAdjDeleteText(mTextNode, mOffset, mReplaceLength);
+    mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
 
     // If IME text node is multiple node, ReplaceData doesn't remove all IME
     // text.  So we need remove remained text into other text node.
     if (replaceableLength < mReplaceLength) {
       int32_t remainLength = mReplaceLength - replaceableLength;
       nsCOMPtr<nsINode> node = mTextNode->GetNextSibling();
       while (node && node->IsNodeOfType(nsINode::eTEXT) &&
              remainLength > 0) {
         Text* text = static_cast<Text*>(node.get());
         uint32_t textLength = text->TextLength();
         text->DeleteData(0, remainLength);
+        mRangeUpdater->SelAdjDeleteText(text, 0, remainLength);
         remainLength -= textLength;
         node = node->GetNextSibling();
       }
     }
   }
 
   nsresult rv = SetSelectionForRanges();
   NS_ENSURE_SUCCESS(rv, rv);
--- a/editor/libeditor/CompositionTransaction.h
+++ b/editor/libeditor/CompositionTransaction.h
@@ -12,16 +12,17 @@
 
 #define NS_IMETEXTTXN_IID \
   { 0xb391355d, 0x346c, 0x43d1, \
     { 0x85, 0xed, 0x9e, 0x65, 0xbe, 0xe7, 0x7e, 0x48 } }
 
 namespace mozilla {
 
 class EditorBase;
+class RangeUpdater;
 class TextRangeArray;
 
 namespace dom {
 class Text;
 } // namespace dom
 
 /**
  * CompositionTransaction stores all edit for a composition, i.e.,
@@ -38,22 +39,24 @@ public:
    * @param aTextNode           The start node of text content.
    * @param aOffset             The location in aTextNode to do the insertion.
    * @param aReplaceLength      The length of text to replace. 0 means not
    *                            replacing existing text.
    * @param aTextRangeArray     Clauses and/or caret information. This may be
    *                            null.
    * @param aString             The new text to insert.
    * @param aEditorBase         Used to get and set the selection.
+   * @param aRangeUpdater       The range updater
    */
   CompositionTransaction(dom::Text& aTextNode,
                          uint32_t aOffset, uint32_t aReplaceLength,
                          TextRangeArray* aTextRangeArray,
                          const nsAString& aString,
-                         EditorBase& aEditorBase);
+                         EditorBase& aEditorBase,
+                         RangeUpdater* aRangeUpdater);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CompositionTransaction,
                                            EditTransactionBase)
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_EDITTRANSACTIONBASE
 
@@ -84,16 +87,18 @@ private:
   RefPtr<TextRangeArray> mRanges;
 
   // The text to insert into mTextNode at mOffset.
   nsString mStringToInsert;
 
   // The editor, which is used to get the selection controller.
   EditorBase& mEditorBase;
 
+  RangeUpdater* mRangeUpdater;
+
   bool mFixed;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(CompositionTransaction, NS_IMETEXTTXN_IID)
 
 } // namespace mozilla
 
 #endif // #ifndef CompositionTransaction_h
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2434,17 +2434,16 @@ nsresult
 EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
                                        Text& aTextNode,
                                        int32_t aOffset,
                                        bool aSuppressIME)
 {
   RefPtr<EditTransactionBase> transaction;
   bool isIMETransaction = false;
   int32_t replacedOffset = 0;
-  int32_t replacedLength = 0;
   // aSuppressIME is used when editor must insert text, yet this text is not
   // part of the current IME operation. Example: adjusting whitespace around an
   // IME insertion.
   if (ShouldHandleIMEComposition() && !aSuppressIME) {
     if (!mIMETextNode) {
       mIMETextNode = &aTextNode;
       mIMETextOffset = aOffset;
     }
@@ -2465,17 +2464,16 @@ EditorBase::InsertTextIntoTextNodeImpl(c
     }
 
     transaction = CreateTxnForComposition(aStringToInsert);
     isIMETransaction = true;
     // All characters of the composition string will be replaced with
     // aStringToInsert.  So, we need to emulate to remove the composition
     // string.
     replacedOffset = mIMETextOffset;
-    replacedLength = mIMETextLength;
     mIMETextLength = aStringToInsert.Length();
   } else {
     transaction = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset);
   }
 
   // Let listeners know what's up
   for (auto& listener : mActionListeners) {
     listener->WillInsertText(
@@ -2484,23 +2482,16 @@ EditorBase::InsertTextIntoTextNodeImpl(c
   }
 
   // XXX We may not need these view batches anymore.  This is handled at a
   // higher level now I believe.
   BeginUpdateViewBatch();
   nsresult rv = DoTransaction(transaction);
   EndUpdateViewBatch();
 
-  if (replacedLength) {
-    mRangeUpdater.SelAdjDeleteText(
-      static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
-      replacedOffset, replacedLength);
-  }
-  mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert);
-
   // let listeners know what happened
   for (auto& listener : mActionListeners) {
     listener->DidInsertText(
       static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
       aOffset, aStringToInsert, rv);
   }
 
   // Added some cruft here for bug 43366.  Layout was crashing because we left
@@ -2612,17 +2603,18 @@ EditorBase::NotifyDocumentListeners(
 }
 
 already_AddRefed<InsertTextTransaction>
 EditorBase::CreateTxnForInsertText(const nsAString& aStringToInsert,
                                    Text& aTextNode,
                                    int32_t aOffset)
 {
   RefPtr<InsertTextTransaction> transaction =
-    new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this);
+    new InsertTextTransaction(aTextNode, aOffset, aStringToInsert, *this,
+                              &mRangeUpdater);
   return transaction.forget();
 }
 
 nsresult
 EditorBase::DeleteText(nsGenericDOMDataNode& aCharData,
                        uint32_t aOffset,
                        uint32_t aLength)
 {
@@ -4242,17 +4234,17 @@ EditorBase::CreateTxnForComposition(cons
 {
   MOZ_ASSERT(mIMETextNode);
   // During handling IME composition, mComposition must have been initialized.
   // TODO: We can simplify CompositionTransaction::Init() with TextComposition
   //       class.
   RefPtr<CompositionTransaction> transaction =
     new CompositionTransaction(*mIMETextNode, mIMETextOffset, mIMETextLength,
                                mComposition->GetRanges(), aStringToInsert,
-                               *this);
+                               *this, &mRangeUpdater);
   return transaction.forget();
 }
 
 NS_IMETHODIMP
 EditorBase::CreateTxnForAddStyleSheet(StyleSheet* aSheet,
                                       AddStyleSheetTransaction** aTransaction)
 {
   RefPtr<AddStyleSheetTransaction> transaction = new AddStyleSheetTransaction();
--- a/editor/libeditor/InsertTextTransaction.cpp
+++ b/editor/libeditor/InsertTextTransaction.cpp
@@ -1,35 +1,38 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "InsertTextTransaction.h"
 
 #include "mozilla/EditorBase.h"         // mEditorBase
+#include "mozilla/SelectionState.h"     // RangeUpdater
 #include "mozilla/dom/Selection.h"      // Selection local var
 #include "mozilla/dom/Text.h"           // mTextNode
 #include "nsAString.h"                  // nsAString parameter
 #include "nsDebug.h"                    // for NS_ASSERTION, etc.
 #include "nsError.h"                    // for NS_OK, etc.
 #include "nsQueryObject.h"              // for do_QueryObject
 
 namespace mozilla {
 
 using namespace dom;
 
 InsertTextTransaction::InsertTextTransaction(Text& aTextNode,
                                              uint32_t aOffset,
                                              const nsAString& aStringToInsert,
-                                             EditorBase& aEditorBase)
+                                             EditorBase& aEditorBase,
+                                             RangeUpdater* aRangeUpdater)
   : mTextNode(&aTextNode)
   , mOffset(aOffset)
   , mStringToInsert(aStringToInsert)
   , mEditorBase(aEditorBase)
+  , mRangeUpdater(aRangeUpdater)
 {
 }
 
 InsertTextTransaction::~InsertTextTransaction()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
@@ -56,16 +59,17 @@ InsertTextTransaction::DoTransaction()
     NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
     DebugOnly<nsresult> rv =
       selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());
     NS_ASSERTION(NS_SUCCEEDED(rv),
                  "Selection could not be collapsed after insert");
   } else {
     // Do nothing - DOM Range gravity will adjust selection
   }
+  mRangeUpdater->SelAdjInsertText(*mTextNode, mOffset, mStringToInsert);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InsertTextTransaction::UndoTransaction()
 {
   return mTextNode->DeleteData(mOffset, mStringToInsert.Length());
--- a/editor/libeditor/InsertTextTransaction.h
+++ b/editor/libeditor/InsertTextTransaction.h
@@ -17,16 +17,18 @@ class nsITransaction;
 
 #define NS_INSERTTEXTTXN_IID \
 { 0x8c9ad77f, 0x22a7, 0x4d01, \
   { 0xb1, 0x59, 0x8a, 0x0f, 0xdb, 0x1d, 0x08, 0xe9 } }
 
 namespace mozilla {
 
 class EditorBase;
+class RangeUpdater;
+
 namespace dom {
 class Text;
 } // namespace dom
 
 /**
  * A transaction that inserts text into a content node.
  */
 class InsertTextTransaction final : public EditTransactionBase
@@ -34,19 +36,21 @@ class InsertTextTransaction final : publ
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INSERTTEXTTXN_IID)
 
   /**
    * @param aElement        The text content node.
    * @param aOffset         The location in aElement to do the insertion.
    * @param aString         The new text to insert.
    * @param aPresShell      Used to get and set the selection.
+   * @param aRangeUpdater   The range updater
    */
   InsertTextTransaction(dom::Text& aTextNode, uint32_t aOffset,
-                        const nsAString& aString, EditorBase& aEditorBase);
+                        const nsAString& aString, EditorBase& aEditorBase,
+                        RangeUpdater* aRangeUpdater);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InsertTextTransaction,
                                            EditTransactionBase)
 
   NS_DECL_EDITTRANSACTIONBASE
 
   NS_IMETHOD Merge(nsITransaction* aTransaction, bool* aDidMerge) override;
@@ -68,15 +72,17 @@ private:
   // The offset into mTextNode where the insertion is to take place.
   uint32_t mOffset;
 
   // The text to insert into mTextNode at mOffset.
   nsString mStringToInsert;
 
   // The editor, which we'll need to get the selection.
   EditorBase& mEditorBase;
+
+  RangeUpdater* mRangeUpdater;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(InsertTextTransaction, NS_INSERTTEXTTXN_IID)
 
 } // namespace mozilla
 
 #endif // #ifndef InsertTextTransaction_h