Bug 1203871 - Part 4. Implement QUERY_TEXT_RECT_ARRAY to nsIDOMWindowUtils for unit test. r=masayuki,smaug draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Thu, 23 Jun 2016 10:42:00 +0100
changeset 380804 8610d6f66dcc1d83df90274f84e1ec33eced0678
parent 380803 6b6cfbba6777d267b0e884444be41079be06dba8
child 380805 ea7807e27f53175a494df4434c0a5418e1d6fd93
push id21331
push userm_kato@ga2.so-net.ne.jp
push dateThu, 23 Jun 2016 12:36:21 +0000
reviewersmasayuki, smaug
bugs1203871
milestone50.0a1
Bug 1203871 - Part 4. Implement QUERY_TEXT_RECT_ARRAY to nsIDOMWindowUtils for unit test. r=masayuki,smaug To test eQueryCharRectArray, I would like to add it to nsIDOMWindowUtils. Also this require unit test and will require external keyboard support on Android Masayiki asks me more review to smaug this due IDL change. 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
@@ -1909,16 +1909,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;
   }
 
   SelectionType selectionType = SelectionType::eNormal;
   static const uint32_t kSelectionFlags =
     QUERY_CONTENT_FLAG_SELECTION_SPELLCHECK |
     QUERY_CONTENT_FLAG_SELECTION_IME_RAWINPUT |
@@ -2026,16 +2029,19 @@ nsDOMWindowUtils::SendQueryContentEvent(
       queryEvent.InitForQueryCaretRect(aOffset, options);
       break;
     case eQueryTextRect:
       queryEvent.InitForQueryTextRect(aOffset, aLength, options);
       break;
     case eQuerySelectedText:
       queryEvent.InitForQuerySelectedText(selectionType, options);
       break;
+    case eQueryTextRectArray:
+      queryEvent.InitForQueryTextRectArray(aOffset, aLength, options);
+      break;
     default:
       queryEvent.Init(options);
       break;
   }
 
   nsEventStatus status;
   nsresult rv = targetWidget->DispatchEvent(&queryEvent, status);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/base/nsQueryContentEventResult.cpp
+++ b/dom/base/nsQueryContentEventResult.cpp
@@ -194,35 +194,60 @@ 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 (!IsRectRelatedPropertyAvailable(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
@@ -1209,16 +1209,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;
 };