Bug 605618 Part 2: Infrastructure for building shadow display list r=tn sr=roc
--- a/layout/base/nsDisplayItemTypes.h
+++ b/layout/base/nsDisplayItemTypes.h
@@ -76,16 +76,17 @@ enum Type {
TYPE_OUTLINE,
TYPE_OWN_LAYER,
TYPE_PAGE_CONTENT,
TYPE_PAGE_SEQUENCE,
TYPE_PLUGIN,
TYPE_PRINT_PREVIEW_BACKGROUND,
TYPE_PRINT_PLUGIN,
TYPE_REMOTE,
+ TYPE_REMOTE_SHADOW,
TYPE_SELECTION_OVERLAY,
TYPE_SOLID_COLOR,
TYPE_TABLE_CELL_BACKGROUND,
TYPE_TABLE_CELL_SELECTION,
TYPE_TABLE_ROW_BACKGROUND,
TYPE_TABLE_ROW_GROUP_BACKGROUND,
TYPE_TABLE_BORDER_BACKGROUND,
TYPE_TEXT,
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -519,16 +519,17 @@ protected:
* subclass would just have a frame pointer, so its object would be just three
* pointers (vtable, next-item, frame).
*
* Display items belong to a list at all times (except temporarily as they
* move from one list to another).
*/
class nsDisplayItem : public nsDisplayItemLink {
public:
+ typedef mozilla::layers::FrameMetrics::ViewID ViewID;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::LayerState LayerState;
// This is never instantiated directly (it has pure virtual methods), so no
// need to count constructors and destructors.
nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
mFrame(aFrame) {
@@ -542,21 +543,33 @@ public:
nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
return aBuilder->Allocate(aSize);
}
// Contains all the type integers for each display list item type
#include "nsDisplayItemTypes.h"
struct HitTestState {
+ typedef nsTArray<ViewID> ShadowArray;
+
+ HitTestState(ShadowArray* aShadows = NULL)
+ : mShadows(aShadows) {
+ }
+
~HitTestState() {
NS_ASSERTION(mItemBuffer.Length() == 0,
"mItemBuffer should have been cleared");
}
+
nsAutoTArray<nsDisplayItem*, 100> mItemBuffer;
+
+ // It is sometimes useful to hit test for frames that are not in this
+ // process. Display items may append IDs into this array if it is
+ // non-null.
+ ShadowArray* mShadows;
};
/**
* Some consecutive items should be rendered together as a unit, e.g.,
* outlines for the same element. For this, we need a way for items to
* identify their type. We use the type for other purposes too.
*/
virtual Type GetType() = 0;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -114,16 +114,17 @@ using namespace mozilla::dom;
namespace css = mozilla::css;
#ifdef DEBUG
// TODO: remove, see bug 598468.
bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false;
#endif // DEBUG
typedef gfxPattern::GraphicsFilter GraphicsFilter;
+typedef FrameMetrics::ViewID ViewID;
/**
* A namespace class for static layout utilities.
*/
nsIFrame*
nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
{
@@ -1089,16 +1090,50 @@ nsLayoutUtils::CombineBreakType(PRUint8
#ifdef DEBUG
#include <stdio.h>
static PRBool gDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
static PRBool gDumpEventList = PR_FALSE;
#endif
+nsresult
+nsLayoutUtils::GetRemoteContentIds(nsIFrame* aFrame,
+ const nsRect& aTarget,
+ nsTArray<ViewID> &aOutIDs,
+ PRBool aIgnoreRootScrollFrame)
+{
+ nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::EVENT_DELIVERY,
+ PR_FALSE);
+ nsDisplayList list;
+
+ if (aIgnoreRootScrollFrame) {
+ nsIFrame* rootScrollFrame =
+ aFrame->PresContext()->PresShell()->GetRootScrollFrame();
+ if (rootScrollFrame) {
+ builder.SetIgnoreScrollFrame(rootScrollFrame);
+ }
+ }
+
+ builder.EnterPresShell(aFrame, aTarget);
+
+ nsresult rv =
+ aFrame->BuildDisplayListForStackingContext(&builder, aTarget, &list);
+
+ builder.LeavePresShell(aFrame, aTarget);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsTArray<nsIFrame*> outFrames;
+ nsDisplayItem::HitTestState hitTestState(&aOutIDs);
+ list.HitTest(&builder, aTarget, &hitTestState, &outFrames);
+ list.DeleteAll();
+
+ return NS_OK;
+}
+
nsIFrame*
nsLayoutUtils::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt,
PRBool aShouldIgnoreSuppression,
PRBool aIgnoreRootScrollFrame)
{
nsresult rv;
nsTArray<nsIFrame*> outFrames;
rv = GetFramesForArea(aFrame, nsRect(aPt, nsSize(1, 1)), outFrames,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -60,30 +60,33 @@ class nsClientRectList;
#include "nsIFrame.h"
#include "nsThreadUtils.h"
#include "nsIPresShell.h"
#include "nsIPrincipal.h"
#include "gfxPattern.h"
#include "imgIContainer.h"
#include "nsCSSPseudoElements.h"
#include "nsHTMLReflowState.h"
+#include "nsIFrameLoader.h"
+#include "Layers.h"
class nsBlockFrame;
class gfxDrawable;
/**
* nsLayoutUtils is a namespace class used for various helper
* functions that are useful in multiple places in layout. The goal
* is not to define multiple copies of the same static helper.
*/
class nsLayoutUtils
{
typedef gfxPattern::GraphicsFilter GraphicsFilter;
public:
+ typedef mozilla::layers::FrameMetrics::ViewID ViewID;
/**
* Use heuristics to figure out the name of the child list that
* aChildFrame is currently in.
*/
static nsIAtom* GetChildListNameFor(nsIFrame* aChildFrame);
/**
@@ -431,16 +434,33 @@ public:
* @param aOrigin The origin to translate to.
* @param aMatrix The matrix to change the basis of.
* @return A matrix equivalent to aMatrix, but operating in the coordinate system with
* origin aOrigin.
*/
static gfxMatrix ChangeMatrixBasis(const gfxPoint &aOrigin, const gfxMatrix &aMatrix);
/**
+ * Find IDs corresponding to a scrollable content element in the child process.
+ * In correspondence with the shadow layer tree, you can use this to perform a
+ * hit test that corresponds to a specific shadow layer that you can then perform
+ * transformations on to do parent-side scrolling.
+ *
+ * @param aFrame The root frame of a stack context
+ * @param aTarget The rect to hit test relative to the frame origin
+ * @param aOutIDs All found IDs are added here
+ * @param aIgnoreRootScrollFrame a boolean to control if the display list
+ * builder should ignore the root scroll frame
+ */
+ static nsresult GetRemoteContentIds(nsIFrame* aFrame,
+ const nsRect& aTarget,
+ nsTArray<ViewID> &aOutIDs,
+ PRBool aIgnoreRootScrollFrame);
+
+ /**
* Given aFrame, the root frame of a stacking context, find its descendant
* frame under the point aPt that receives a mouse event at that location,
* or nsnull if there is no such frame.
* @param aPt the point, relative to the frame origin
* @param aShouldIgnoreSuppression a boolean to control if the display
* list builder should ignore paint suppression or not
* @param aIgnoreRootScrollFrame whether or not the display list builder
* should ignore the root scroll frame.
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -277,29 +277,17 @@ nsSubDocumentFrame::BuildDisplayList(nsD
if (!mInnerView)
return NS_OK;
#ifdef MOZ_IPC
nsFrameLoader* frameLoader = FrameLoader();
if (frameLoader) {
RenderFrameParent* rfp = frameLoader->GetCurrentRemoteFrame();
if (rfp) {
- // We're the subdoc for <browser remote="true"> and it has
- // painted content. Display its shadow layer tree.
- nsDisplayList shadowTree;
- shadowTree.AppendToTop(
- new (aBuilder) nsDisplayRemote(aBuilder, this, rfp));
-
- // Clip the shadow layers to subdoc bounds
- nsPoint offset = GetOffsetToCrossDoc(aBuilder->ReferenceFrame());
- nsRect bounds = mInnerView->GetBounds() + offset;
-
- return aLists.Content()->AppendNewToTop(
- new (aBuilder) nsDisplayClip(aBuilder, this, &shadowTree,
- bounds));
+ return rfp->BuildDisplayList(aBuilder, this, aDirtyRect, aLists);
}
}
#endif
nsIView* subdocView = mInnerView->GetFirstChild();
if (!subdocView)
return NS_OK;
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -42,16 +42,17 @@
#include "BasicLayers.h"
#include "LayerManagerOGL.h"
#include "RenderFrameParent.h"
#include "gfx3DMatrix.h"
#include "nsFrameLoader.h"
#include "nsViewportFrame.h"
+#include "nsSubDocumentFrame.h"
typedef nsFrameLoader::ViewportConfig ViewportConfig;
using namespace mozilla::layers;
namespace mozilla {
namespace layout {
static void
@@ -359,20 +360,56 @@ RenderFrameParent::GetShadowLayers() con
ContainerLayer*
RenderFrameParent::GetRootLayer() const
{
ShadowLayersParent* shadowLayers = GetShadowLayers();
return shadowLayers ? shadowLayers->GetRoot() : nsnull;
}
+NS_IMETHODIMP
+RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ nsSubDocumentFrame* aFrame,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists)
+{
+ // We're the subdoc for <browser remote="true"> and it has
+ // painted content. Display its shadow layer tree.
+ nsDisplayList shadowTree;
+ shadowTree.AppendToTop(
+ new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
+
+ // Clip the shadow layers to subdoc bounds
+ nsPoint offset = aFrame->GetOffsetToCrossDoc(aBuilder->ReferenceFrame());
+ nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset;
+
+ return aLists.Content()->AppendNewToTop(
+ new (aBuilder) nsDisplayClip(aBuilder, aFrame, &shadowTree,
+ bounds));
+}
+
} // namespace layout
} // namespace mozilla
already_AddRefed<Layer>
nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager)
{
PRInt32 appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel);
nsRefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect);
return layer.forget();
}
+
+
+void
+nsDisplayRemoteShadow::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
+ HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
+{
+ // If we are here, then rects have intersected.
+ //
+ // XXX I think iframes and divs can be rounded like anything else but we don't
+ // cover that case here.
+ //
+ if (aState->mShadows) {
+ aState->mShadows->AppendElement(mId);
+ }
+}
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -39,44 +39,50 @@
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_layout_RenderFrameParent_h
#define mozilla_layout_RenderFrameParent_h
#include "mozilla/layout/PRenderFrameParent.h"
#include "nsDisplayList.h"
+#include "Layers.h"
class nsFrameLoader;
+class nsSubDocumentFrame;
namespace mozilla {
+
namespace layers {
-class ContainerLayer;
-class Layer;
-class LayerManager;
class ShadowLayersParent;
}
namespace layout {
class RenderFrameParent : public PRenderFrameParent
{
+ typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ContainerLayer ContainerLayer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
public:
RenderFrameParent(nsFrameLoader* aFrameLoader);
virtual ~RenderFrameParent();
void Destroy();
void ShadowLayersUpdated();
+ NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ nsSubDocumentFrame* aFrame,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists);
+
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame,
LayerManager* aManager,
const nsIntRect& aVisibleRect);
protected:
NS_OVERRIDE void ActorDestroy(ActorDestroyReason why);
@@ -121,9 +127,52 @@ public:
BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager);
NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE)
private:
RenderFrameParent* mRemoteFrame;
};
+/**
+ * nsDisplayRemoteShadow is a way of adding display items for frames in a
+ * separate process, for hit testing only. After being processed, the hit
+ * test state will contain IDs for any remote frames that were hit.
+ *
+ * The frame should be its respective render frame parent.
+ */
+class nsDisplayRemoteShadow : public nsDisplayItem
+{
+ typedef mozilla::layout::RenderFrameParent RenderFrameParent;
+ typedef mozilla::layers::FrameMetrics::ViewID ViewID;
+
+public:
+ nsDisplayRemoteShadow(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ nsRect aRect,
+ ViewID aId)
+ : nsDisplayItem(aBuilder, aFrame)
+ , mRect(aRect)
+ , mId(aId)
+ {}
+
+ NS_OVERRIDE nsRect GetBounds(nsDisplayListBuilder* aBuilder)
+ {
+ return mRect;
+ }
+
+ virtual PRUint32 GetPerFrameKey()
+ {
+ NS_ABORT();
+ return 0;
+ }
+
+ NS_OVERRIDE void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
+ HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
+
+ NS_DISPLAY_DECL_NAME("Remote-Shadow", TYPE_REMOTE_SHADOW)
+
+private:
+ nsRect mRect;
+ ViewID mId;
+};
+
#endif // mozilla_layout_RenderFrameParent_h