Bug 1275918 part.2 Update TextComposition::mCompositionStartOffset when it's modified in the remote process r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 14 Jun 2016 21:06:34 +0900
changeset 302148 bbe31ff52ae422e4133e0eea6a1dcebba990100e
parent 302147 eefc9532e7152d0b03e9489af0b54a1df7ea29f8
child 302149 fd0960e658109b1e1b613a835279d08a5108d244
push id78619
push usermasayuki@d-toybox.com
push dateTue, 21 Jun 2016 07:52:45 +0000
treeherdermozilla-inbound@bbe31ff52ae4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1275918
milestone50.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 1275918 part.2 Update TextComposition::mCompositionStartOffset when it's modified in the remote process r=m_kato MozReview-Commit-ID: H1SJTWWav6G
dom/events/IMEStateManager.cpp
dom/events/IMEStateManager.h
dom/events/TextComposition.cpp
dom/events/TextComposition.h
dom/ipc/TabParent.cpp
widget/ContentCache.cpp
widget/ContentCache.h
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -217,16 +217,49 @@ IMEStateManager::StopIMEStateManagement(
   sActiveInputContextWidget = nullptr;
   sPresContext = nullptr;
   sContent = nullptr;
   sActiveTabParent = nullptr;
   DestroyIMEContentObserver();
 }
 
 // static
+void
+IMEStateManager::MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
+                                                uint32_t aStartOffset)
+{
+  if (NS_WARN_IF(!sTextCompositions)) {
+    MOZ_LOG(sISMLog, LogLevel::Warning,
+      ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+       "aWidget=0x%p, aStartOffset=%u), called when there is no "
+       "composition", aWidget, aStartOffset));
+    return;
+  }
+
+  RefPtr<TextComposition> composition = GetTextCompositionFor(aWidget);
+  if (NS_WARN_IF(!composition)) {
+    MOZ_LOG(sISMLog, LogLevel::Warning,
+      ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+       "aWidget=0x%p, aStartOffset=%u), called when there is no "
+       "composition", aWidget, aStartOffset));
+    return;
+  }
+
+  if (composition->NativeOffsetOfStartComposition() == aStartOffset) {
+    return;
+  }
+
+  MOZ_LOG(sISMLog, LogLevel::Info,
+    ("ISM: IMEStateManager::MaybeStartOffsetUpdatedInChild("
+     "aWidget=0x%p, aStartOffset=%u), old offset=%u",
+     aWidget, aStartOffset, composition->NativeOffsetOfStartComposition()));
+  composition->OnStartOffsetUpdatedInChild(aStartOffset);
+}
+
+// static
 nsresult
 IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
 
   // First, if there is a composition in the aPresContext, clean up it.
   if (sTextCompositions) {
     TextCompositionArray::index_type i =
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -92,16 +92,28 @@ public:
                                              const InputContextAction& aAction);
 
   /**
    * StopIMEStateManagement() is called when the process should stop managing
    * IME state.
    */
   static void StopIMEStateManagement();
 
+  /**
+   * MaybeStartOffsetUpdatedInChild() is called when composition start offset
+   * is maybe updated in the child process.  I.e., even if it's not updated,
+   * this is called and never called if the composition is in this process.
+   * @param aWidget             The widget whose native IME context has the
+   *                            composition.
+   * @param aStartOffset        New composition start offset with native
+   *                            linebreaks.
+   */
+  static void MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
+                                             uint32_t aStartOffset);
+
   static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
   static nsresult OnRemoveContent(nsPresContext* aPresContext,
                                   nsIContent* aContent);
   /**
    * OnChangeFocus() should be called when focused content is changed or
    * IME enabled state is changed.  If nobody has focus, set both aPresContext
    * and aContent nullptr.  E.g., all windows are deactivated.
    */
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -505,16 +505,22 @@ TextComposition::OnCompositionEventDispa
   }
 
   if (aCompositionEvent->CausesDOMTextEvent()) {
     mTargetClauseOffsetInComposition = aCompositionEvent->TargetClauseOffset();
   }
 }
 
 void
+TextComposition::OnStartOffsetUpdatedInChild(uint32_t aStartOffset)
+{
+  mCompositionStartOffset = aStartOffset;
+}
+
+void
 TextComposition::MaybeNotifyIMEOfCompositionEventHandled(
                    const WidgetCompositionEvent* aCompositionEvent)
 {
   if (aCompositionEvent->mMessage != eCompositionStart &&
       !aCompositionEvent->CausesDOMTextEvent()) {
     return;
   }
 
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -397,16 +397,25 @@ private:
   /**
    * 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();
 
   /**
+   * OnStartOffsetUpdatedInChild() is called when composition start offset
+   * is updated in the child process.  I.e., this is called and never called
+   * if the composition is in this process.
+   * @param aStartOffset        New composition start offset with native
+   *                            linebreaks.
+   */
+  void OnStartOffsetUpdatedInChild(uint32_t aStartOffset);
+
+  /**
    * CompositionEventDispatcher dispatches the specified composition (or text)
    * event.
    */
   class CompositionEventDispatcher : public Runnable
   {
   public:
     CompositionEventDispatcher(TextComposition* aTextComposition,
                                nsINode* aEventTarget,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1861,17 +1861,17 @@ TabParent::RecvNotifyIMEFocus(const Cont
                               nsIMEUpdatePreference* aPreference)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     *aPreference = nsIMEUpdatePreference();
     return true;
   }
 
-  mContentCache.AssignContent(aContentCache, &aIMENotification);
+  mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
   IMEStateManager::NotifyIME(aIMENotification, widget, true);
 
   if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
     *aPreference = widget->GetIMEUpdatePreference();
   }
   return true;
 }
 
