Bug 1224015 - Part 1: nsLayoutUtils functions do not account for nsPresShell resolution r=tnikkel

This commit is contained in:
Randall Barker 2015-11-26 20:51:13 -06:00
parent bc0cfae6b7
commit 7b02572a95
9 changed files with 88 additions and 27 deletions

View File

@ -7659,7 +7659,7 @@ nsContentUtils::ToWidgetPoint(const CSSPoint& aPoint,
nsPresContext* aPresContext)
{
return LayoutDeviceIntPoint::FromAppUnitsRounded(
CSSPoint::ToAppUnits(aPoint) + aOffset,
(CSSPoint::ToAppUnits(aPoint) + aOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution()),
aPresContext->AppUnitsPerDevPixel());
}

View File

@ -935,6 +935,10 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
nsPoint pt =
LayoutDevicePixel::ToAppUnits(aPoint, aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
if (aPresContext->PresShell()) {
pt = pt.RemoveResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
}
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());

View File

@ -422,21 +422,7 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
return input;
}
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
if (!content) {
return input;
}
// First, scale inversely by the root content document's pres shell
// resolution to cancel the scale-to-resolution transform that the
// compositor adds to the layer with the pres shell resolution. The points
// sent to Gecko by APZ don't have this transform unapplied (unlike other
// compositor-side transforms) because APZ doesn't know about it.
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
input = input / shell->GetResolution();
}
// Now apply the callback-transform.
// Apply the callback-transform.
// XXX: technically we need to walk all the way up the layer tree from the layer
// represented by |aGuid.mScrollId| up to the root of the layer tree and apply
// the input transforms at each level in turn. However, it is quite difficult
@ -447,9 +433,19 @@ APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
// some things transformed improperly. In practice we should rarely hit scenarios
// where any of this matters, so I'm skipping it for now and just doing the single
// transform for the layer that the input hit.
void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
if (property) {
CSSPoint delta = (*static_cast<CSSPoint*>(property));
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
if (content) {
void* property = content->GetProperty(nsGkAtoms::apzCallbackTransform);
CSSPoint delta = property ? (*static_cast<CSSPoint*>(property)) : CSSPoint(0.0f, 0.0f);
// The delta is in root content document coordinate space while the
// aInput point is in root document coordinate space so convert the
// delta to root document space before adding it to the aInput point.
float resolution = 1.0f;
if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
resolution = shell->GetResolution();
}
delta.x = delta.x * resolution;
delta.y = delta.y * resolution;
input += delta;
}
return input;

View File

@ -147,6 +147,14 @@ ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint,
}
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
// CalculateRectToZoomTo performs a hit test on the frame associated with the
// Root Content Document. Unfortunately that frame does not know about the
// resolution of the document and so we must remove it before calculating
// the zoomToRect.
nsIPresShell* presShell = document->GetShell();
const float resolution = presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f;
point.x = point.x / resolution;
point.y = point.y / resolution;
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
uint32_t presShellId;

View File

@ -37,6 +37,11 @@ struct nsPoint : public mozilla::gfx::BasePoint<nscoord, nsPoint> {
*/
MOZ_WARN_UNUSED_RESULT inline nsPoint
ScaleToOtherAppUnits(int32_t aFromAPP, int32_t aToAPP) const;
MOZ_WARN_UNUSED_RESULT inline nsPoint
RemoveResolution(const float resolution) const;
MOZ_WARN_UNUSED_RESULT inline nsPoint
ApplyResolution(const float resolution) const;
};
inline nsPoint ToAppUnits(const nsIntPoint& aPoint, nscoord aAppUnitsPerPixel);
@ -68,6 +73,28 @@ nsPoint::ScaleToOtherAppUnits(int32_t aFromAPP, int32_t aToAPP) const
return *this;
}
inline nsPoint
nsPoint::RemoveResolution(const float resolution) const {
if (resolution != 1.0f) {
nsPoint point;
point.x = NSToCoordRound(NSCoordToFloat(x) / resolution);
point.y = NSToCoordRound(NSCoordToFloat(y) / resolution);
return point;
}
return *this;
}
inline nsPoint
nsPoint::ApplyResolution(const float resolution) const {
if (resolution != 1.0f) {
nsPoint point;
point.x = NSToCoordRound(NSCoordToFloat(x) * resolution);
point.y = NSToCoordRound(NSCoordToFloat(y) * resolution);
return point;
}
return *this;
}
// app units are integer multiples of pixels, so no rounding needed
inline nsPoint
ToAppUnits(const nsIntPoint& aPoint, nscoord aAppUnitsPerPixel)

