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 * These APIs are designed to be used with nsIDOMWindowUtils
* setDisplayPort() and setResolution(). * setDisplayPort() and setResolution().
*/ */
[scriptable, uuid(fbd25468-d2cf-487b-bc58-a0e105398b47)] [scriptable, uuid(c04c5c40-fa2a-4e9c-94f5-b362a10a86cb)]
interface nsIContentView : nsISupports interface nsIContentView : nsISupports
{ {
/** /**
@ -265,6 +265,13 @@ interface nsIFrameLoader : nsISupports
* Defaults to true. * Defaults to true.
*/ */
attribute boolean clipSubdocument; 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>); native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);

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

@ -76,6 +76,7 @@
#include "nsFrameLoader.h" #include "nsFrameLoader.h"
#include "nsIDOMEventTarget.h" #include "nsIDOMEventTarget.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsIScrollableFrame.h"
#include "nsSubDocumentFrame.h" #include "nsSubDocumentFrame.h"
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsGUIEvent.h" #include "nsGUIEvent.h"
@ -330,6 +331,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
, mRemoteBrowserShown(false) , mRemoteBrowserShown(false)
, mRemoteFrame(false) , mRemoteFrame(false)
, mClipSubdocument(true) , mClipSubdocument(true)
, mClampScrollPosition(true)
, mCurrentRemoteFrame(nsnull) , mCurrentRemoteFrame(nsnull)
, mRemoteBrowser(nsnull) , mRemoteBrowser(nsnull)
, mRenderMode(RENDER_MODE_DEFAULT) , mRenderMode(RENDER_MODE_DEFAULT)
@ -1755,6 +1757,38 @@ nsFrameLoader::SetClipSubdocument(bool aClip)
return NS_OK; 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 nsIntSize
nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame) nsFrameLoader::GetSubDocumentSize(const nsIFrame *aIFrame)
{ {

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

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

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

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

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

@ -177,7 +177,7 @@ public:
} }
nsRect GetScrollRange() const; 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; nsPoint ClampScrollPosition(const nsPoint& aPt) const;
static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance); static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);
void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode); void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode);
@ -261,6 +261,8 @@ public:
bool IsIgnoringViewportClipping() const; bool IsIgnoringViewportClipping() const;
bool ShouldClampScrollPosition() const;
bool IsAlwaysActive() const; bool IsAlwaysActive() const;
void MarkActive(); void MarkActive();
void MarkInactive(); void MarkInactive();

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

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