Bug 1203871 - Part 4. Implement QUERY_TEXT_RECT_ARRAY to nsIDOMWindowUtils. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Mon, 14 Mar 2016 16:03:36 +0900
changeset 340457 1dc51e8e0e6529c1af1766859a38c2695fdfacf6
parent 340456 41fd5679bf2162a58fac17816426f64d0fb60d5b
child 340458 b82513049c682f0b09bc28c0b4a1af2d5252f4f8
push id12969
push userm_kato@ga2.so-net.ne.jp
push dateTue, 15 Mar 2016 10:01:34 +0000
reviewersmasayuki
bugs1203871
milestone48.0a1
Bug 1203871 - Part 4. Implement QUERY_TEXT_RECT_ARRAY to nsIDOMWindowUtils. r?masayuki To test eQueryCharRectArray, I would like to add it to nsIDOMWindowUtils. Also this will require external keyboard support on Android. MozReview-Commit-ID: 24lvQxXBnRX
dom/base/nsDOMWindowUtils.cpp
dom/base/nsQueryContentEventResult.cpp
dom/base/nsQueryContentEventResult.h
dom/base/test/test_sendQueryContentAndSelectionSetEvent.html
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/interfaces/base/nsIQueryContentEventResult.idl
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1847,16 +1847,19 @@ nsDOMWindowUtils::SendQueryContentEvent(
       message = eQueryTextRect;
       break;
     case QUERY_EDITOR_RECT:
       message = eQueryEditorRect;
       break;
     case QUERY_CHARACTER_AT_POINT:
       message = eQueryCharacterAtPoint;
       break;
+    case QUERY_TEXT_RECT_ARRAY:
+      message = eQueryTextRectArray;
+      break;
     default:
       return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIWidget> targetWidget = widget;
   LayoutDeviceIntPoint pt(aX, aY);
 
   bool useNativeLineBreak =
@@ -1895,16 +1898,20 @@ nsDOMWindowUtils::SendQueryContentEvent(
       queryEvent.InitForQueryTextContent(aOffset, aLength, useNativeLineBreak);
       break;
     case eQueryCaretRect:
       queryEvent.InitForQueryCaretRect(aOffset, useNativeLineBreak);
       break;
     case eQueryTextRect:
       queryEvent.InitForQueryTextRect(aOffset, aLength, useNativeLineBreak);
       break;
+    case eQueryTextRectArray:
+      queryEvent.InitForQueryTextRectArray(aOffset, aLength,
+                                           useNativeLineBreak);
+      break;
     default:
       queryEvent.mUseNativeLineBreak = useNativeLineBreak;
       break;
   }
 
   nsEventStatus status;
   nsresult rv = targetWidget->DispatchEvent(&queryEvent, status);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsQueryContentEventResult.cpp
+++ b/dom/base/nsQueryContentEventResult.cpp
@@ -150,34 +150,59 @@ nsQueryContentEventResult::GetTentativeC
   }
   if (NS_WARN_IF(mEventMessage != eQueryCharacterAtPoint)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   *aNotFound = (mTentativeCaretOffset == WidgetQueryContentEvent::NOT_FOUND);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsQueryContentEventResult::GetCharacterRect(int32_t aOffset,
+                                            int32_t * aLeft, int32_t* aTop,
+                                            int32_t* aWidth, int32_t* aHeight)
+{
+  NS_ENSURE_TRUE(mSucceeded, NS_ERROR_NOT_AVAILABLE);
+  NS_ENSURE_TRUE(mEventMessage == eQueryTextRectArray,
+                 NS_ERROR_NOT_AVAILABLE);
+
+  if (NS_WARN_IF(mRectArray.Length() <= static_cast<uint32_t>(aOffset))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  *aLeft = mRectArray[aOffset].x;
+  *aTop = mRectArray[aOffset].y;
+  *aWidth = mRectArray[aOffset].width;
+  *aHeight = mRectArray[aOffset].height;
+
+  return NS_OK;
+}
+
 void
 nsQueryContentEventResult::SetEventResult(nsIWidget* aWidget,
                                           const WidgetQueryContentEvent &aEvent)
 {
   mEventMessage = aEvent.mMessage;
   mSucceeded = aEvent.mSucceeded;
   mReversed = aEvent.mReply.mReversed;
   mRect = aEvent.mReply.mRect;
   mOffset = aEvent.mReply.mOffset;
   mTentativeCaretOffset = aEvent.mReply.mTentativeCaretOffset;
   mString = aEvent.mReply.mString;
+  mRectArray = aEvent.mReply.mRectArray;
 
   if (!IsRectEnabled(mEventMessage) || !aWidget || !mSucceeded) {
     return;
   }
 
   nsIWidget* topWidget = aWidget->GetTopLevelWidget();
   if (!topWidget || topWidget == aWidget) {
     return;
   }
 
   // Convert the top widget related coordinates to the given widget's.
   LayoutDeviceIntPoint offset =
     aWidget->WidgetToScreenOffset() - topWidget->WidgetToScreenOffset();
   mRect.MoveBy(-offset);
+  for (size_t i = 0; i < mRectArray.Length(); i++) {
+    mRectArray[i].MoveBy(-offset);
+  }
 }
--- a/dom/base/nsQueryContentEventResult.h
+++ b/dom/base/nsQueryContentEventResult.h
@@ -30,14 +30,15 @@ protected:
   ~nsQueryContentEventResult();
 
   mozilla::EventMessage mEventMessage;
 
   uint32_t mOffset;
   uint32_t mTentativeCaretOffset;
   nsString mString;
   mozilla::LayoutDeviceIntRect mRect;
+  nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
 
   bool mSucceeded;
   bool mReversed;
 };
 
 #endif // mozilla_dom_nsQueryContentEventResult_h
--- a/dom/base/test/test_sendQueryContentAndSelectionSetEvent.html
+++ b/dom/base/test/test_sendQueryContentAndSelectionSetEvent.html
@@ -112,16 +112,42 @@ function runTests()
      "sendQueryContentEvent(QUERY_TEXT_RECT) should return same top as calling with QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK");
   is(result.left, textRectNative.left,
      "sendQueryContentEvent(QUERY_TEXT_RECT) should return same left as calling with QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK");
   is(result.height, textRectNative.height,
      "sendQueryContentEvent(QUERY_TEXT_RECT) should return same height as calling with QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK");
   is(result.width, textRectNative.width,
      "sendQueryContentEvent(QUERY_TEXT_RECT) should return same width as calling with QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK");
 
