Bug 1109410 Resolve CSS transform in ContentEventHandler::ConvertToRootViewRelativeOffset() r=roc

This commit is contained in:
Masayuki Nakano 2015-10-05 14:46:39 +09:00
Родитель f729d738ab
Коммит f961371a5e
4 изменённых файлов: 106 добавлений и 17 удалений

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

@ -203,13 +203,13 @@ ContentEventHandler::QueryContentRect(nsIContent* aContent,
// get rect for first frame
nsRect resultRect(nsPoint(0, 0), frame->GetRect().Size());
nsresult rv = ConvertToRootViewRelativeOffset(frame, resultRect);
nsresult rv = ConvertToRootRelativeOffset(frame, resultRect);
NS_ENSURE_SUCCESS(rv, rv);
// account for any additional frames
while ((frame = frame->GetNextContinuation()) != nullptr) {
nsRect frameRect(nsPoint(0, 0), frame->GetRect().Size());
rv = ConvertToRootViewRelativeOffset(frame, frameRect);
rv = ConvertToRootRelativeOffset(frame, frameRect);
NS_ENSURE_SUCCESS(rv, rv);
resultRect.UnionRect(resultRect, frameRect);
}
@ -1017,7 +1017,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
// get the starting frame rect
nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size());
rv = ConvertToRootViewRelativeOffset(firstFrame, rect);
rv = ConvertToRootRelativeOffset(firstFrame, rect);
NS_ENSURE_SUCCESS(rv, rv);
nsRect frameRect = rect;
nsPoint ptOffset;
@ -1059,7 +1059,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
}
}
frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
rv = ConvertToRootViewRelativeOffset(frame, frameRect);
rv = ConvertToRootRelativeOffset(frame, frameRect);
NS_ENSURE_SUCCESS(rv, rv);
if (frame != lastFrame) {
// not last frame, so just add rect to previous result
@ -1125,7 +1125,7 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
lineBreakType);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == aEvent->mInput.mOffset) {
rv = ConvertToRootViewRelativeOffset(caretFrame, caretRect);
rv = ConvertToRootRelativeOffset(caretFrame, caretRect);
NS_ENSURE_SUCCESS(rv, rv);
nscoord appUnitsPerDevPixel =
caretFrame->PresContext()->AppUnitsPerDevPixel();
@ -1186,7 +1186,7 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
rect.height = fontHeight;
}
rv = ConvertToRootViewRelativeOffset(frame, rect);
rv = ConvertToRootRelativeOffset(frame, rect);
NS_ENSURE_SUCCESS(rv, rv);
aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
@ -1547,18 +1547,21 @@ ContentEventHandler::GetStartFrameAndOffset(const nsRange* aRange,
}
nsresult
ContentEventHandler::ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
nsRect& aRect)
ContentEventHandler::ConvertToRootRelativeOffset(nsIFrame* aFrame,
nsRect& aRect)
{
NS_ASSERTION(aFrame, "aFrame must not be null");
nsView* view = nullptr;
nsPoint posInView;
aFrame->GetOffsetFromView(posInView, &view);
if (!view) {
nsPresContext* rootPresContext = aFrame->PresContext()->GetRootPresContext();
if (NS_WARN_IF(!rootPresContext)) {
return NS_ERROR_FAILURE;
}
aRect += posInView + view->GetOffsetTo(nullptr);
nsIFrame* rootFrame = rootPresContext->PresShell()->GetRootFrame();
if (NS_WARN_IF(!rootFrame)) {
return NS_ERROR_FAILURE;
}
aRect = nsLayoutUtils::TransformFrameRectToAncestor(aFrame, aRect, rootFrame);
return NS_OK;
}

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

@ -136,9 +136,10 @@ protected:
nsresult GetStartFrameAndOffset(const nsRange* aRange,
nsIFrame*& aFrame,
int32_t& aOffsetInFrame);
// Convert the frame relative offset to the root view relative offset.
nsresult ConvertToRootViewRelativeOffset(nsIFrame* aFrame,
nsRect& aRect);
// Convert the frame relative offset to the root frame of the root presContext
// relative offset.
nsresult ConvertToRootRelativeOffset(nsIFrame* aFrame,
nsRect& aRect);
// Expand aXPOffset to the nearest offset in cluster boundary. aForward is
// true, it is expanded to forward.
nsresult ExpandToClusterBoundary(nsIContent* aContent, bool aForward,

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

@ -582,7 +582,11 @@ public:
// 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.
// mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
// and eQueryEditorRect. The coordinates is system coordinates relative to
// the top level widget of mFocusedWidget. E.g., if a <xul:panel> which
// is owned by a window has focused editor, the offset of mRect is relative
// to the owner window, not the <xul:panel>.
mozilla::LayoutDeviceIntRect mRect;
// The return widget has the caret. This is set at all query events.
nsIWidget* mFocusedWidget;

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

@ -2309,6 +2309,86 @@ function runCharAtPointAtOutsideTest()
}
}
function runCSSTransformTest()
{
textarea.focus();
textarea.value = "some text";
textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect,
"runCSSTransformTest: editorRect")) {
return;
}
var firstCharRect = synthesizeQueryTextRect(0, 1);
if (!checkQueryContentResult(firstCharRect,
"runCSSTransformTest: firstCharRect")) {
return;
}
var lastCharRect = synthesizeQueryTextRect(textarea.value.length - 1, textarea.value.length);
if (!checkQueryContentResult(lastCharRect,
"runCSSTransformTest: lastCharRect")) {
return;
}
var caretRect = synthesizeQueryCaretRect(textarea.selectionStart);
if (!checkQueryContentResult(caretRect,
"runCSSTransformTest: caretRect")) {
return;
}
var caretRectBeforeFirstChar = synthesizeQueryCaretRect(0);
if (!checkQueryContentResult(caretRectBeforeFirstChar,
"runCSSTransformTest: caretRectBeforeFirstChar")) {
return;
}
try {
textarea.style.transform = "translate(10px, 15px)";
function movedRect(aRect, aX, aY)
{
return { left: aRect.left + aX, top: aRect.top + aY, width: aRect.width, height: aRect.height }
}
var editorRectTranslated = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRectTranslated,
"runCSSTransformTest: editorRectTranslated") ||
!checkRect(editorRectTranslated, movedRect(editorRect, 10, 15),
"runCSSTransformTest: editorRectTranslated")) {
return;
}
var firstCharRectTranslated = synthesizeQueryTextRect(0, 1);
if (!checkQueryContentResult(firstCharRectTranslated,
"runCSSTransformTest: firstCharRectTranslated") ||
!checkRect(firstCharRectTranslated, movedRect(firstCharRect, 10, 15),
"runCSSTransformTest: firstCharRectTranslated")) {
return;
}
var lastCharRectTranslated = synthesizeQueryTextRect(textarea.value.length - 1, textarea.value.length);
if (!checkQueryContentResult(lastCharRectTranslated,
"runCSSTransformTest: lastCharRectTranslated") ||
!checkRect(lastCharRectTranslated, movedRect(lastCharRect, 10, 15),
"runCSSTransformTest: lastCharRectTranslated")) {
return;
}
var caretRectTranslated = synthesizeQueryCaretRect(textarea.selectionStart);
if (!checkQueryContentResult(caretRectTranslated,
"runCSSTransformTest: caretRectTranslated") ||
!checkRect(caretRectTranslated, movedRect(caretRect, 10, 15),
"runCSSTransformTest: caretRectTranslated")) {
return;
}
var caretRectBeforeFirstCharTranslated = synthesizeQueryCaretRect(0);
if (!checkQueryContentResult(caretRectBeforeFirstCharTranslated,
"runCSSTransformTest: caretRectBeforeFirstCharTranslated") ||
!checkRect(caretRectBeforeFirstCharTranslated, movedRect(caretRectBeforeFirstChar, 10, 15),
"runCSSTransformTest: caretRectBeforeFirstCharTranslated")) {
return;
}
// XXX It's too difficult to check the result with scale and rotate...
} finally {
textarea.style.transform = "";
}
}
function runBug722639Test()
{
textarea.focus();
@ -4522,6 +4602,7 @@ function runTest()
runCompositionEventTest();
runCharAtPointTest(textarea, "textarea in the document");
runCharAtPointAtOutsideTest();
runCSSTransformTest();
runBug722639Test();
runForceCommitTest();
runNestedSettingValue();