@@ -1887,58 +1887,58 @@ TabParent::RecvNotifyIMETextChange(const
   nsIMEUpdatePreference updatePreference = widget->GetIMEUpdatePreference();
   NS_ASSERTION(updatePreference.WantTextChange(),
                "Don't call Send/RecvNotifyIMETextChange without NOTIFY_TEXT_CHANGE");
   MOZ_ASSERT(!aIMENotification.mTextChangeData.mCausedOnlyByComposition ||
                updatePreference.WantChangesCausedByComposition(),
     "The widget doesn't want text change notification caused by composition");
 #endif
 
-  mContentCache.AssignContent(aContentCache, &aIMENotification);
+  mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
   mContentCache.MaybeNotifyIME(widget, aIMENotification);
   return true;
 }
 
 bool
 TabParent::RecvNotifyIMECompositionUpdate(
              const ContentCache& aContentCache,
              const IMENotification& aIMENotification)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
 
-  mContentCache.AssignContent(aContentCache, &aIMENotification);
+  mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
   mContentCache.MaybeNotifyIME(widget, aIMENotification);
   return true;
 }
 
 bool
 TabParent::RecvNotifyIMESelection(const ContentCache& aContentCache,
                                   const IMENotification& aIMENotification)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return true;
 
-  mContentCache.AssignContent(aContentCache, &aIMENotification);
+  mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
   mContentCache.MaybeNotifyIME(widget, aIMENotification);
   return true;
 }
 
 bool
 TabParent::RecvUpdateContentCache(const ContentCache& aContentCache)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
 
-  mContentCache.AssignContent(aContentCache);
+  mContentCache.AssignContent(aContentCache, widget);
   return true;
 }
 
 bool
 TabParent::RecvNotifyIMEMouseButtonEvent(
              const IMENotification& aIMENotification,
              bool* aConsumedByIME)
 {
@@ -1957,17 +1957,17 @@ bool
 TabParent::RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
                                        const IMENotification& aIMENotification)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
 
-  mContentCache.AssignContent(aContentCache, &aIMENotification);
+  mContentCache.AssignContent(aContentCache, widget, &aIMENotification);
   mContentCache.MaybeNotifyIME(widget, aIMENotification);
   return true;
 }
 
 bool
 TabParent::RecvOnEventNeedingAckHandled(const EventMessage& aMessage)
 {
   // This is called when the child process receives WidgetCompositionEvent or
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -433,41 +433,50 @@ ContentCacheInParent::ContentCacheInPare
   , mCommitStringByRequest(nullptr)
   , mPendingEventsNeedingAck(0)
   , mIsComposing(false)
 {
 }
 
 void
 ContentCacheInParent::AssignContent(const ContentCache& aOther,
+                                    nsIWidget* aWidget,
                                     const IMENotification* aNotification)
 {
   mCompositionStart = aOther.mCompositionStart;
   mText = aOther.mText;
   mSelection = aOther.mSelection;
   mFirstCharRect = aOther.mFirstCharRect;
   mCaret = aOther.mCaret;
   mTextRectArray = aOther.mTextRectArray;
   mEditorRect = aOther.mEditorRect;
 
+  if (mIsComposing) {
+    NS_WARN_IF(mCompositionStart == UINT32_MAX);
+    IMEStateManager::MaybeStartOffsetUpdatedInChild(aWidget, mCompositionStart);
+  } else {
+    NS_WARN_IF(mCompositionStart != UINT32_MAX);
+  }
+
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCacheInParent: 0x%p AssignContent(aNotification=%s), "
      "Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, "
      "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, "
      "mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ "
-     "mStart=%u, mRects.Length()=%u }, mCompositionStart=%u, mEditorRect=%s",
+     "mStart=%u, mRects.Length()=%u }, mIsComposing=%s, mCompositionStart=%u, "
+     "mEditorRect=%s",
      this, GetNotificationName(aNotification),
      mText.Length(), mSelection.mAnchor, mSelection.mFocus,
      GetWritingModeName(mSelection.mWritingMode).get(),
      GetRectText(mSelection.mAnchorCharRect).get(),
      GetRectText(mSelection.mFocusCharRect).get(),
      GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(),
      mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
-     mTextRectArray.mRects.Length(), mCompositionStart,
-     GetRectText(mEditorRect).get()));
+     mTextRectArray.mRects.Length(), GetBoolName(mIsComposing),
+     mCompositionStart, GetRectText(mEditorRect).get()));
 }
 
 bool
 ContentCacheInParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
                                               nsIWidget* aWidget) const
 {
   MOZ_ASSERT(aWidget);
 
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -275,16 +275,17 @@ public:
   ContentCacheInParent();
 
   /**
    * AssignContent() is called when TabParent receives ContentCache from
    * the content process.  This doesn't copy composition information because
    * it's managed by TabParent itself.
    */
   void AssignContent(const ContentCache& aOther,
+                     nsIWidget* aWidget,
                      const IMENotification* aNotification = nullptr);
 
   /**
    * HandleQueryContentEvent() sets content data to aEvent.mReply.
    *
    * For eQuerySelectedText, fail if the cache doesn't contain the whole
    *  selected range. (This shouldn't happen because PuppetWidget should have
    *  already sent the whole selection.)