зеркало из https://github.com/mozilla/gecko-dev.git
Bug 618975 Pan overflow elements in parent process r=cjones r=tn sr=roc a=blocking-fennec
This commit is contained in:
Родитель
77297fa5c2
Коммит
975ed8713b
|
@ -1749,6 +1749,7 @@ GK_ATOM(DeleteTxnName, "Deleting")
|
|||
// IPC stuff
|
||||
GK_ATOM(Remote, "remote")
|
||||
GK_ATOM(RemoteId, "_remote_id")
|
||||
GK_ATOM(DisplayPort, "_displayport")
|
||||
|
||||
// Names for system metrics
|
||||
GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "nsFocusManager.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
#include "nsIScrollableFrame.h"
|
||||
|
||||
|
@ -258,9 +259,25 @@ nsDOMWindowUtils::SetCSSViewport(float aWidthPx, float aHeightPx)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void DestroyNsRect(void* aObject, nsIAtom* aPropertyName,
|
||||
void* aPropertyValue, void* aData)
|
||||
{
|
||||
nsRect* rect = static_cast<nsRect*>(aPropertyValue);
|
||||
delete rect;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetDisplayPort(float aXPx, float aYPx,
|
||||
float aWidthPx, float aHeightPx)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(false, "This interface is deprecated.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
|
||||
float aWidthPx, float aHeightPx,
|
||||
nsIDOMElement* aElement)
|
||||
{
|
||||
if (!IsUniversalXPConnectCapable()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -275,9 +292,58 @@ nsDOMWindowUtils::SetDisplayPort(float aXPx, float aYPx,
|
|||
nsPresContext::CSSPixelsToAppUnits(aYPx),
|
||||
nsPresContext::CSSPixelsToAppUnits(aWidthPx),
|
||||
nsPresContext::CSSPixelsToAppUnits(aHeightPx));
|
||||
presShell->SetDisplayPort(displayport);
|
||||
|
||||
presShell->SetIgnoreViewportScrolling(PR_TRUE);
|
||||
if (!aElement) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
|
||||
if (!content) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsRect lastDisplayPort;
|
||||
if (nsLayoutUtils::GetDisplayPort(content, &lastDisplayPort) &&
|
||||
displayport == lastDisplayPort) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
content->SetProperty(nsGkAtoms::DisplayPort, new nsRect(displayport),
|
||||
DestroyNsRect);
|
||||
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
if (rootScrollFrame) {
|
||||
if (content == rootScrollFrame->GetContent()) {
|
||||
// We are setting the root displayport. The pres context needs a special
|
||||
// flag to be set.
|
||||
presShell->SetIgnoreViewportScrolling(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (Bug 593243 should fix this.)
|
||||
//
|
||||
// Invalidated content does not pay any attention to the displayport, so
|
||||
// invalidating the subdocument's root frame could end up not repainting
|
||||
// visible content.
|
||||
//
|
||||
// For instance, imagine the iframe is located at y=1000. Even though the
|
||||
// displayport may intersect the iframe's viewport, the visual overflow
|
||||
// rect of the root content could be (0, 0, 800, 500). Since the dirty region
|
||||
// does not intersect the visible overflow rect, the display list for the
|
||||
// iframe will not even be generated.
|
||||
//
|
||||
// Here, we find the very top presShell and use its root frame for
|
||||
// invalidation instead.
|
||||
//
|
||||
nsPresContext* rootPresContext = GetPresContext()->GetRootPresContext();
|
||||
if (rootPresContext) {
|
||||
nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
|
||||
nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
rootFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -129,30 +129,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
void setCSSViewport(in float aWidthPx, in float aHeightPx);
|
||||
|
||||
/**
|
||||
* Set the "displayport" to be <xPx, yPx, widthPx, heightPx> in
|
||||
* units of CSS pixels, regardless of the size of the enclosing
|
||||
* widget/view. This will *not* trigger reflow.
|
||||
*
|
||||
* <x, y> is relative to the top-left of the CSS viewport. This
|
||||
* means that the pixels rendered to the displayport take scrolling
|
||||
* into account, for example.
|
||||
*
|
||||
* The displayport will be used as the window's visible region for
|
||||
* the purposes of invalidation and painting. The displayport can
|
||||
* approximately be thought of as a "persistent" drawWindow()
|
||||
* (albeit with coordinates relative to the CSS viewport): the
|
||||
* bounds are remembered by the platform, and layer pixels are
|
||||
* retained and updated inside the viewport bounds.
|
||||
*
|
||||
* It's legal to set a displayport that extends beyond the CSS
|
||||
* viewport in any direction (left/right/top/bottom).
|
||||
*
|
||||
* It's also legal to set a displayport that extends beyond the
|
||||
* document's bounds. The value of the pixels rendered outside the
|
||||
* document bounds is not yet defined.
|
||||
*
|
||||
* The caller of this method must have UniversalXPConnect
|
||||
* privileges.
|
||||
* @DEPRECATED See nsIDOMWindowUtils_MOZILLA_2_0_BRANCH.
|
||||
*/
|
||||
void setDisplayPort(in float aXPx, in float aYPx,
|
||||
in float aWidthPx, in float aHeightPx);
|
||||
|
@ -824,7 +801,7 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
|
||||
typedef unsigned long long nsViewID;
|
||||
|
||||
[scriptable, uuid(be2e28c8-64f8-4100-906d-8a451ddd6835)]
|
||||
[scriptable, uuid(7ad49829-e631-4cdd-a237-95847d9bcbe6)]
|
||||
interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
|
||||
/**
|
||||
* Get the type of the currently focused html input, if any.
|
||||
|
@ -838,6 +815,36 @@ interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports {
|
|||
*/
|
||||
nsIDOMElement findElementWithViewId(in nsViewID aId);
|
||||
|
||||
/**
|
||||
* For any scrollable element, this allows you to override the
|
||||
* visible region and draw more than what is visible, which is
|
||||
* useful for asynchronous drawing. The "displayport" will be
|
||||
* <xPx, yPx, widthPx, heightPx> in units of CSS pixels,
|
||||
* regardless of the size of the enclosing container. This
|
||||
* will *not* trigger reflow.
|
||||
*
|
||||
* For the root scroll area, pass in the root document element.
|
||||
* For scrollable elements, pass in the container element (for
|
||||
* instance, the element with overflow: scroll).
|
||||
*
|
||||
* <x, y> is relative to the top-left of what would normally be
|
||||
* the visible area of the element. This means that the pixels
|
||||
* rendered to the displayport take scrolling into account,
|
||||
* for example.
|
||||
*
|
||||
* It's legal to set a displayport that extends beyond the overflow
|
||||
* area in any direction (left/right/top/bottom).
|
||||
*
|
||||
* It's also legal to set a displayport that extends beyond the
|
||||
* area's bounds. No pixels are rendered outside the area bounds.
|
||||
*
|
||||
* The caller of this method must have UniversalXPConnect
|
||||
* privileges.
|
||||
*/
|
||||
void setDisplayPortForElement(in float aXPx, in float aYPx,
|
||||
in float aWidthPx, in float aHeightPx,
|
||||
in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* Same as enterModalState, but returns the window associated with the
|
||||
* current JS context.
|
||||
|
|
|
@ -1252,7 +1252,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
|||
item->GetLayerState(mBuilder, mManager);
|
||||
|
||||
// Assign the item to a layer
|
||||
if (layerState == LAYER_ACTIVE && (aClip.mRoundedClipRects.IsEmpty() ||
|
||||
if (layerState == LAYER_ACTIVE_FORCE ||
|
||||
layerState == LAYER_ACTIVE && (aClip.mRoundedClipRects.IsEmpty() ||
|
||||
// We can use the visible rect here only because the item has its own
|
||||
// layer, like the comment below.
|
||||
!aClip.IsRectClippedByRoundedCorner(item->GetVisibleRect()))) {
|
||||
|
|
|
@ -56,7 +56,10 @@ namespace mozilla {
|
|||
enum LayerState {
|
||||
LAYER_NONE,
|
||||
LAYER_INACTIVE,
|
||||
LAYER_ACTIVE
|
||||
LAYER_ACTIVE,
|
||||
// Force an active layer even if it causes incorrect rendering, e.g.
|
||||
// when the layer has rounded rect clips.
|
||||
LAYER_ACTIVE_FORCE
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -149,12 +149,13 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
|||
}
|
||||
|
||||
static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
nsIFrame* aViewportFrame,
|
||||
ContainerLayer* aRoot,
|
||||
nsRect aVisibleRect,
|
||||
nsRect aViewport,
|
||||
nsRect aDisplayPort,
|
||||
ViewID aScrollId) {
|
||||
nsPresContext* presContext = aForFrame->PresContext();
|
||||
nsIPresShell* presShell = presContext->GetPresShell();
|
||||
|
||||
nsIntRect visible = aVisibleRect.ToNearestPixels(presContext->AppUnitsPerDevPixel());
|
||||
aRoot->SetVisibleRegion(nsIntRegion(visible));
|
||||
|
@ -163,23 +164,23 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
|||
|
||||
PRInt32 auPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
metrics.mViewport = aViewport.ToNearestPixels(auPerDevPixel);
|
||||
if (presShell->UsingDisplayPort()) {
|
||||
metrics.mDisplayPort =
|
||||
presShell->GetDisplayPort().ToNearestPixels(auPerDevPixel);
|
||||
if (aViewport != aDisplayPort) {
|
||||
metrics.mDisplayPort = aDisplayPort.ToNearestPixels(auPerDevPixel);
|
||||
}
|
||||
|
||||
nsIScrollableFrame* rootScrollableFrame =
|
||||
presShell->GetRootScrollFrameAsScrollable();
|
||||
if (rootScrollableFrame) {
|
||||
nsSize contentSize =
|
||||
rootScrollableFrame->GetScrollRange().Size() +
|
||||
rootScrollableFrame->GetScrollPortRect().Size();
|
||||
nsIScrollableFrame* scrollableFrame = NULL;
|
||||
if (aViewportFrame)
|
||||
scrollableFrame = aViewportFrame->GetScrollTargetFrame();
|
||||
|
||||
if (scrollableFrame) {
|
||||
nsSize contentSize =
|
||||
scrollableFrame->GetScrollRange().Size() +
|
||||
scrollableFrame->GetScrollPortRect().Size();
|
||||
metrics.mContentSize = nsIntSize(NSAppUnitsToIntPixels(contentSize.width, auPerDevPixel),
|
||||
NSAppUnitsToIntPixels(contentSize.height, auPerDevPixel));
|
||||
|
||||
metrics.mViewportScrollOffset =
|
||||
rootScrollableFrame->GetScrollPosition().ToNearestPixels(auPerDevPixel);
|
||||
|
||||
scrollableFrame->GetScrollPosition().ToNearestPixels(auPerDevPixel);
|
||||
}
|
||||
else {
|
||||
nsSize contentSize = aForFrame->GetSize();
|
||||
|
@ -523,7 +524,18 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
|||
ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
|
||||
: FrameMetrics::NULL_SCROLL_ID;
|
||||
|
||||
RecordFrameMetrics(aForFrame, root, mVisibleRect, mVisibleRect, id);
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
nsRect visibleRect = mVisibleRect;
|
||||
if (rootScrollFrame) {
|
||||
nsIContent* content = rootScrollFrame->GetContent();
|
||||
if (content) {
|
||||
// If there is a displayport defined for the root content element,
|
||||
// it will be stored in visibleRect.
|
||||
nsLayoutUtils::GetDisplayPort(content, &visibleRect);
|
||||
}
|
||||
}
|
||||
RecordFrameMetrics(aForFrame, presShell->GetRootScrollFrame(),
|
||||
root, mVisibleRect, mVisibleRect, visibleRect, id);
|
||||
|
||||
// If the layer manager supports resolution scaling, set that up
|
||||
if (LayerManager::LAYERS_BASIC == layerManager->GetBackendType()) {
|
||||
|
@ -1694,9 +1706,11 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
nsIFrame* aForFrame,
|
||||
nsIFrame* aViewportFrame)
|
||||
nsIFrame* aViewportFrame,
|
||||
const nsRect& aDisplayPort)
|
||||
: nsDisplayOwnLayer(aBuilder, aForFrame, aList)
|
||||
, mViewportFrame(aViewportFrame)
|
||||
, mDisplayPort(aDisplayPort)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
|
||||
|
@ -1721,7 +1735,8 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
mViewportFrame->GetPosition() +
|
||||
aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
|
||||
RecordFrameMetrics(mFrame, layer, mVisibleRect, viewport, scrollId);
|
||||
RecordFrameMetrics(mFrame, mViewportFrame, layer, mVisibleRect, viewport,
|
||||
mDisplayPort, scrollId);
|
||||
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -1733,14 +1748,17 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsIPresShell* presShell = presContext->GetPresShell();
|
||||
|
||||
if (presShell->UsingDisplayPort()) {
|
||||
nsRect viewport = mViewportFrame->GetRect() -
|
||||
mViewportFrame->GetPosition() +
|
||||
aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
|
||||
if (mDisplayPort != viewport) {
|
||||
// The visible region for the children may be much bigger than the hole we
|
||||
// are viewing the children from, so that the compositor process has enough
|
||||
// content to asynchronously pan while content is being refreshed.
|
||||
|
||||
nsRegion childVisibleRegion = presShell->GetDisplayPort() + aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
nsRegion childVisibleRegion = mDisplayPort + aBuilder->ToReferenceFrame(mViewportFrame);
|
||||
|
||||
nsRect boundedRect;
|
||||
boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));
|
||||
|
|
|
@ -1790,9 +1790,12 @@ public:
|
|||
* @param aForFrame This will determine what the displayport is. It should be
|
||||
* the root content frame of the scrolled area.
|
||||
* @param aViewportFrame The viewport frame you see this content through.
|
||||
* @param aDisplayPort Overrides the visibility of the child items if it
|
||||
* is not equal to the visible area.
|
||||
*/
|
||||
nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
|
||||
nsIFrame* aForFrame, nsIFrame* aViewportFrame);
|
||||
nsIFrame* aForFrame, nsIFrame* aViewportFrame,
|
||||
const nsRect& aDisplayPort);
|
||||
NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
@ -1807,8 +1810,16 @@ public:
|
|||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
// Force this as a layer so we can scroll asynchronously.
|
||||
// This causes incorrect rendering for rounded clips!
|
||||
return mozilla::LAYER_ACTIVE_FORCE;
|
||||
}
|
||||
private:
|
||||
nsIFrame* mViewportFrame;
|
||||
nsRect mDisplayPort;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1154,19 +1154,21 @@ public:
|
|||
* Set up a "displayport", which overrides what everything else thinks
|
||||
* is the visible region of this document with the specified
|
||||
* displayport rect.
|
||||
* @DEPRECATED Use nsLayoutUtils displayport methods
|
||||
*/
|
||||
virtual void SetDisplayPort(const nsRect& aDisplayPort) = 0;
|
||||
PRBool UsingDisplayPort() const
|
||||
{ return mRenderFlags & STATE_USING_DISPLAYPORT; }
|
||||
{ NS_ABORT_IF_FALSE(false, "UsingDisplayPort is deprecated"); return false; }
|
||||
|
||||
/**
|
||||
* Return the displayport being used. |UsingDisplayPort()| must be
|
||||
* true.
|
||||
* @DEPRECATED Use nsLayoutUtils displayport methods
|
||||
*/
|
||||
nsRect GetDisplayPort()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(UsingDisplayPort(), "no displayport defined!");
|
||||
return mDisplayPort;
|
||||
NS_ABORT_IF_FALSE(false, "GetDisplayPort is deprecated");
|
||||
return nsRect();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -143,6 +143,10 @@ static void DestroyViewID(void* aObject, nsIAtom* aPropertyName,
|
|||
delete id;
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace class for static layout utilities.
|
||||
*/
|
||||
|
||||
ViewID
|
||||
nsLayoutUtils::FindIDFor(nsIContent* aContent)
|
||||
{
|
||||
|
@ -177,9 +181,19 @@ nsLayoutUtils::FindContentFor(ViewID aId)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace class for static layout utilities.
|
||||
*/
|
||||
bool
|
||||
nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult)
|
||||
{
|
||||
void* property = aContent->GetProperty(nsGkAtoms::DisplayPort);
|
||||
if (!property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aResult) {
|
||||
*aResult = *static_cast<nsRect*>(property);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
|
||||
|
@ -1368,6 +1382,16 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
|||
nsPresContext* presContext = aFrame->PresContext();
|
||||
nsIPresShell* presShell = presContext->PresShell();
|
||||
|
||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
||||
bool usingDisplayPort = false;
|
||||
nsRect displayport;
|
||||
if (rootScrollFrame) {
|
||||
nsIContent* content = rootScrollFrame->GetContent();
|
||||
if (content) {
|
||||
usingDisplayPort = nsLayoutUtils::GetDisplayPort(content, &displayport);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
|
||||
nsRegion visibleRegion;
|
||||
if (aFlags & PAINT_WIDGET_LAYERS) {
|
||||
|
@ -1377,10 +1401,10 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra
|
|||
// |ignoreViewportScrolling| and |usingDisplayPort| are persistent
|
||||
// document-rendering state. We rely on PresShell to flush
|
||||
// retained layers as needed when that persistent state changes.
|
||||
if (!presShell->UsingDisplayPort()) {
|
||||
if (!usingDisplayPort) {
|
||||
visibleRegion = aFrame->GetVisualOverflowRectRelativeToSelf();
|
||||
} else {
|
||||
visibleRegion = presShell->GetDisplayPort();
|
||||
visibleRegion = displayport;
|
||||
}
|
||||
} else {
|
||||
visibleRegion = aDirtyRegion;
|
||||
|
|
|
@ -94,6 +94,11 @@ public:
|
|||
*/
|
||||
static nsIContent* FindContentFor(ViewID aId);
|
||||
|
||||
/**
|
||||
* Get display port for the given element.
|
||||
*/
|
||||
static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult);
|
||||
|
||||
/**
|
||||
* Use heuristics to figure out the name of the child list that
|
||||
* aChildFrame is currently in.
|
||||
|
|
|
@ -1037,12 +1037,10 @@ protected:
|
|||
struct RenderingState {
|
||||
RenderingState(PresShell* aPresShell)
|
||||
: mRenderFlags(aPresShell->mRenderFlags)
|
||||
, mDisplayPort(aPresShell->mDisplayPort)
|
||||
, mXResolution(aPresShell->mXResolution)
|
||||
, mYResolution(aPresShell->mYResolution)
|
||||
{ }
|
||||
PRUint32 mRenderFlags;
|
||||
nsRect mDisplayPort;
|
||||
float mXResolution;
|
||||
float mYResolution;
|
||||
};
|
||||
|
@ -1056,7 +1054,6 @@ protected:
|
|||
~AutoSaveRestoreRenderingState()
|
||||
{
|
||||
mPresShell->mRenderFlags = mOldState.mRenderFlags;
|
||||
mPresShell->mDisplayPort = mOldState.mDisplayPort;
|
||||
mPresShell->mXResolution = mOldState.mXResolution;
|
||||
mPresShell->mYResolution = mOldState.mYResolution;
|
||||
}
|
||||
|
@ -6017,14 +6014,7 @@ void PresShell::SetIgnoreViewportScrolling(PRBool aIgnore)
|
|||
|
||||
void PresShell::SetDisplayPort(const nsRect& aDisplayPort)
|
||||
{
|
||||
if (UsingDisplayPort() && mDisplayPort == aDisplayPort) {
|
||||
return;
|
||||
}
|
||||
RenderingState state(this);
|
||||
state.mRenderFlags = ChangeFlag(mRenderFlags, PR_TRUE,
|
||||
STATE_USING_DISPLAYPORT);
|
||||
state.mDisplayPort = aDisplayPort;
|
||||
SetRenderingState(state);
|
||||
NS_ABORT_IF_FALSE(false, "SetDisplayPort is deprecated");
|
||||
}
|
||||
|
||||
nsresult PresShell::SetResolution(float aXResolution, float aYResolution)
|
||||
|
@ -6054,37 +6044,8 @@ void PresShell::SetRenderingState(const RenderingState& aState)
|
|||
}
|
||||
|
||||
mRenderFlags = aState.mRenderFlags;
|
||||
if (UsingDisplayPort()) {
|
||||
mDisplayPort = aState.mDisplayPort;
|
||||
} else {
|
||||
mDisplayPort = nsRect();
|
||||
}
|
||||
mXResolution = aState.mXResolution;
|
||||
mYResolution = aState.mYResolution;
|
||||
|
||||
// FIXME (Bug 593243 should fix this.)
|
||||
//
|
||||
// Invalidated content does not pay any attention to the displayport, so
|
||||
// invalidating the subdocument's root frame could end up not repainting
|
||||
// visible content.
|
||||
//
|
||||
// For instance, imagine the iframe is located at y=1000. Even though the
|
||||
// displayport may intersect the iframe's viewport, the visual overflow
|
||||
// rect of the root content could be (0, 0, 800, 500). Since the dirty region
|
||||
// does not intersect the visible overflow rect, the display list for the
|
||||
// iframe will not even be generated.
|
||||
//
|
||||
// Here, we find the very top presShell and use its root frame for
|
||||
// invalidation instead.
|
||||
//
|
||||
nsPresContext* rootPresContext = mPresContext->GetRootPresContext();
|
||||
if (rootPresContext) {
|
||||
nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
|
||||
nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
|
||||
if (rootFrame) {
|
||||
rootFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PresShell::SynthesizeMouseMove(PRBool aFromScroll)
|
||||
|
|
|
@ -1863,9 +1863,12 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
scrollParts, createLayersForScrollbars);
|
||||
}
|
||||
|
||||
nsIPresShell* presShell = mOuter->PresContext()->GetPresShell();
|
||||
nsRect scrollPort = (mIsRoot && presShell->UsingDisplayPort()) ?
|
||||
(presShell->GetDisplayPort()) : mScrollPort;
|
||||
nsRect displayport;
|
||||
PRBool usingDisplayPort = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(),
|
||||
&displayport);
|
||||
if (!usingDisplayPort) {
|
||||
displayport = mScrollPort;
|
||||
}
|
||||
|
||||
// Overflow clipping can never clip frames outside our subtree, so there
|
||||
// is no need to worry about whether we are a moving frame that might clip
|
||||
|
@ -1876,18 +1879,69 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
// had dirty rects saved for them by their parent frames calling
|
||||
// MarkOutOfFlowChildrenForDisplayList, so it's safe to restrict our
|
||||
// dirty rect here.
|
||||
dirtyRect.IntersectRect(aDirtyRect, scrollPort);
|
||||
dirtyRect.IntersectRect(aDirtyRect, mScrollPort);
|
||||
|
||||
if (usingDisplayPort) {
|
||||
dirtyRect = displayport;
|
||||
}
|
||||
|
||||
nsDisplayListCollection set;
|
||||
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
|
||||
|
||||
nsPresContext* presContext = mOuter->PresContext();
|
||||
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
// Since making new layers is expensive, only use nsDisplayScrollLayer
|
||||
// if the area is scrollable.
|
||||
//
|
||||
// Scroll frames can be generated with a scroll range that is 0, 0.
|
||||
// Furthermore, it is not worth the memory tradeoff to allow asynchronous
|
||||
// scrolling of small scroll frames. We use an arbitrary minimum scroll
|
||||
// range of 20 pixels to eliminate many gfx scroll frames from becoming a
|
||||
// layer.
|
||||
//
|
||||
nsRect scrollRange = GetScrollRange();
|
||||
PRBool buildingLayer =
|
||||
(XRE_GetProcessType() == GeckoProcessType_Content &&
|
||||
(scrollRange.width >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel) ||
|
||||
scrollRange.height >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel))) &&
|
||||
(!mIsRoot || !mOuter->PresContext()->IsRootContentDocument());
|
||||
|
||||
#else
|
||||
PRBool buildingLayer = false;
|
||||
#endif
|
||||
|
||||
if (buildingLayer) {
|
||||
// Note that using StackingContext breaks z order, so the resulting
|
||||
// rendering can be incorrect for weird edge cases!
|
||||
|
||||
rv = mScrolledFrame->BuildDisplayListForStackingContext(
|
||||
aBuilder,
|
||||
dirtyRect + mOuter->GetOffsetTo(mScrolledFrame),
|
||||
set.Content()
|
||||
);
|
||||
|
||||
nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
|
||||
aBuilder,
|
||||
set.Content(),
|
||||
mScrolledFrame,
|
||||
mOuter,
|
||||
displayport
|
||||
);
|
||||
set.Content()->AppendNewToTop(layerItem);
|
||||
} else {
|
||||
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsRect clip;
|
||||
clip = scrollPort + aBuilder->ToReferenceFrame(mOuter);
|
||||
clip = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
|
||||
|
||||
nscoord radii[8];
|
||||
// Our override of GetBorderRadii ensures we never have a radius at
|
||||
// the corners where we have a scrollbar.
|
||||
mOuter->GetPaddingBoxBorderRadii(radii);
|
||||
|
||||
// mScrolledFrame may have given us a background, e.g., the scrolled canvas
|
||||
// frame below the viewport. If so, we want it to be clipped. We also want
|
||||
// to end up on our BorderBackground list.
|
||||
|
|
|
@ -340,32 +340,12 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
PRInt32 parentAPD = PresContext()->AppUnitsPerDevPixel();
|
||||
PRInt32 subdocAPD = presContext->AppUnitsPerDevPixel();
|
||||
|
||||
nsIFrame* subdocRootScrollFrame = presShell->GetRootScrollFrame();
|
||||
|
||||
nsRect dirty;
|
||||
if (subdocRootFrame) {
|
||||
if (presShell->UsingDisplayPort() && subdocRootScrollFrame) {
|
||||
dirty = presShell->GetDisplayPort();
|
||||
|
||||
// The visual overflow rect of our viewport frame unfortunately may not
|
||||
// intersect with the displayport of that frame. For example, the scroll
|
||||
// offset of the frame may be (0, 0) so that the visual overflow rect
|
||||
// is (0, 0, 800px, 500px) while the display port may have its top-left
|
||||
// corner below y=500px.
|
||||
//
|
||||
// We have to force the frame to have a little faith and build a display
|
||||
// list anyway. (see nsIFrame::BuildDisplayListForChild for the short-
|
||||
// circuit code we are evading here).
|
||||
//
|
||||
subdocRootScrollFrame->AddStateBits(
|
||||
NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
|
||||
|
||||
} else {
|
||||
// get the dirty rect relative to the root frame of the subdoc
|
||||
dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
|
||||
// and convert into the appunits of the subdoc
|
||||
dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
|
||||
}
|
||||
// get the dirty rect relative to the root frame of the subdoc
|
||||
dirty = aDirtyRect + GetOffsetToCrossDoc(subdocRootFrame);
|
||||
// and convert into the appunits of the subdoc
|
||||
dirty = dirty.ConvertAppUnitsRoundOut(parentAPD, subdocAPD);
|
||||
|
||||
aBuilder->EnterPresShell(subdocRootFrame, dirty);
|
||||
}
|
||||
|
@ -425,32 +405,6 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
bool addedLayer = false;
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
// Make a scrollable layer in the child process so it can be manipulated
|
||||
// with transforms in the parent process.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();
|
||||
|
||||
if (scrollFrame) {
|
||||
NS_ASSERTION(subdocRootFrame, "Root scroll frame should be non-null");
|
||||
nsRect scrollRange = scrollFrame->GetScrollRange();
|
||||
|
||||
// Since making new layers is expensive, only use nsDisplayScrollLayer
|
||||
// if the area is scrollable.
|
||||
if (scrollRange.width != 0 || scrollRange.height != 0) {
|
||||
addedLayer = true;
|
||||
nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
|
||||
aBuilder,
|
||||
&childItems,
|
||||
subdocRootScrollFrame,
|
||||
subdocRootFrame
|
||||
);
|
||||
childItems.AppendToTop(layerItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (subdocRootFrame && parentAPD != subdocAPD) {
|
||||
NS_WARN_IF_FALSE(!addedLayer,
|
||||
"Two container layers have been added. "
|
||||
|
|
Загрузка…
Ссылка в новой задаче