Bug 1275914 part.3 TextComposition should use IMEContentObserver or ContentEventHandler directly when it queries the selection r?smaug draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 10 Jun 2016 19:45:21 +0900
changeset 380216 41a5a069d53de2172e4060472b8d5f6749405319
parent 380215 127c900a3995eccf0a9fc0099d55a0c174f9aa55
child 380217 75ebfce7be10045e212b8ad4c6363bd590c5f5e8
push id21167
push usermasayuki@d-toybox.com
push dateTue, 21 Jun 2016 06:55:55 +0000
reviewerssmaug
bugs1275914
milestone50.0a1
Bug 1275914 part.3 TextComposition should use IMEContentObserver or ContentEventHandler directly when it queries the selection r?smaug TextComposition queries selection start offset a lot of times. Therefore, for reducing the runtime cost, it should use IMEContentObserver if it's available or ContentEventHandler, otherwise. MozReview-Commit-ID: 61GgQZDX2HP
dom/events/TextComposition.cpp
dom/events/TextComposition.h
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -429,16 +429,52 @@ TextComposition::HandleSelectionEvent(ns
   sHandlingSelectionEvent = true;
   // XXX During setting selection, a selection listener may change selection
   //     again.  In such case, sHandlingSelectionEvent doesn't indicate if
   //     the selection change is caused by a selection event.  However, it
   //     must be non-realistic scenario.
   handler.OnSelectionEvent(aSelectionEvent);
 }
 
+uint32_t
+TextComposition::GetSelectionStartOffset()
+{
+  nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget();
+  WidgetQueryContentEvent selectedTextEvent(true, eQuerySelectedText, widget);
+
+  // The editor which has this composition is observed by active
+  // IMEContentObserver, we can use the cache of it.
+  RefPtr<IMEContentObserver> contentObserver =
+    IMEStateManager::GetActiveContentObserver();
+  bool doQuerySelection = true;
+  if (contentObserver) {
+    if (contentObserver->IsManaging(this)) {
+      doQuerySelection = false;
+      contentObserver->HandleQueryContentEvent(&selectedTextEvent);
+    }
+    // If another editor already has focus, we cannot retrieve selection
+    // in the editor which has this composition...
+    else if (NS_WARN_IF(contentObserver->GetPresContext() == mPresContext)) {
+      return 0;  // XXX Is this okay?
+    }
+  }
+
+  // Otherwise, using slow path (i.e., compute every time with
+  // ContentEventHandler)
+  if (doQuerySelection) {
+    ContentEventHandler handler(mPresContext);
+    handler.HandleQueryContentEvent(&selectedTextEvent);
+  }
+
+  if (NS_WARN_IF(!selectedTextEvent.mSucceeded)) {
+    return 0; // XXX Is this okay?
+  }
+  return selectedTextEvent.mReply.mOffset;
+}
+
 void
 TextComposition::OnCompositionEventDispatched(
                    const WidgetCompositionEvent* aCompositionEvent)
 {
   MOZ_RELEASE_ASSERT(!mTabParent);
 
   if (!IsValidStateForComposition(aCompositionEvent->mWidget)) {
     return;
@@ -452,31 +488,18 @@ TextComposition::OnCompositionEventDispa
                mWasCompositionStringEmpty,
              "mWasCompositionStringEmpty should be true if the dispatched "
              "event is eCompositionStart");
 
   if (mWasCompositionStringEmpty &&
       !aCompositionEvent->CausesDOMCompositionEndEvent()) {
     // If there was no composition string, current selection start may be the
     // offset for inserting composition string.
-    nsCOMPtr<nsIWidget> widget = mPresContext->GetRootWidget();
-    WidgetQueryContentEvent selectedTextEvent(true, eQuerySelectedText, widget);
-    nsEventStatus status = nsEventStatus_eIgnore;
-    if (mString.IsEmpty()) {
-      widget->DispatchEvent(&selectedTextEvent, status);
-    } else {
-      MOZ_ASSERT(aCompositionEvent->mMessage == eCompositionChange);
-      // TODO: Update mCompositionStartOffset with first IME selection
-    }
-    if (NS_WARN_IF(!selectedTextEvent.mSucceeded)) {
-      // XXX Is this okay?
-      mCompositionStartOffset = 0;
-    } else {
-      mCompositionStartOffset = selectedTextEvent.mReply.mOffset;
-    }
+    // Update composition start offset with current selection start.
+    mCompositionStartOffset = GetSelectionStartOffset();
     mTargetClauseOffsetInComposition = 0;
   }
 
   if (aCompositionEvent->CausesDOMTextEvent()) {
     mTargetClauseOffsetInComposition = aCompositionEvent->TargetClauseOffset();
   }
 }
 
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -390,16 +390,23 @@ private:
    * MaybeNotifyIMEOfCompositionEventHandled() notifies IME of composition
    * event handled.  This should be called after dispatching a composition
    * event which came from widget.
    */
   void MaybeNotifyIMEOfCompositionEventHandled(
          const WidgetCompositionEvent* aCompositionEvent);
 
   /**
+   * GetSelectionStartOffset() returns normal selection start offset in the
+   * editor which has this composition.
+   * If it failed or lost focus, this would return 0.
+   */
+  uint32_t GetSelectionStartOffset();
+
+  /**
    * CompositionEventDispatcher dispatches the specified composition (or text)
    * event.
    */
   class CompositionEventDispatcher : public Runnable
   {
   public:
     CompositionEventDispatcher(TextComposition* aTextComposition,
                                nsINode* aEventTarget,