Bug 960866 part.3 Remove nsEditor::mIsIMEComposing r=ehsan+smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 12 Feb 2014 22:02:56 +0900
changeset 186592 984a2e65a52f7c22056381683e3b103644d1e137
parent 186591 41d17ebf8454c296b26991963887db13ae0758c5
child 186593 5159f90e44eff593513507f74fc496648ced101b
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs960866
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 960866 part.3 Remove nsEditor::mIsIMEComposing r=ehsan+smaug
dom/events/TextComposition.cpp
dom/events/TextComposition.h
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/text/moz.build
editor/libeditor/text/nsPlaintextEditor.cpp
widget/TextEvents.h
widget/TextRange.h
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -22,17 +22,18 @@ namespace mozilla {
  ******************************************************************************/
 
 TextComposition::TextComposition(nsPresContext* aPresContext,
                                  nsINode* aNode,
                                  WidgetGUIEvent* aEvent) :
   mPresContext(aPresContext), mNode(aNode),
   mNativeContext(aEvent->widget->GetInputContext().mNativeIMEContext),
   mCompositionStartOffset(0), mCompositionTargetOffset(0),
-  mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests)
+  mIsSynthesizedForTests(aEvent->mFlags.mIsSynthesizedForTests),
+  mIsComposing(false)
 {
 }
 
 bool
 TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
 {
   return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
 }
@@ -44,16 +45,18 @@ TextComposition::DispatchEvent(WidgetGUI
 {
   if (aEvent->message == NS_COMPOSITION_UPDATE) {
     mLastData = aEvent->AsCompositionEvent()->data;
   }
 
   nsEventDispatcher::Dispatch(mNode, mPresContext,
                               aEvent, nullptr, aStatus, aCallBack);
 
+  MOZ_ASSERT_IF(aEvent->message == NS_COMPOSITION_END, !mIsComposing);
+
   // Notify composition update to widget if possible
   NotityUpdateComposition(aEvent);
 }
 
 void
 TextComposition::NotityUpdateComposition(WidgetGUIEvent* aEvent)
 {
   nsEventStatus status;
@@ -118,16 +121,22 @@ TextComposition::SynthesizeCommit(bool a
 
 nsresult
 TextComposition::NotifyIME(widget::NotificationToIME aNotification)
 {
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
   return nsIMEStateManager::NotifyIME(aNotification, mPresContext);
 }
 
+void
+TextComposition::EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent)
+{
+  mIsComposing = aTextEvent->IsComposing();
+}
+
 /******************************************************************************
  * TextComposition::CompositionEventDispatcher
  ******************************************************************************/
 
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
                                                nsPresContext* aPresContext,
                                                nsINode* aEventTarget,
                                                uint32_t aEventMessage,
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -68,16 +68,28 @@ public:
    */
   nsresult NotifyIME(widget::NotificationToIME aNotification);
 
   /**
    * the offset of first selected clause or start of of compositon
    */
   uint32_t OffsetOfTargetClause() const { return mCompositionTargetOffset; }
 
+  /**
+   * Returns true if there is non-empty composition string and it's not fixed.
+   * Otherwise, false.
+   */
+  bool IsComposing() const { return mIsComposing; }
+
+  /**
+   * EditorWillHandleTextEvent() must be called before the focused editor
+   * handles the text event.
+   */
+  void EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent);
+
 private:
   // This class holds nsPresContext weak.  This instance shouldn't block
   // destroying it.  When the presContext is being destroyed, it's notified to
   // nsIMEStateManager::OnDestroyPresContext(), and then, it destroy
   // this instance.
   nsPresContext* mPresContext;
   nsCOMPtr<nsINode> mNode;
 
@@ -93,16 +105,19 @@ private:
   uint32_t mCompositionStartOffset;
   // Offset of the selected clause of the composition string from start of the
   // editor
   uint32_t mCompositionTargetOffset;
 
   // See the comment for IsSynthesizedForTests().
   bool mIsSynthesizedForTests;
 
+  // See the comment for IsComposing().
+  bool mIsComposing;
+
   // Hide the default constructor and copy constructor.
   TextComposition() {}
   TextComposition(const TextComposition& aOther);
 
 
   /**
    * DispatchEvent() dispatches the aEvent to the mContent synchronously.
    * The caller must ensure that it's safe to dispatch the event.
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -139,17 +139,16 @@ nsEditor::nsEditor()
 ,  mUpdateCount(0)
 ,  mPlaceHolderBatch(0)
 ,  mAction(EditAction::none)
 ,  mIMETextOffset(0)
 ,  mIMEBufferLength(0)
 ,  mDirection(eNone)
 ,  mDocDirtyState(-1)
 ,  mSpellcheckCheckboxState(eTriUnset)
-,  mIsIMEComposing(false)
 ,  mShouldTxnSetSelection(true)
 ,  mDidPreDestroy(false)
 ,  mDidPostCreate(false)
 ,  mDispatchInputEvent(true)
 {
 }
 
 nsEditor::~nsEditor()
@@ -2053,17 +2052,16 @@ nsEditor::EndIMEComposition()
                    "nsIAbsorbingTransaction::Commit() failed");
     }
   }
 
   /* reset the data we need to construct a transaction */
   mIMETextNode = nullptr;
   mIMETextOffset = 0;
   mIMEBufferLength = 0;
-  mIsIMEComposing = false;
   mComposition = nullptr;
 
   // notify editor observers of action
   NotifyEditorObservers();
 }
 
 
 NS_IMETHODIMP
