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
--- 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;
};