Bug 1261671 ContentEventHandler::ConvertToRootRelativeOffset() should resolve CSS transform per same FullZoom level documents WIP
MozReview-Commit-ID: 6PuVtyJYfWz
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -1904,26 +1904,46 @@ ContentEventHandler::GetStartFrameAndOff
}
nsresult
ContentEventHandler::ConvertToRootRelativeOffset(nsIFrame* aFrame,
nsRect& aRect)
{
NS_ASSERTION(aFrame, "aFrame must not be null");
- nsPresContext* rootPresContext = aFrame->PresContext()->GetRootPresContext();
- if (NS_WARN_IF(!rootPresContext)) {
- return NS_ERROR_FAILURE;
+ nsIFrame* frame = aFrame;
+ for (;;) {
+ nsPresContext* ancestor =
+ frame->PresContext()->GetTopLevelSameAppUnitsPerDevPixelPresContext();
+ nsIFrame* ancestorRootFrame = ancestor->PresShell()->GetRootFrame();
+ if (NS_WARN_IF(!ancestorRootFrame)) {
+ return NS_ERROR_FAILURE;
+ }
+ MOZ_ASSERT(ancestorRootFrame->GetPosition() == nsPoint(0, 0));
+ MOZ_ASSERT(ancestorRootFrame->PresContext() == ancestor);
+ printf("aRect={ x=%d, y=%d, width=%d, height=%d\n", aRect.x, aRect.y, aRect.width, aRect.height);
+ aRect = nsLayoutUtils::TransformFrameRectToAncestor(frame, aRect,
+ ancestorRootFrame);
+ if (ancestor->IsRoot()) {
+ break;
+ }
+ frame = ancestorRootFrame->GetParent();
+ if (frame) {
+ MOZ_ASSERT(ancestorRootFrame->PresContext() != frame->PresContext());
+ MOZ_ASSERT(ancestorRootFrame->GetSize() == frame->GetSize());
+ } else {
+ nsPoint pt;
+ frame = nsLayoutUtils::GetCrossDocParentFrame(ancestorRootFrame, &pt);
+ if (NS_WARN_IF(!frame)) {
+ return NS_ERROR_FAILURE;
+ }
+ aRect.MoveBy(pt);
+ }
}
- nsIFrame* rootFrame = rootPresContext->PresShell()->GetRootFrame();
- if (NS_WARN_IF(!rootFrame)) {
- return NS_ERROR_FAILURE;
- }
-
- aRect = nsLayoutUtils::TransformFrameRectToAncestor(aFrame, aRect, rootFrame);
+ printf("aRect={ x=%d, y=%d, width=%d, height=%d\n\n\n", aRect.x, aRect.y, aRect.width, aRect.height);
return NS_OK;
}
static void AdjustRangeForSelection(nsIContent* aRoot,
nsINode** aNode,
int32_t* aNodeOffset)
{
nsINode* node = *aNode;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1046,17 +1046,17 @@ nsPresContext::Observe(nsISupports* aSub
return NS_DispatchToCurrentThread(runnable);
}
NS_WARNING("unrecognized topic in nsPresContext::Observe");
return NS_ERROR_FAILURE;
}
nsPresContext*
-nsPresContext::GetParentPresContext()
+nsPresContext::GetParentPresContext() const
{
nsIPresShell* shell = GetPresShell();
if (shell) {
nsViewManager* viewManager = shell->GetViewManager();
if (viewManager) {
nsView* view = viewManager->GetRootView();
if (view) {
view = view->GetParent(); // anonymous inner view
@@ -1084,16 +1084,31 @@ nsPresContext::GetToplevelContentDocumen
for (;;) {
nsPresContext* parent = pc->GetParentPresContext();
if (!parent || parent->IsChrome())
return pc;
pc = parent;
}
}
+nsPresContext*
+nsPresContext::GetTopLevelSameAppUnitsPerDevPixelPresContext() const
+{
+ nsPresContext* pc = const_cast<nsPresContext*>(this);
+ int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel();
+ for (;;) {
+ nsPresContext* parent = pc->GetParentPresContext();
+ if (!parent || parent->AppUnitsPerDevPixel() != appUnitsPerDevPixel) {
+ break;
+ }
+ pc = parent;
+ }
+ return pc;
+}
+
nsIWidget*
nsPresContext::GetNearestWidget(nsPoint* aOffset)
{
NS_ENSURE_TRUE(mShell, nullptr);
nsIFrame* frame = mShell->GetRootFrame();
NS_ENSURE_TRUE(frame, nullptr);
return frame->GetView()->GetNearestWidget(aOffset);
}
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -178,25 +178,32 @@ public:
}
nsIPresShell* GetPresShell() const { return mShell; }
/**
* Returns the parent prescontext for this one. Returns null if this is a
* root.
*/
- nsPresContext* GetParentPresContext();
+ nsPresContext* GetParentPresContext() const;
/**
* Returns the prescontext of the toplevel content document that contains
* this presentation, or null if there isn't one.
*/
nsPresContext* GetToplevelContentDocumentPresContext();
/**
+ * Returns an ancestor presentation context whose app units per device pixel
+ * is same as the instance's. If the parent presentation context has
+ * different value, this returns itself.
+ */
+ nsPresContext* GetTopLevelSameAppUnitsPerDevPixelPresContext() const;
+
+ /**
* Returns the nearest widget for the root frame of this.
*
* @param aOffset If non-null the offset from the origin of the root
* frame's view to the widget's origin (usually positive)
* expressed in appunits of this will be returned in
* aOffset.
*/
nsIWidget* GetNearestWidget(nsPoint* aOffset = nullptr);
@@ -588,17 +595,17 @@ public:
if (HasCachedStyleData()) {
// Media queries could have changed, since we changed the meaning
// of 'em' units in them.
MediaFeatureValuesChanged(eRestyle_ForceDescendants,
NS_STYLE_HINT_REFLOW);
}
}
- float GetFullZoom() { return mFullZoom; }
+ float GetFullZoom() const { return mFullZoom; }
void SetFullZoom(float aZoom);
nscoord GetAutoQualityMinFontSize() {
return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
}
/**
* Return the device's screen size in inches, for font size