View File

@ -140,10 +140,10 @@ typedef struct CapturingContentInfo {
mozilla::StaticRefPtr<nsIContent> mContent;
} CapturingContentInfo;
// 327d78a0-0680-4709-b209-1cf9578720e6
// 5023beaa-0e54-4fc7-b9dc-0344dc4fb8be
#define NS_IPRESSHELL_IID \
{ 0x327d78a0, 0x0680, 0x4709, \
{ 0xb2, 0x09, 0x1c, 0xf9, 0x57, 0x87, 0x20, 0xe6 } }
{ 0x5023beaa, 0x0e54, 0x4fc7, \
{ 0xb9, 0xdc, 0x03, 0x44, 0xdc, 0x4f, 0xb8, 0xbe } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@ -1416,6 +1416,7 @@ public:
virtual nsresult SetResolution(float aResolution) = 0;
float GetResolution() { return mResolution.valueOr(1.0); }
virtual float GetCumulativeResolution() = 0;
virtual float GetCumulativeScaleResolution() = 0;
/**
* Was the current resolution set by the user or just default initialized?

View File

@ -2111,7 +2111,9 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
nsPresContext* presContext = aFrame->PresContext();
nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
presContext->DevPixelsToAppUnits(aPoint.y));
return pt - view->ViewToWidgetOffset();
pt = pt - view->ViewToWidgetOffset();
pt = pt.RemoveResolution(presContext->PresShell()->GetCumulativeScaleResolution());
return pt;
}
}
@ -2146,6 +2148,10 @@ nsLayoutUtils::GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
int32_t rootAPD = rootFrame->PresContext()->AppUnitsPerDevPixel();
int32_t localAPD = aFrame->PresContext()->AppUnitsPerDevPixel();
widgetToView = widgetToView.ScaleToOtherAppUnits(rootAPD, localAPD);
nsIPresShell* shell = aFrame->PresContext()->PresShell();
// XXX Bug 1224748 - Update nsLayoutUtils functions to correctly handle nsPresShell resolution
widgetToView = widgetToView.RemoveResolution(shell->GetCumulativeScaleResolution());
/* If we encountered a transform, we can't do simple arithmetic to figure
* out how to convert back to aFrame's coordinates and must use the CTM.
@ -2893,8 +2899,9 @@ nsLayoutUtils::TranslateViewToWidget(nsPresContext* aPresContext,
return LayoutDeviceIntPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
}
LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(aPt.x + viewOffset.x),
aPresContext->AppUnitsToDevPixels(aPt.y + viewOffset.y));
nsPoint pt = (aPt + viewOffset).ApplyResolution(aPresContext->PresShell()->GetCumulativeScaleResolution());
LayoutDeviceIntPoint relativeToViewWidget(aPresContext->AppUnitsToDevPixels(pt.x),
aPresContext->AppUnitsToDevPixels(pt.y));
return relativeToViewWidget + WidgetToWidgetOffset(viewWidget, aWidget);
}

View File

@ -5351,6 +5351,22 @@ float PresShell::GetCumulativeResolution()
return resolution;
}
float PresShell::GetCumulativeScaleResolution()
{
float resolution = 1.0;
nsIPresShell* currentShell = this;
while (currentShell) {
resolution *= currentShell->ScaleToResolution() ? currentShell->GetResolution() : 1.0f;
nsPresContext* parentCtx = currentShell->GetPresContext()->GetParentPresContext();
if (parentCtx) {
currentShell = parentCtx->PresShell();
} else {
currentShell = nullptr;
}
}
return resolution;
}
void PresShell::SetRenderingState(const RenderingState& aState)
{
if (mRenderFlags != aState.mRenderFlags) {
@ -7097,8 +7113,9 @@ PresShell::HandleEvent(nsIFrame* aFrame,
// document that is being captured.
retargetEventDoc = capturingContent->GetCrossShadowCurrentDoc();
#ifdef ANDROID
} else if (aEvent->mClass == eTouchEventClass ||
(aEvent->AsMouseEvent() && aEvent->AsMouseEvent()->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH)) {
} else if ((aEvent->mClass == eTouchEventClass) ||
(aEvent->mClass == eMouseEventClass) ||
(aEvent->mClass == eWheelEventClass)) {
retargetEventDoc = GetTouchEventTargetDocument();
#endif
}

View File

@ -218,6 +218,7 @@ public:
}
virtual bool ScaleToResolution() const override;
virtual float GetCumulativeResolution() override;
virtual float GetCumulativeScaleResolution() override;
//nsIViewObserver interface