Bug 966157 - Part 2. Child process should listen NOTIFY_IME_OF_POSITION_CHANGE. r=masayuki
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Mon, 15 Dec 2014 18:37:00 +0900
changeset 248694 5e9067e7f6cda968c46e6ea7ccc55814751202f4
parent 248693 2a997130c2e79daf5a60e439868338bbcf66fba1
child 248695 8a01e921708c0c5811c6e4ecfdf04b39e84eab5e
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs966157
milestone37.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 966157 - Part 2. Child process should listen NOTIFY_IME_OF_POSITION_CHANGE. r=masayuki
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
widget/PuppetWidget.cpp
widget/PuppetWidget.h
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -230,16 +230,26 @@ parent:
     /**
      * Notifies chrome to currect editor rect
      *
      *  rect         Rect of current focused editor
      */
     prio(urgent) async NotifyIMEEditorRect(nsIntRect rect);
 
     /**
+     * Notifies chrome to position change
+     *
+     *  editorRect   Rect of current focused editor
+     *  compositionRects     Rects of current composition string
+     */
+    prio(urgent) async NotifyIMEPositionChange(nsIntRect editorRect,
+                                               nsIntRect[] compositionRects,
+                                               nsIntRect caretRect);
+
+    /**
      * Instructs chrome to end any pending composition
      *
      *  cancel       PR_TRUE if composition should be cancelled
      *  composition  Text to commit before ending the composition
      *
      *  if cancel is PR_TRUE,
      *    widget should return empty string for composition
      *  if cancel is PR_FALSE,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1491,16 +1491,39 @@ TabParent::RecvNotifyIMEMouseButtonEvent
 bool
 TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
 {
   mIMEEditorRect = aRect;
   return true;
 }
 
 bool
+TabParent::RecvNotifyIMEPositionChange(
+             const nsIntRect& aEditorRect,
+             const InfallibleTArray<nsIntRect>& aCompositionRects,
+             const nsIntRect& aCaretRect)
+{
+  mIMEEditorRect = aEditorRect;
+  mIMECompositionRects = aCompositionRects;
+  mIMECaretRect = aCaretRect;
+
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget) {
+    return true;
+  }
+
+  const nsIMEUpdatePreference updatePreference =
+    widget->GetIMEUpdatePreference();
+  if (updatePreference.WantPositionChanged()) {
+    widget->NotifyIME(IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
+  }
+  return true;
+}
+
+bool
 TabParent::RecvRequestFocus(const bool& aCanRaise)
 {
   nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
   if (!fm) {
     return true;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -174,16 +174,20 @@ public:
                                         const uint32_t& aAnchor,
                                         const uint32_t& aFocus,
                                         const mozilla::WritingMode& aWritingMode,
                                         const bool& aCausedByComposition) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
                                                bool* aConsumedByIME) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMEEditorRect(const nsIntRect& aRect) MOZ_OVERRIDE;
+    virtual bool RecvNotifyIMEPositionChange(
+                   const nsIntRect& aEditoRect,
+                   const InfallibleTArray<nsIntRect>& aCompositionRects,
+                   const nsIntRect& aCaretRect) MOZ_OVERRIDE;
     virtual bool RecvEndIMEComposition(const bool& aCancel,
                                        nsString* aComposition) MOZ_OVERRIDE;
     virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
                                      int32_t* aIMEOpen,
                                      intptr_t* aNativeIMEContext) MOZ_OVERRIDE;
     virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
                                      const int32_t& aIMEOpen,
                                      const nsString& aType,
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -443,16 +443,18 @@ PuppetWidget::NotifyIME(const IMENotific
     case NOTIFY_IME_OF_SELECTION_CHANGE:
       return NotifyIMEOfSelectionChange(aIMENotification);
     case NOTIFY_IME_OF_TEXT_CHANGE:
       return NotifyIMEOfTextChange(aIMENotification);
     case NOTIFY_IME_OF_COMPOSITION_UPDATE:
       return NotifyIMEOfUpdateComposition();
     case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
       return NotifyIMEOfMouseButtonEvent(aIMENotification);
+    case NOTIFY_IME_OF_POSITION_CHANGE:
+      return NotifyIMEOfPositionChange();
     default:
       return NS_ERROR_NOT_IMPLEMENTED;
   }
 }
 
 NS_IMETHODIMP_(void)
 PuppetWidget::SetInputContext(const InputContext& aContext,
                               const InputContextAction& aAction)
@@ -541,75 +543,129 @@ nsresult
 PuppetWidget::NotifyIMEOfUpdateComposition()
 {
 #ifndef MOZ_CROSS_PROCESS_IME
   return NS_OK;
 #endif
 
   NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
 
+  uint32_t startOffset;
+  uint32_t targetCauseOffset;
+  nsAutoTArray<nsIntRect, 16> textRectArray;
+  if (!GetCompositionRects(startOffset,
+                           textRectArray,
+                           targetCauseOffset)) {
+    return NS_ERROR_FAILURE;
+  }
+  nsIntRect caretRect;
+  GetCaretRect(caretRect, targetCauseOffset);
+
+  mTabChild->SendNotifyIMESelectedCompositionRect(startOffset,
+                                                  textRectArray,
+                                                  targetCauseOffset,
+                                                  caretRect);
+  return NS_OK;
+}
+
+bool
+PuppetWidget::GetCompositionRects(uint32_t& aStartOffset,
+                                  nsTArray<nsIntRect>& aTextRectArray,
+                                  uint32_t& aTargetCauseOffset)
+{
   nsRefPtr<TextComposition> textComposition =
     IMEStateManager::GetTextCompositionFor(this);
-  NS_ENSURE_TRUE(textComposition, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(textComposition, false);
 
   nsEventStatus status;
-  nsTArray<nsIntRect> textRectArray(textComposition->String().Length());
-  uint32_t startOffset = textComposition->NativeOffsetOfStartComposition();
-  uint32_t endOffset = textComposition->String().Length() + startOffset;
-  for (uint32_t i = startOffset; i < endOffset; i++) {
+  aTextRectArray.SetCapacity(textComposition->String().Length());
+  aStartOffset = textComposition->NativeOffsetOfStartComposition();
+  aTargetCauseOffset = textComposition->OffsetOfTargetClause();
+  uint32_t endOffset = textComposition->String().Length() + aStartOffset;
+  for (uint32_t i = aStartOffset; i < endOffset; i++) {
     WidgetQueryContentEvent textRect(true, NS_QUERY_TEXT_RECT, this);
     InitEvent(textRect, nullptr);
     textRect.InitForQueryTextRect(i, 1);
     DispatchEvent(&textRect, status);
-    NS_ENSURE_TRUE(textRect.mSucceeded, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(textRect.mSucceeded, false);
+
+    aTextRectArray.AppendElement(textRect.mReply.mRect);
+  }
+  return true;
+}
 
-    textRectArray.AppendElement(textRect.mReply.mRect);
-  }
+uint32_t
+PuppetWidget::GetCaretOffset()
+{
+  nsEventStatus status;
+  WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT, this);
+  InitEvent(selection, nullptr);
+  DispatchEvent(&selection, status);
+  NS_ENSURE_TRUE(selection.mSucceeded, 0);
 
-  uint32_t targetCauseOffset = textComposition->OffsetOfTargetClause();
+  return selection.mReply.mOffset;
+}
+
+bool
+PuppetWidget::GetCaretRect(nsIntRect& aCaretRect, uint32_t aCaretOffset)
+{
+  nsEventStatus status;
   WidgetQueryContentEvent caretRect(true, NS_QUERY_CARET_RECT, this);
   InitEvent(caretRect, nullptr);
-  caretRect.InitForQueryCaretRect(targetCauseOffset);
+  caretRect.InitForQueryCaretRect(aCaretOffset);
   DispatchEvent(&caretRect, status);
-  NS_ENSURE_TRUE(caretRect.mSucceeded, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(caretRect.mSucceeded, false);
 
-  mTabChild->SendNotifyIMESelectedCompositionRect(startOffset,
-                                                  textRectArray,
-                                                  targetCauseOffset,
-                                                  caretRect.mReply.mRect);
-  return NS_OK;
+  aCaretRect = caretRect.mReply.mRect;
+
+  return true;
 }
 
 nsresult
 PuppetWidget::NotifyIMEOfEditorRect()
 {
 #ifndef MOZ_CROSS_PROCESS_IME
   return NS_OK;
 #endif
+  if (NS_WARN_IF(!mTabChild)) {
+    return NS_ERROR_FAILURE;
+  }
 
+  nsIntRect rect;
+  if (!GetEditorRect(rect)) {
+    return NS_ERROR_FAILURE;
+  }
+  mTabChild->SendNotifyIMEEditorRect(rect);
+  return NS_OK;
+}
+
+bool
+PuppetWidget::GetEditorRect(nsIntRect& aRect)
+{
   nsEventStatus status;
   WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, this);
   InitEvent(editorRectEvent);
   DispatchEvent(&editorRectEvent, status);
-  if (editorRectEvent.mSucceeded) {
-    mTabChild->SendNotifyIMEEditorRect(editorRectEvent.mReply.mRect);
+  if (NS_WARN_IF(!editorRectEvent.mSucceeded)) {
+    return false;
   }
+  aRect = editorRectEvent.mReply.mRect;
 
-  return NS_OK;
+  return true;
 }
 
-
 nsIMEUpdatePreference
 PuppetWidget::GetIMEUpdatePreference()
 {
 #ifdef MOZ_CROSS_PROCESS_IME
   // e10s requires IME information cache into TabParent
   return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
                                nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
-                               nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE);
+                               nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
+                               nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
 #else
   // B2G doesn't handle IME as widget-level.
   return nsIMEUpdatePreference();
 #endif
 }
 
 nsresult
 PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
@@ -690,16 +746,50 @@ PuppetWidget::NotifyIMEOfMouseButtonEven
   if (!mTabChild->SendNotifyIMEMouseButtonEvent(aIMENotification,
                                                 &consumedByIME)) {
     return NS_ERROR_FAILURE;
   }
 
   return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK;
 }
 
+nsresult
+PuppetWidget::NotifyIMEOfPositionChange()
+{
+#ifndef MOZ_CROSS_PROCESS_IME
+  return NS_OK;
+#endif
+  if (NS_WARN_IF(!mTabChild)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIntRect editorRect;
+  if (!GetEditorRect(editorRect)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  uint32_t startOffset;
+  uint32_t targetCauseOffset;
+  nsAutoTArray<nsIntRect, 16> textRectArray;
+  if (!GetCompositionRects(startOffset,
+                           textRectArray,
+                           targetCauseOffset)) {
+    // no composition string, get caret offset by NS_QUERY_SELECTED_TEXT
+    targetCauseOffset = GetCaretOffset();
+  }
+
+  nsIntRect caretRect;
+  GetCaretRect(caretRect, targetCauseOffset);
+  if (!mTabChild->SendNotifyIMEPositionChange(editorRect, textRectArray,
+                                              caretRect)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 PuppetWidget::SetCursor(nsCursor aCursor)
 {
   if (mCursor == aCursor && !mUpdateCursor) {
     return NS_OK;
   }
 
   if (mTabChild &&
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -212,16 +212,24 @@ private:
 
   nsresult IMEEndComposition(bool aCancel);
   nsresult NotifyIMEOfFocusChange(bool aFocus);
   nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
   nsresult NotifyIMEOfUpdateComposition();
   nsresult NotifyIMEOfTextChange(const IMENotification& aIMENotification);
   nsresult NotifyIMEOfMouseButtonEvent(const IMENotification& aIMENotification);
   nsresult NotifyIMEOfEditorRect();
+  nsresult NotifyIMEOfPositionChange();
+
+  bool GetEditorRect(nsIntRect& aEditorRect);
+  bool GetCompositionRects(uint32_t& aStartOffset,
+                           nsTArray<nsIntRect>& aRectArray,
+                           uint32_t& aTargetCauseOffset);
+  bool GetCaretRect(nsIntRect& aCaretRect, uint32_t aCaretOffset);
+  uint32_t GetCaretOffset();
 
   class PaintTask : public nsRunnable {
   public:
     NS_DECL_NSIRUNNABLE
     explicit PaintTask(PuppetWidget* widget) : mWidget(widget) {}
     void Revoke() { mWidget = nullptr; }
   private:
     PuppetWidget* mWidget;