mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 907743 - Align display port to tile boundaries when tiles are enabled. r=botond,kats
This aligns display ports to tile boundaries, taking care to compensate for the difference between the requested scroll position and the actual scroll position.
This commit is contained in:
parent
df8953eecb
commit
2b33da1618
@ -1482,9 +1482,8 @@ nsDOMWindowUtils::SuppressEventHandling(bool aSuppress)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aScrollY)
|
||||
{
|
||||
static nsresult
|
||||
getScrollXYAppUnits(nsWeakPtr mWindow, bool aFlushLayout, nsPoint& aScrollPos) {
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
@ -1499,15 +1498,22 @@ nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aSc
|
||||
doc->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
|
||||
nsPoint scrollPos(0,0);
|
||||
nsIPresShell *presShell = doc->GetShell();
|
||||
if (presShell) {
|
||||
nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
scrollPos = sf->GetScrollPosition();
|
||||
aScrollPos = sf->GetScrollPosition();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aScrollY)
|
||||
{
|
||||
nsPoint scrollPos(0,0);
|
||||
nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
|
||||
*aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
|
||||
|
||||
@ -1531,6 +1537,18 @@ nsDOMWindowUtils::ScrollToCSSPixelsApproximate(float aX, float aY, bool* aRetVal
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout, float* aScrollX, float* aScrollY)
|
||||
{
|
||||
nsPoint scrollPos(0,0);
|
||||
nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
*aScrollX = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.x);
|
||||
*aScrollY = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.y);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout, int32_t* aWidth,
|
||||
int32_t* aHeight)
|
||||
|
@ -43,7 +43,7 @@ interface nsIDOMEventTarget;
|
||||
interface nsIRunnable;
|
||||
interface nsICompositionStringSynthesizer;
|
||||
|
||||
[scriptable, uuid(e12df416-e3e0-4177-b936-fa106f62ae3f)]
|
||||
[scriptable, uuid(3772df78-905f-40cf-952f-e4954c63d0ec)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -652,6 +652,14 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
*/
|
||||
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
|
||||
|
||||
/**
|
||||
* Returns the scroll position of the window's currently loaded document.
|
||||
*
|
||||
* @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
|
||||
* @see nsIDOMWindow::scrollX/Y
|
||||
*/
|
||||
void getScrollXYFloat(in boolean aFlushLayout, out float aScrollX, out float aScrollY);
|
||||
|
||||
/**
|
||||
* Sets the scroll position of the root scroll frame of the window.
|
||||
* Returns true on success, false on error (if the window didn't have a root
|
||||
|
@ -1559,44 +1559,49 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
return true;
|
||||
}
|
||||
|
||||
CSSRect cssCompositedRect = aFrameMetrics.CalculateCompositedRectInCssPixels();
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
|
||||
FrameMetrics newMetrics = aFrameMetrics;
|
||||
APZCCallbackHelper::UpdateRootFrame(utils, newMetrics);
|
||||
|
||||
CSSRect cssCompositedRect = newMetrics.CalculateCompositedRectInCssPixels();
|
||||
// The BrowserElementScrolling helper must know about these updated metrics
|
||||
// for other functions it performs, such as double tap handling.
|
||||
// Note, %f must not be used because it is locale specific!
|
||||
nsCString data;
|
||||
data.AppendPrintf("{ \"x\" : %d", NS_lround(aFrameMetrics.mScrollOffset.x));
|
||||
data.AppendPrintf(", \"y\" : %d", NS_lround(aFrameMetrics.mScrollOffset.y));
|
||||
data.AppendPrintf("{ \"x\" : %d", NS_lround(newMetrics.mScrollOffset.x));
|
||||
data.AppendPrintf(", \"y\" : %d", NS_lround(newMetrics.mScrollOffset.y));
|
||||
data.AppendLiteral(", \"viewport\" : ");
|
||||
data.AppendLiteral("{ \"width\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mViewport.width);
|
||||
data.AppendFloat(newMetrics.mViewport.width);
|
||||
data.AppendLiteral(", \"height\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mViewport.height);
|
||||
data.AppendFloat(newMetrics.mViewport.height);
|
||||
data.AppendLiteral(" }");
|
||||
data.AppendLiteral(", \"displayPort\" : ");
|
||||
data.AppendLiteral("{ \"x\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mDisplayPort.x);
|
||||
data.AppendFloat(newMetrics.mDisplayPort.x);
|
||||
data.AppendLiteral(", \"y\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mDisplayPort.y);
|
||||
data.AppendFloat(newMetrics.mDisplayPort.y);
|
||||
data.AppendLiteral(", \"width\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mDisplayPort.width);
|
||||
data.AppendFloat(newMetrics.mDisplayPort.width);
|
||||
data.AppendLiteral(", \"height\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mDisplayPort.height);
|
||||
data.AppendFloat(newMetrics.mDisplayPort.height);
|
||||
data.AppendLiteral(" }");
|
||||
data.AppendLiteral(", \"compositionBounds\" : ");
|
||||
data.AppendPrintf("{ \"x\" : %d", aFrameMetrics.mCompositionBounds.x);
|
||||
data.AppendPrintf(", \"y\" : %d", aFrameMetrics.mCompositionBounds.y);
|
||||
data.AppendPrintf(", \"width\" : %d", aFrameMetrics.mCompositionBounds.width);
|
||||
data.AppendPrintf(", \"height\" : %d", aFrameMetrics.mCompositionBounds.height);
|
||||
data.AppendPrintf("{ \"x\" : %d", newMetrics.mCompositionBounds.x);
|
||||
data.AppendPrintf(", \"y\" : %d", newMetrics.mCompositionBounds.y);
|
||||
data.AppendPrintf(", \"width\" : %d", newMetrics.mCompositionBounds.width);
|
||||
data.AppendPrintf(", \"height\" : %d", newMetrics.mCompositionBounds.height);
|
||||
data.AppendLiteral(" }");
|
||||
data.AppendLiteral(", \"cssPageRect\" : ");
|
||||
data.AppendLiteral("{ \"x\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mScrollableRect.x);
|
||||
data.AppendFloat(newMetrics.mScrollableRect.x);
|
||||
data.AppendLiteral(", \"y\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mScrollableRect.y);
|
||||
data.AppendFloat(newMetrics.mScrollableRect.y);
|
||||
data.AppendLiteral(", \"width\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mScrollableRect.width);
|
||||
data.AppendFloat(newMetrics.mScrollableRect.width);
|
||||
data.AppendLiteral(", \"height\" : ");
|
||||
data.AppendFloat(aFrameMetrics.mScrollableRect.height);
|
||||
data.AppendFloat(newMetrics.mScrollableRect.height);
|
||||
data.AppendLiteral(" }");
|
||||
data.AppendLiteral(", \"cssCompositedRect\" : ");
|
||||
data.AppendLiteral("{ \"width\" : ");
|
||||
@ -1608,19 +1613,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
|
||||
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
|
||||
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
|
||||
APZCCallbackHelper::UpdateRootFrame(utils, aFrameMetrics);
|
||||
|
||||
mLastMetrics = aFrameMetrics;
|
||||
|
||||
// ScrollWindowTo() can make some small adjustments to the offset before
|
||||
// actually scrolling the window. To ensure that the scroll offset stored
|
||||
// in mLastMetrics is the same as the offset stored in the window,
|
||||
// re-query the latter.
|
||||
CSSIntPoint actualScrollOffset;
|
||||
utils->GetScrollXY(false, &actualScrollOffset.x, &actualScrollOffset.y);
|
||||
mLastMetrics.mScrollOffset = actualScrollOffset;
|
||||
mLastMetrics = newMetrics;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ EXPORTS += [
|
||||
'opengl/TexturePoolOGL.h',
|
||||
'ReadbackLayer.h',
|
||||
'SharedTextureImage.h',
|
||||
'TiledLayerBuffer.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
|
@ -137,10 +137,8 @@ public:
|
||||
|
||||
// Return the actual scroll value so we can use it to filter
|
||||
// out scroll messages triggered by setting the display port.
|
||||
CSSIntPoint actualScrollOffset;
|
||||
utils->GetScrollXY(false, &actualScrollOffset.x, &actualScrollOffset.y);
|
||||
if (mLastOffsetOut) {
|
||||
*mLastOffsetOut = actualScrollOffset;
|
||||
*mLastOffsetOut = mozilla::gfx::RoundedToInt(mFrameMetrics.mScrollOffset);
|
||||
}
|
||||
if (mLastScrollIdOut) {
|
||||
mLastScrollIdOut->mScrollId = mFrameMetrics.mScrollId;
|
||||
|
@ -4,10 +4,12 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "APZCCallbackHelper.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "TiledLayerBuffer.h" // For TILEDLAYERBUFFER_TILE_SIZE
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
@ -24,9 +26,69 @@ APZCCallbackHelper::HasValidPresShellId(nsIDOMWindowUtils* aUtils,
|
||||
return NS_SUCCEEDED(rv) && aMetrics.mPresShellId == presShellId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands a given rectangle to the next tile boundary. Note, this will
|
||||
* expand the rectangle if it is already on tile boundaries.
|
||||
*/
|
||||
static CSSRect ExpandDisplayPortToTileBoundaries(
|
||||
const CSSRect& aDisplayPort,
|
||||
const CSSToLayerScale& aLayerPixelsPerCSSPixel)
|
||||
{
|
||||
// Convert the given rect to layer coordinates so we can inflate to tile
|
||||
// boundaries (layer space corresponds to texture pixel space here).
|
||||
LayerRect displayPortInLayerSpace = aDisplayPort * aLayerPixelsPerCSSPixel;
|
||||
|
||||
// Inflate the rectangle by 1 so that we always push to the next tile
|
||||
// boundary. This is desirable to stop from having a rectangle with a
|
||||
// moving origin occasionally being smaller when it coincidentally lines
|
||||
// up to tile boundaries.
|
||||
displayPortInLayerSpace.Inflate(1);
|
||||
|
||||
// Now nudge the rectangle to the nearest equal or larger tile boundary.
|
||||
gfxFloat left = TILEDLAYERBUFFER_TILE_SIZE
|
||||
* floor(displayPortInLayerSpace.x / TILEDLAYERBUFFER_TILE_SIZE);
|
||||
gfxFloat top = TILEDLAYERBUFFER_TILE_SIZE
|
||||
* floor(displayPortInLayerSpace.y / TILEDLAYERBUFFER_TILE_SIZE);
|
||||
gfxFloat right = TILEDLAYERBUFFER_TILE_SIZE
|
||||
* ceil(displayPortInLayerSpace.XMost() / TILEDLAYERBUFFER_TILE_SIZE);
|
||||
gfxFloat bottom = TILEDLAYERBUFFER_TILE_SIZE
|
||||
* ceil(displayPortInLayerSpace.YMost() / TILEDLAYERBUFFER_TILE_SIZE);
|
||||
|
||||
displayPortInLayerSpace = LayerRect(left, top, right - left, bottom - top);
|
||||
CSSRect displayPort = displayPortInLayerSpace / aLayerPixelsPerCSSPixel;
|
||||
|
||||
return displayPort;
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeAlignAndClampDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics,
|
||||
const CSSPoint& aActualScrollOffset)
|
||||
{
|
||||
// Correct the display-port by the difference between the requested scroll
|
||||
// offset and the resulting scroll offset after setting the requested value.
|
||||
CSSRect& displayPort = aFrameMetrics.mDisplayPort;
|
||||
displayPort += aActualScrollOffset - aFrameMetrics.mScrollOffset;
|
||||
|
||||
// Expand the display port to the next tile boundaries, if tiled thebes layers
|
||||
// are enabled.
|
||||
if (Preferences::GetBool("layers.force-tiles")) {
|
||||
// aFrameMetrics.mZoom is the zoom amount reported by the APZC,
|
||||
// scale by ScreenToLayerScale to get the gecko zoom amount
|
||||
displayPort =
|
||||
ExpandDisplayPortToTileBoundaries(displayPort + aActualScrollOffset,
|
||||
aFrameMetrics.mZoom * ScreenToLayerScale(1))
|
||||
- aActualScrollOffset;
|
||||
}
|
||||
|
||||
// Finally, clamp the display port to the scrollable rect.
|
||||
CSSRect scrollableRect = aFrameMetrics.mScrollableRect;
|
||||
displayPort = scrollableRect.ClampRect(displayPort + aActualScrollOffset)
|
||||
- aActualScrollOffset;
|
||||
}
|
||||
|
||||
void
|
||||
APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
|
||||
const FrameMetrics& aMetrics)
|
||||
FrameMetrics& aMetrics)
|
||||
{
|
||||
// Precondition checks
|
||||
MOZ_ASSERT(aUtils);
|
||||
@ -47,6 +109,17 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils,
|
||||
// Scroll the window to the desired spot
|
||||
aUtils->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset.x, aMetrics.mScrollOffset.y, nullptr);
|
||||
|
||||
// Re-query the scroll position after setting it so that anything that relies on it
|
||||
// can have an accurate value.
|
||||
CSSPoint actualScrollOffset;
|
||||
aUtils->GetScrollXYFloat(false, &actualScrollOffset.x, &actualScrollOffset.y);
|
||||
|
||||
// Correct the display port due to the difference between mScrollOffset and the
|
||||
// actual scroll offset, possibly align it to tile boundaries (if tiled layers are
|
||||
// enabled), and clamp it to the scrollable rect.
|
||||
MaybeAlignAndClampDisplayPort(aMetrics, actualScrollOffset);
|
||||
aMetrics.mScrollOffset = actualScrollOffset;
|
||||
|
||||
// The mZoom variable on the frame metrics stores the CSS-to-screen scale for this
|
||||
// frame. This scale includes all of the (cumulative) resolutions set on the presShells
|
||||
// from the root down to this frame. However, when setting the resolution, we only
|
||||
|
@ -33,9 +33,13 @@ public:
|
||||
const FrameMetrics& aMetrics);
|
||||
|
||||
/* Applies the scroll and zoom parameters from the given FrameMetrics object to
|
||||
the root frame corresponding to the given DOMWindowUtils. */
|
||||
the root frame corresponding to the given DOMWindowUtils. If tiled thebes
|
||||
layers are enabled, this will align the displayport to tile boundaries.
|
||||
Setting the scroll position can cause some small adjustments to be made
|
||||
to the actual scroll position. aMetrics' display port and scroll position
|
||||
will be updated with any modifications made. */
|
||||
static void UpdateRootFrame(nsIDOMWindowUtils* aUtils,
|
||||
const FrameMetrics& aMetrics);
|
||||
FrameMetrics& aMetrics);
|
||||
|
||||
/* Applies the scroll parameters from the given FrameMetrics object to the subframe
|
||||
corresponding to the given content object. */
|
||||
|
Loading…
Reference in New Issue
Block a user