Bug 492394 part.1 NS_QUERY_CHARACTER_AT_POINT should also return tentative caret offset for the point r=smaug, sr=smaug

This commit is contained in:
Masayuki Nakano 2015-04-14 14:27:37 +09:00
Родитель 14e96990fc
Коммит 8c1890067d
8 изменённых файлов: 114 добавлений и 12 удалений

Просмотреть файл

@ -38,6 +38,21 @@ nsQueryContentEventResult::GetOffset(uint32_t *aOffset)
return NS_OK;
}
NS_IMETHODIMP
nsQueryContentEventResult::GetTentativeCaretOffset(uint32_t* aOffset)
{
bool notFound;
nsresult rv = GetTentativeCaretOffsetNotFound(&notFound);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (NS_WARN_IF(notFound)) {
return NS_ERROR_NOT_AVAILABLE;
}
*aOffset = mTentativeCaretOffset;
return NS_OK;
}
static bool IsRectEnabled(uint32_t aEventID)
{
return aEventID == NS_QUERY_CARET_RECT ||
@ -126,6 +141,19 @@ nsQueryContentEventResult::GetNotFound(bool *aNotFound)
return NS_OK;
}
NS_IMETHODIMP
nsQueryContentEventResult::GetTentativeCaretOffsetNotFound(bool* aNotFound)
{
if (NS_WARN_IF(!mSucceeded)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_WARN_IF(mEventID != NS_QUERY_CHARACTER_AT_POINT)) {
return NS_ERROR_NOT_AVAILABLE;
}
*aNotFound = (mTentativeCaretOffset == WidgetQueryContentEvent::NOT_FOUND);
return NS_OK;
}
void
nsQueryContentEventResult::SetEventResult(nsIWidget* aWidget,
const WidgetQueryContentEvent &aEvent)
@ -135,6 +163,7 @@ nsQueryContentEventResult::SetEventResult(nsIWidget* aWidget,
mReversed = aEvent.mReply.mReversed;
mRect = aEvent.mReply.mRect;
mOffset = aEvent.mReply.mOffset;
mTentativeCaretOffset = aEvent.mReply.mTentativeCaretOffset;
mString = aEvent.mReply.mString;
if (!IsRectEnabled(mEventID) || !aWidget || !mSucceeded) {

Просмотреть файл

@ -30,6 +30,7 @@ protected:
uint32_t mEventID;
uint32_t mOffset;
uint32_t mTentativeCaretOffset;
nsString mString;
mozilla::LayoutDeviceIntRect mRect;

Просмотреть файл

@ -1135,6 +1135,9 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
return rv;
}
aEvent->mReply.mOffset = aEvent->mReply.mTentativeCaretOffset =
WidgetQueryContentEvent::NOT_FOUND;
nsIFrame* rootFrame = mPresShell->GetRootFrame();
NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
nsIWidget* rootWidget = rootFrame->GetNearestWidget();
@ -1164,12 +1167,10 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
nsLayoutUtils::GetEventCoordinatesRelativeTo(&eventOnRoot, rootFrame);
nsIFrame* targetFrame = nsLayoutUtils::GetFrameForPoint(rootFrame, ptInRoot);
if (!targetFrame || targetFrame->GetType() != nsGkAtoms::textFrame ||
!targetFrame->GetContent() ||
if (!targetFrame || !targetFrame->GetContent() ||
!nsContentUtils::ContentIsDescendantOf(targetFrame->GetContent(),
mRootContent)) {
// there is no character at the point.
aEvent->mReply.mOffset = WidgetQueryContentEvent::NOT_FOUND;
// There is no character at the point.
aEvent->mSucceeded = true;
return NS_OK;
}
@ -1178,6 +1179,35 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
int32_t targetAPD = targetFrame->PresContext()->AppUnitsPerDevPixel();
ptInTarget = ptInTarget.ScaleToOtherAppUnits(rootAPD, targetAPD);
nsIFrame::ContentOffsets tentativeCaretOffsets =
targetFrame->GetContentOffsetsFromPoint(ptInTarget);
if (!tentativeCaretOffsets.content ||
!nsContentUtils::ContentIsDescendantOf(tentativeCaretOffsets.content,
mRootContent)) {
// There is no character nor tentative caret point at the point.
aEvent->mSucceeded = true;
return NS_OK;
}
rv = GetFlatTextOffsetOfRange(mRootContent, tentativeCaretOffsets.content,
tentativeCaretOffsets.offset,
&aEvent->mReply.mTentativeCaretOffset,
GetLineBreakType(aEvent));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (targetFrame->GetType() != nsGkAtoms::textFrame) {
// There is no character at the point but there is tentative caret point.
aEvent->mSucceeded = true;
return NS_OK;
}
MOZ_ASSERT(
aEvent->mReply.mTentativeCaretOffset != WidgetQueryContentEvent::NOT_FOUND,
"The point is inside a character bounding box. Why tentative caret point "
"hasn't been found?");
nsTextFrame* textframe = static_cast<nsTextFrame*>(targetFrame);
nsIFrame::ContentOffsets contentOffsets =
textframe->GetCharacterOffsetAtFramePoint(ptInTarget);

Просмотреть файл

@ -11,10 +11,11 @@
* See nsIDOMWindowUtils.idl, which properites can be used was documented.
*/
[scriptable, uuid(4b4ba266-b51e-4f0f-8d0e-9f13cb2a0056)]
[scriptable, uuid(e2c39e0e-345f-451a-a7b2-e0230d555847)]
interface nsIQueryContentEventResult : nsISupports
{
readonly attribute unsigned long offset;
readonly attribute unsigned long tentativeCaretOffset;
readonly attribute boolean reversed;
readonly attribute long left;
@ -25,4 +26,5 @@ interface nsIQueryContentEventResult : nsISupports
readonly attribute boolean succeeded;
readonly attribute boolean notFound;
readonly attribute boolean tentativeCaretOffsetNotFound;
};

Просмотреть файл

@ -258,8 +258,9 @@
#define NS_QUERY_CONTENT_STATE (NS_QUERY_CONTENT_EVENT_START + 6)
// Query for the selection in the form of a nsITransferable.
#define NS_QUERY_SELECTION_AS_TRANSFERABLE (NS_QUERY_CONTENT_EVENT_START + 7)
// Query for character at a point. This returns the character offset and its
// rect. The point is specified by Event::refPoint.
// Query for character at a point. This returns the character offset, its
// rect and also tentative caret point if the point is clicked. The point is
// specified by Event::refPoint.
#define NS_QUERY_CHARACTER_AT_POINT (NS_QUERY_CONTENT_EVENT_START + 8)
// Query if the DOM element under Event::refPoint belongs to our widget
// or not.

Просмотреть файл

@ -554,6 +554,9 @@ public:
{
void* mContentsRoot;
uint32_t mOffset;
// mTentativeCaretOffset is used by only NS_QUERY_CHARACTER_AT_POINT.
// This is the offset where caret would be if user clicked at the refPoint.
uint32_t mTentativeCaretOffset;
nsString mString;
// Finally, the coordinates is system coordinates.
mozilla::LayoutDeviceIntRect mRect;

Просмотреть файл

@ -587,6 +587,7 @@ struct ParamTraits<mozilla::WidgetQueryContentEvent>
WriteParam(aMsg, aParam.mInput.mOffset);
WriteParam(aMsg, aParam.mInput.mLength);
WriteParam(aMsg, aParam.mReply.mOffset);
WriteParam(aMsg, aParam.mReply.mTentativeCaretOffset);
WriteParam(aMsg, aParam.mReply.mString);
WriteParam(aMsg, aParam.mReply.mRect);
WriteParam(aMsg, aParam.mReply.mReversed);
@ -606,6 +607,7 @@ struct ParamTraits<mozilla::WidgetQueryContentEvent>
ReadParam(aMsg, aIter, &aResult->mInput.mOffset) &&
ReadParam(aMsg, aIter, &aResult->mInput.mLength) &&
ReadParam(aMsg, aIter, &aResult->mReply.mOffset) &&
ReadParam(aMsg, aIter, &aResult->mReply.mTentativeCaretOffset) &&
ReadParam(aMsg, aIter, &aResult->mReply.mString) &&
ReadParam(aMsg, aIter, &aResult->mReply.mRect) &&
ReadParam(aMsg, aIter, &aResult->mReply.mReversed) &&

Просмотреть файл

@ -19,13 +19,13 @@
onpopuphidden="onPanelHidden(event);">
<vbox id="vbox">
<textbox id="textbox" onfocus="onFocusPanelTextbox(event);"
multiline="true" cols="20" rows="4"/>
multiline="true" cols="20" rows="4" style="font-size: 36px;"/>
</vbox>
</panel>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display">
<div id="div" style="margin: 0; padding: 0; font-size: 24px;">Here is a text frame.</div>
<div id="div" style="margin: 0; padding: 0; font-size: 36px;">Here is a text frame.</div>
<textarea style="margin: 0;" id="textarea" cols="20" rows="4"></textarea><br/>
<iframe id="iframe" width="300" height="150"
src="data:text/html,&lt;textarea id='textarea' cols='20' rows='4'&gt;&lt;/textarea&gt;"></iframe><br/>
@ -2169,9 +2169,11 @@ function runCharAtPointTest(aFocusedEditor, aTargetName)
aFocusedEditor.focus();
const kNone = -1;
const kTestingOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
const kLeftSideOffset = [ kNone, 9, 19, kNone, 33 + kLFLen];
const kRightSideOffset = [ 1, 11, kNone, 22 + kLFLen, kNone];
const kTestingOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
const kLeftSideOffset = [ kNone, 9, 19, kNone, 33 + kLFLen];
const kRightSideOffset = [ 1, 11, kNone, 22 + kLFLen, kNone];
const kLeftTentativeCaretOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
const kRightTentativeCaretOffset = [ 1, 11, 21, 22 + kLFLen, 35 + kLFLen];
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect,
@ -2203,6 +2205,12 @@ function runCharAtPointTest(aFocusedEditor, aTargetName)
checkRect(charAtPt1, textRect, "runCharAtPointTest (" + aTargetName +
"): charAtPt1 left is wrong: i=" + i);
}
ok(!charAtPt1.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt1 isn't found: i=" + i);
if (!charAtPt1.tentativeCaretOffsetNotFound) {
is(charAtPt1.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt1 is wrong: i=" + i);
}
}
// Test #2, getting same character rect by the point near the bottom-right.
@ -2218,6 +2226,12 @@ function runCharAtPointTest(aFocusedEditor, aTargetName)
checkRect(charAtPt2, textRect, "runCharAtPointTest (" + aTargetName +
"): charAtPt1 left is wrong: i=" + i);
}
ok(!charAtPt2.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt2 isn't found: i=" + i);
if (!charAtPt2.tentativeCaretOffsetNotFound) {
is(charAtPt2.tentativeCaretOffset, kRightTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt2 is wrong: i=" + i);
}
}
// Test #3, getting left character offset.
@ -2233,6 +2247,18 @@ function runCharAtPointTest(aFocusedEditor, aTargetName)
is(charAtPt3.offset, kLeftSideOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt3 offset is wrong: i=" + i);
}
if (kLeftSideOffset[i] == kNone) {
// There may be no enough padding-left (depends on platform)
todo(false,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 isn't tested: i=" + i);
} else {
ok(!charAtPt3.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 isn't found: i=" + i);
if (!charAtPt3.tentativeCaretOffsetNotFound) {
is(charAtPt3.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 is wrong: i=" + i);
}
}
}
// Test #4, getting right character offset.
@ -2248,6 +2274,12 @@ function runCharAtPointTest(aFocusedEditor, aTargetName)
is(charAtPt4.offset, kRightSideOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt4 offset is wrong: i=" + i);
}
ok(!charAtPt4.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt4 isn't found: i=" + i);
if (!charAtPt4.tentativeCaretOffsetNotFound) {
is(charAtPt4.tentativeCaretOffset, kRightTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt4 is wrong: i=" + i);
}
}
}
}
@ -2268,6 +2300,8 @@ function runCharAtPointAtOutsideTest()
"runCharAtPointAtOutsideTest: charAtPt")) {
ok(charAtPt.notFound,
"runCharAtPointAtOutsideTest: charAtPt is found on outside of editor");
ok(charAtPt.tentativeCaretOffsetNotFound,
"runCharAtPointAtOutsideTest: tentative caret offset for charAtPt is found on outside of editor");
}
}