Bug 726817 - Add nsIFrameLoaderOwner.clampScrollPosition. r=roc

Add an attribute to nsIFrameLoaderOwner that allows the clamping of set scroll
positions to be toggled.
This commit is contained in:
Chris Lord 2012-02-17 23:41:13 +00:00
Родитель 6765c25533
Коммит 468bb3d933
6 изменённых файлов: 81 добавлений и 9 удалений

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

@ -67,7 +67,7 @@ typedef unsigned long long nsContentViewId;
* These APIs are designed to be used with nsIDOMWindowUtils
* setDisplayPort() and setResolution().
*/
[scriptable, uuid(fbd25468-d2cf-487b-bc58-a0e105398b47)]
[scriptable, uuid(c04c5c40-fa2a-4e9c-94f5-b362a10a86cb)]
interface nsIContentView : nsISupports
{
/**
@ -265,6 +265,13 @@ interface nsIFrameLoader : nsISupports
* Defaults to true.
*/
attribute boolean clipSubdocument;
/**
* If false, then the subdocument's scroll coordinates will not be clamped
* to their scroll boundaries.
* Defaults to true.
*/
attribute boolean clampScrollPosition;
};
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);

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

@ -76,6 +76,7 @@
#include "nsFrameLoader.h"
#include "nsIDOMEventTarget.h"
#include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h"
#include "nsDOMError.h"
#include "nsGUIEvent.h"
@ -330,6 +331,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
, mRemoteBrowserShown(false)
, mRemoteFrame(false)
, mClipSubdocument(true)
, mClampScrollPosition(true)
, mCurrentRemoteFrame(nsnull)
, mRemoteBrowser(nsnull)
, mRenderMode(RENDER_MODE_DEFAULT)
@ -1755,6 +1757,38 @@ nsFrameLoader::SetClipSubdocument(bool aClip)
return NS_OK;
}
NS_IMETHODIMP
nsFrameLoader::GetClampScrollPosition(bool* aResult)
{
*aResult = mClampScrollPosition;
return NS_OK;
}
NS_IMETHODIMP
nsFrameLoader::SetClampScrollPosition(bool aClamp)
{
mClampScrollPosition = aClamp;
// When turning clamping on, make sure the current position is clamped.
if (aClamp) {
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
if (frame) {
nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
if (subdocFrame) {
nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
if (subdocRootFrame) {
nsIScrollableFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
GetRootScrollFrameAsScrollable();
if (subdocRootScrollFrame) {
subdocRootScrollFrame->ScrollTo(subdocRootScrollFrame->GetScrollPosition(), nsIScrollableFrame::INSTANT);
}
}
}
}
}
return NS_OK;
}
nsIntSize
nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame)
{

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

@ -289,6 +289,8 @@ public:
bool ShouldClipSubdocument() { return mClipSubdocument; }
bool ShouldClampScrollPosition() { return mClampScrollPosition; }
private:
bool ShouldUseRemoteProcess();
@ -342,6 +344,7 @@ private:
bool mRemoteBrowserShown : 1;
bool mRemoteFrame : 1;
bool mClipSubdocument : 1;
bool mClampScrollPosition : 1;
// XXX leaking
nsCOMPtr<nsIObserver> mChildHost;

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

@ -1550,7 +1550,11 @@ void
nsGfxScrollFrameInner::ScrollTo(nsPoint aScrollPosition,
nsIScrollableFrame::ScrollMode aMode)
{
mDestination = ClampScrollPosition(aScrollPosition);
if (ShouldClampScrollPosition()) {
mDestination = ClampScrollPosition(aScrollPosition);
} else {
mDestination = aScrollPosition;
}
if (aMode == nsIScrollableFrame::INSTANT) {
// Asynchronous scrolling is not allowed, so we'll kill any existing
@ -1713,6 +1717,15 @@ bool nsGfxScrollFrameInner::IsIgnoringViewportClipping() const
return subdocFrame && !subdocFrame->ShouldClipSubdocument();
}
bool nsGfxScrollFrameInner::ShouldClampScrollPosition() const
{
if (!mIsRoot)
return true;
nsSubDocumentFrame* subdocFrame = static_cast<nsSubDocumentFrame*>
(nsLayoutUtils::GetCrossDocParentFrame(mOuter->PresContext()->PresShell()->GetRootFrame()));
return !subdocFrame || subdocFrame->ShouldClampScrollPosition();
}
bool nsGfxScrollFrameInner::IsAlwaysActive() const
{
// The root scrollframe for a non-chrome document which is the direct
@ -1812,17 +1825,23 @@ ClampInt(nscoord aLower, nscoord aVal, nscoord aUpper, nscoord aAppUnitsPerPixel
}
nsPoint
nsGfxScrollFrameInner::ClampAndRestrictToDevPixels(const nsPoint& aPt,
nsIntPoint* aPtDevPx) const
nsGfxScrollFrameInner::RestrictToDevPixels(const nsPoint& aPt,
nsIntPoint* aPtDevPx,
bool aShouldClamp) const
{
nsPresContext* presContext = mOuter->PresContext();
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
// Convert to device pixels so we scroll to an integer offset of device
// pixels. But we also need to make sure that our position remains
// inside the allowed region.
nsRect scrollRange = GetScrollRange();
*aPtDevPx = nsIntPoint(ClampInt(scrollRange.x, aPt.x, scrollRange.XMost(), appUnitsPerDevPixel),
ClampInt(scrollRange.y, aPt.y, scrollRange.YMost(), appUnitsPerDevPixel));
if (aShouldClamp) {
nsRect scrollRange = GetScrollRange();
*aPtDevPx = nsIntPoint(ClampInt(scrollRange.x, aPt.x, scrollRange.XMost(), appUnitsPerDevPixel),
ClampInt(scrollRange.y, aPt.y, scrollRange.YMost(), appUnitsPerDevPixel));
} else {
*aPtDevPx = nsIntPoint(NSAppUnitsToIntPixels(aPt.x, appUnitsPerDevPixel),
NSAppUnitsToIntPixels(aPt.y, appUnitsPerDevPixel));
}
return nsPoint(NSIntPixelsToAppUnits(aPtDevPx->x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(aPtDevPx->y, appUnitsPerDevPixel));
}
@ -1858,7 +1877,8 @@ nsGfxScrollFrameInner::ScrollToImpl(nsPoint aPt)
nsPresContext* presContext = mOuter->PresContext();
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsIntPoint ptDevPx;
nsPoint pt = ClampAndRestrictToDevPixels(aPt, &ptDevPx);
nsPoint pt = RestrictToDevPixels(aPt, &ptDevPx, ShouldClampScrollPosition());
nsPoint curPos = GetScrollPosition();
if (pt == curPos) {

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

@ -177,7 +177,7 @@ public:
}
nsRect GetScrollRange() const;
nsPoint ClampAndRestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx) const;
nsPoint RestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx, bool aShouldClamp) const;
nsPoint ClampScrollPosition(const nsPoint& aPt) const;
static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);
void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode);
@ -261,6 +261,8 @@ public:
bool IsIgnoringViewportClipping() const;
bool ShouldClampScrollPosition() const;
bool IsAlwaysActive() const;
void MarkActive();
void MarkInactive();

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

@ -130,6 +130,12 @@ public:
return !frameLoader || frameLoader->ShouldClipSubdocument();
}
bool ShouldClampScrollPosition()
{
nsFrameLoader* frameLoader = FrameLoader();
return !frameLoader || frameLoader->ShouldClampScrollPosition();
}
protected:
friend class AsyncFrameInit;