+  // QueryTextRectArray
+  var textRectArray = gUtils.sendQueryContentEvent(gUtils.QUERY_TEXT_RECT_ARRAY, 1, 2, 0, 0);
+  ok(textRectArray.succeeded,
+     "sendQueryContentEvent(QUERY_TEXT_RECT_ARRAY) should succeed");
+  var textRect = gUtils.sendQueryContentEvent(gUtils.QUERY_TEXT_RECT, 1, 2, 0, 0);
+  ok(textRect.succeeded,
+     "sendQueryContentEvent(QUERY_TEXT_RECT) should succeed");
+  var left = {};
+  var top = {};
+  var width = {};
+  var height = {};
+  var left2 = {};
+  var top2 = {};
+  var width2 = {};
+  var height2 = {};
+  textRectArray.getCharacterRect(0, left, top, width, height);
+  ok(textRect.top, top.value,
+     "sendQueryContentEvent(QUERY_TEXT_RECT_ARRAY) should return same top that returns QUERY_TEXT_RECT");
+  ok(textRect.left, left.value,
+     "sendQueryContentEvent(QUERY_TEXT_RECT_ARRAY) should return same left that returns QUERY_TEXT_RECT");
+  textRectArray.getCharacterRect(1, left2, top2, width2, height2);
+  ok(textRect.width, width.value + width2.value,
+     "sendQueryContentEvent(QUERY_TEXT_RECT_ARRAY) should return same width that QUERY_TEXT_RECT is returned for offset 1 and 2");
+  ok(textRect.height, height.value,
+     "sendQueryContentEvent(QUERY_TEXT_RECT_ARRAY) should return same height that returns QUERY_TEXT_RECT");
+
   // QueryCharacterAtOffset
   result = gUtils.sendQueryContentEvent(gUtils.QUERY_CHARACTER_AT_POINT, 0, 0, textRectNative.left + 1, textRectNative.top + 1,
                                         gUtils.QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK);
   ok(result.succeeded,
      "sendQueryContentEvent(QUERY_CHARACTER_AT_POINT, QUERY_CONTENT_FLAG_USE_NATIVE_LINE_BREAK) should succeed");
   is(result.top, textRectNative.top,
      "The character top is wrong");
   is(result.left, textRectNative.left,
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1171,16 +1171,27 @@ interface nsIDOMWindowUtils : nsISupport
    * @param aY        Y offset in the widget.
    *
    * @return offset, notFound, left, top, width and height properties of the
    *         result are available.
    */
   const unsigned long QUERY_CHARACTER_AT_POINT                  = 3208;
 
   /**
+   * QUERY_TEXT_RECT_ARRAY queries the rects per character
+   *
+   * @param aOffset   The first character's offset.  0 is the first character.
+   * @param aLength   The length of getting text.  If the aLength is too long,
+   *                  the extra length is ignored.
+   * @param aX        Not used.
+   * @param aY        Not used.
+   */
+  const unsigned long QUERY_TEXT_RECT_ARRAY                     = 3209;
+
+  /**
    * Called when the remote child frame has changed its fullscreen state,
    * when entering fullscreen, and when the origin which is fullscreen changes.
    * aFrameElement is the iframe element which contains the child-process
    * fullscreen document.
    */
   void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement);
 
   /**
--- a/dom/interfaces/base/nsIQueryContentEventResult.idl
+++ b/dom/interfaces/base/nsIQueryContentEventResult.idl
@@ -19,12 +19,16 @@ interface nsIQueryContentEventResult : n
   readonly attribute boolean reversed;
 
   readonly attribute long left;
   readonly attribute long top;
   readonly attribute long width;
   readonly attribute long height;
   readonly attribute AString text;
 
+  void getCharacterRect(in long offset,
+                        out long left, out long top,
+                        out long width, out long height);
+
   readonly attribute boolean succeeded;
   readonly attribute boolean notFound;
   readonly attribute boolean tentativeCaretOffsetNotFound;
 };