@@ -4196,49 +4194,20 @@ nsEditor::DeleteSelectionAndCreateNode(c
 /* Non-interface, protected methods */
 
 int32_t
 nsEditor::GetIMEBufferLength()
 {
   return mIMEBufferLength;
 }
 
-void
-nsEditor::SetIsIMEComposing(){  
-  // We set mIsIMEComposing according to mIMETextRangeList.
-  nsCOMPtr<nsIPrivateTextRange> rangePtr;
-  uint16_t listlen, type;
-
-  mIsIMEComposing = false;
-  listlen = mIMETextRangeList->GetLength();
-
-  for (uint16_t i = 0; i < listlen; i++)
-  {
-      rangePtr = mIMETextRangeList->Item(i);
-      if (!rangePtr) continue;
-      nsresult result = rangePtr->GetRangeType(&type);
-      if (NS_FAILED(result)) continue;
-      if ( type == nsIPrivateTextRange::TEXTRANGE_RAWINPUT ||
-           type == nsIPrivateTextRange::TEXTRANGE_CONVERTEDTEXT ||
-           type == nsIPrivateTextRange::TEXTRANGE_SELECTEDRAWTEXT ||
-           type == nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT )
-      {
-        mIsIMEComposing = true;
-#ifdef DEBUG_IME
-        printf("nsEditor::mIsIMEComposing = true\n");
-#endif
-        break;
-      }
-  }
-  return;
-}
-
 bool
-nsEditor::IsIMEComposing() {
-  return mIsIMEComposing;
+nsEditor::IsIMEComposing() const
+{
+  return mComposition && mComposition->IsComposing();
 }
 
 nsresult
 nsEditor::DeleteSelectionAndPrepareToCreateNode()
 {
   nsresult res;
   nsRefPtr<Selection> selection = GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -595,18 +595,20 @@ public:
 
   /** counts number of editable child nodes */
   uint32_t CountEditableChildren(nsINode* aNode);
   
   /** Find the deep first and last children. */
   nsINode* GetFirstEditableNode(nsINode* aRoot);
 
   int32_t GetIMEBufferLength();
-  bool IsIMEComposing();    /* test if IME is in composition state */
-  void SetIsIMEComposing(); /* call this before |IsIMEComposing()| */
+  /**
+   * Returns true if there is composition string and not fixed.
+   */
+  bool IsIMEComposing() const;
 
   /** from html rules code - migration in progress */
   static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
   static nsIAtom *GetTag(nsIDOMNode *aNode);
 
   bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
   virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
 
@@ -859,18 +861,16 @@ protected:
 
   uint32_t          mIMETextOffset;    // offset in text node where IME comp string begins
   uint32_t          mIMEBufferLength;  // current length of IME comp string
 
   EDirection        mDirection;          // the current direction of editor action
   int8_t            mDocDirtyState;      // -1 = not initialized
   uint8_t           mSpellcheckCheckboxState; // a Tristate value
 
-  bool mIsIMEComposing;   // is IME in composition state?
-
   bool mShouldTxnSetSelection;  // turn off for conservative selection adjustment by txns
   bool mDidPreDestroy;    // whether PreDestroy has been called
   bool mDidPostCreate;    // whether PostCreate has been called
   bool mDispatchInputEvent;
 
   friend bool NSCanUnload(nsISupports* serviceMgr);
   friend class nsAutoTxnsConserveSelection;
   friend class nsAutoSelectionReset;
--- a/editor/libeditor/text/moz.build
+++ b/editor/libeditor/text/moz.build
@@ -15,12 +15,13 @@ UNIFIED_SOURCES += [
     'nsTextEditUtils.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
     '/content/base/src',
+    '/dom/events',
     '/editor/txmgr/src',
 ]
 
 FINAL_LIBRARY = 'gklayout'
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -1,14 +1,15 @@
 /* -*- 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 "TextComposition.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Selection.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/mozalloc.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
@@ -843,44 +844,45 @@ nsPlaintextEditor::UpdateIMEComposition(
   NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
 
   nsCOMPtr<nsISelection> selection;
   nsresult rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<nsCaret> caretP = ps->GetCaret();
 
-  // Update information of clauses in the new composition string.
-  // This will be refered by followed methods.
   nsCOMPtr<nsIPrivateTextEvent> privateTextEvent =
     do_QueryInterface(aDOMTextEvent);
   NS_ENSURE_TRUE(privateTextEvent, NS_ERROR_INVALID_ARG);
+
+  // XXX This approach is ugly, we should sort out the text event handling.
+  mComposition->EditorWillHandleTextEvent(widgetTextEvent);
+
+  // Update information of clauses in the new composition string.
+  // This will be refered by followed methods.
   mIMETextRangeList = privateTextEvent->GetInputRange();
   NS_ABORT_IF_FALSE(mIMETextRangeList, "mIMETextRangeList must not be nullptr");
 
-  // We set mIsIMEComposing properly.
-  SetIsIMEComposing();
-
   {
     nsAutoPlaceHolderBatch batch(this, nsGkAtoms::IMETxnName);
 
     rv = InsertText(widgetTextEvent->theText);
 
     mIMEBufferLength = widgetTextEvent->theText.Length();
 
     if (caretP) {
       caretP->SetCaretDOMSelection(selection);
     }
   }
 
   // If still composing, we should fire input event via observer.
   // Note that if committed, we don't need to notify it since it will be
   // notified at followed compositionend event.
   // NOTE: We must notify after the auto batch will be gone.
-  if (mIsIMEComposing) {
+  if (IsIMEComposing()) {
     NotifyEditorObservers();
   }
 
   return rv;
 }
 
 already_AddRefed<nsIContent>
 nsPlaintextEditor::GetInputEventTargetContent()
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -231,16 +231,26 @@ public:
   {
     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).
   }
+
+  bool IsComposing() const
+  {
+    for (uint32_t i = 0; i < rangeCount; i++) {
+      if (rangeArray[i].IsClause()) {
+        return true;
+      }
+    }
+    return false;
+  }
 };
 
 /******************************************************************************
  * mozilla::WidgetCompositionEvent
  ******************************************************************************/
 
 class WidgetCompositionEvent : public WidgetGUIEvent
 {
--- a/widget/TextRange.h
+++ b/widget/TextRange.h
@@ -142,16 +142,24 @@ struct TextRange
   // XXX Storing end offset makes the initializing code very complicated.
   //     We should replace it with mLength.
   uint32_t mEndOffset;
   uint32_t mRangeType;
 
   TextRangeStyle mRangeStyle;
 
   uint32_t Length() const { return mEndOffset - mStartOffset; }
+
+  bool IsClause() const
+  {
+    MOZ_ASSERT(mRangeType >= NS_TEXTRANGE_CARETPOSITION &&
+                 mRangeType <= NS_TEXTRANGE_SELECTEDCONVERTEDTEXT,
+               "Invalid range type");
+    return mRangeType != NS_TEXTRANGE_CARETPOSITION;
+  }
 };
 
 /******************************************************************************
  * mozilla::TextRangeArray
  *
  * XXX This should be replaced with nsTArray<TextRange>.
  ******************************************************************************/