Bug 1275918 part.2 Update TextComposition::mCompositionStartOffset when it's modified in the remote process r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 14 Jun 2016 21:06:34 +0900
changeset 378023 59119d543ba16eca3406918dd97738c7ce8f07e7
parent 378022 83c907462c2e59e000514b14b5c4e11ba72adf5a
child 378166 7897c3b1de9184827fdb375c6566680911fab671
push id20917
push usermasayuki@d-toybox.com
push dateTue, 14 Jun 2016 12:17:57 +0000
reviewersm_kato
bugs1275918
milestone50.0a1
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.)