Bug 1828295 part 1: Fix HyperTextAccessible::GetCaretRect when the title bar is enabled. r=morgan

I don't quite know which part of this was breaking, but the coordinates were quite wrong in the parent process.
They were wrong enough that when we adjusted for the character height, we ended up with a negative height in the resulting rect.
This code is now more similar to how we do this in LocalAccessible::BoundsInAppUnits.
This should also take CSS transforms into account in most cases where we weren't previously, though perhaps not for some iframe transforms.

Differential Revision: https://phabricator.services.mozilla.com/D176619
This commit is contained in:
James Teh 2023-05-31 10:04:18 +00:00
parent 8bed3d22d7
commit f34c3edf90

View File

@ -33,6 +33,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIScrollableFrame.h"
#include "nsIMathMLFrame.h"
#include "nsLayoutUtils.h"
#include "nsRange.h"
#include "nsTextFragment.h"
#include "mozilla/Assertions.h"
@ -731,20 +732,25 @@ LayoutDeviceIntRect HyperTextAccessible::GetCaretRect(nsIWidget** aWidget) {
nsIFrame* frame = caret->GetGeometry(&rect);
if (!frame || rect.IsEmpty()) return LayoutDeviceIntRect();
nsPoint offset;
// Offset from widget origin to the frame origin, which includes chrome
// on the widget.
*aWidget = frame->GetNearestWidget(offset);
NS_ENSURE_TRUE(*aWidget, LayoutDeviceIntRect());
rect.MoveBy(offset);
LayoutDeviceIntRect caretRect = LayoutDeviceIntRect::FromUnknownRect(
rect.ToOutsidePixels(frame->PresContext()->AppUnitsPerDevPixel()));
// clang-format off
// ((content screen origin) - (content offset in the widget)) = widget origin on the screen
// clang-format on
caretRect.MoveBy((*aWidget)->WidgetToScreenOffset() -
(*aWidget)->GetClientOffset());
PresShell* presShell = mDoc->PresShellPtr();
// Transform rect to be relative to the root frame.
nsIFrame* rootFrame = presShell->GetRootFrame();
rect = nsLayoutUtils::TransformFrameRectToAncestor(frame, rect, rootFrame);
// We need to inverse translate with the offset of the edge of the visual
// viewport from top edge of the layout viewport.
nsPoint viewportOffset = presShell->GetVisualViewportOffset() -
presShell->GetLayoutViewportOffset();
rect.MoveBy(-viewportOffset);
// We need to take into account a non-1 resolution set on the presshell.
// This happens with async pinch zooming. Here we scale the bounds before
// adding the screen-relative offset.
rect.ScaleRoundOut(presShell->GetResolution());
// Now we need to put the rect in absolute screen coords.
nsRect rootScreenRect = rootFrame->GetScreenRectInAppUnits();
rect.MoveBy(rootScreenRect.TopLeft());
// Finally, convert from app units.
auto caretRect = LayoutDeviceIntRect::FromAppUnitsToNearest(
rect, presShell->GetPresContext()->AppUnitsPerDevPixel());
// Correct for character size, so that caret always matches the size of
// the character. This is important for font size transitions, and is
@ -763,6 +769,8 @@ LayoutDeviceIntRect HyperTextAccessible::GetCaretRect(nsIWidget** aWidget) {
if (!charRect.IsEmpty()) {
caretRect.SetTopEdge(charRect.Y());
}
*aWidget = frame->GetNearestWidget();
return caretRect;
}