diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index b5429c465b1..f0809f8f319 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -580,16 +580,6 @@ public: nsIAtom *aPropertyName, nsresult *aStatus = nsnull) const; - /** - * Useful template for use with SetProperty. - */ - template - static void DestroyProperty(void* aObject, nsIAtom* aPropertyName, - void* aPropertyValue, void* aData) - { - delete static_cast(aPropertyValue); - } - /** * Set a property to be associated with this node. This will overwrite an * existing value if one exists. The existing value is destroyed using the diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index aabc07c4f3e..66e3b4179d5 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -992,6 +992,21 @@ nsDOMWindowUtils::GetFocusedInputType(char** aType) return NS_OK; } +NS_IMETHODIMP +nsDOMWindowUtils::FindElementWithViewId(nsViewID aID, + nsIDOMElement** aResult) +{ + if (aID == FrameMetrics::ROOT_SCROLL_ID) { + nsPresContext* presContext = GetPresContext(); + nsIDocument* document = presContext->Document(); + CallQueryInterface(document->GetRootElement(), aResult); + return NS_OK; + } + + nsRefPtr content = nsLayoutUtils::FindContentFor(aID); + return CallQueryInterface(content, aResult); +} + NS_IMETHODIMP nsDOMWindowUtils::GetScreenPixelsPerCSSPixel(float* aScreenPixels) { diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index a90a857ab29..b55d6322c05 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -822,10 +822,19 @@ interface nsIDOMWindowUtils : nsISupports { in AString value2); }; +typedef unsigned long long nsViewID; + [scriptable, uuid(3a0334aa-b9cc-4b32-9b6c-599cd4e40d5b)] interface nsIDOMWindowUtils_MOZILLA_2_0_BRANCH : nsISupports { /** * Get the type of the currently focused html input, if any. */ readonly attribute string focusedInputType; + + /** + * Given a view ID from the compositor process, retrieve the element + * associated with a view. For scrollpanes for documents, the root + * element of the document is returned. + */ + nsIDOMElement findElementWithViewId(in nsViewID aId); }; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index cfcb3647a20..ab3ae017160 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -69,8 +69,6 @@ using namespace mozilla; using namespace mozilla::layers; typedef FrameMetrics::ViewID ViewID; -static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID; - nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, PRBool aBuildCaret) : mReferenceFrame(aReferenceFrame), @@ -1637,19 +1635,8 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder, // Get the already set unique ID for scrolling this content remotely. // Or, if not set, generate a new ID. - ViewID scrollId; - { - nsIContent* content = mFrame->GetContent(); - void* scrollIdProperty = content->GetProperty(nsGkAtoms::RemoteId); - if (scrollIdProperty) { - scrollId = *static_cast(scrollIdProperty); - } else { - scrollId = sScrollIdCounter++; - content->SetProperty(nsGkAtoms::RemoteId, new ViewID(scrollId), - nsINode::DestroyProperty); - } - } - + nsIContent* content = mFrame->GetContent(); + ViewID scrollId = nsLayoutUtils::FindIDFor(content); nsRect viewport = mViewportFrame->GetRect() - mViewportFrame->GetPosition() + diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index f3bfcf97306..33d644b2ded 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -97,6 +97,7 @@ #include "nsCanvasFrame.h" #include "gfxDrawable.h" #include "gfxUtils.h" +#include "nsDataHashtable.h" #ifdef MOZ_SVG #include "nsSVGUtils.h" @@ -121,6 +122,61 @@ bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false; typedef gfxPattern::GraphicsFilter GraphicsFilter; typedef FrameMetrics::ViewID ViewID; +static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID; + +typedef nsDataHashtable ContentMap; +static ContentMap* sContentMap = NULL; +static ContentMap& GetContentMap() { + if (!sContentMap) { + sContentMap = new ContentMap(); + nsresult rv = sContentMap->Init(); + NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not initialize map."); + } + return *sContentMap; +} + +static void DestroyViewID(void* aObject, nsIAtom* aPropertyName, + void* aPropertyValue, void* aData) +{ + ViewID* id = static_cast(aPropertyValue); + GetContentMap().Remove(*id); + delete id; +} + +ViewID +nsLayoutUtils::FindIDFor(nsIContent* aContent) +{ + ViewID scrollId; + + void* scrollIdProperty = aContent->GetProperty(nsGkAtoms::RemoteId); + if (scrollIdProperty) { + scrollId = *static_cast(scrollIdProperty); + } else { + scrollId = sScrollIdCounter++; + aContent->SetProperty(nsGkAtoms::RemoteId, new ViewID(scrollId), + DestroyViewID); + GetContentMap().Put(scrollId, aContent); + } + + return scrollId; +} + +nsIContent* +nsLayoutUtils::FindContentFor(ViewID aId) +{ + NS_ABORT_IF_FALSE(aId != FrameMetrics::NULL_SCROLL_ID && + aId != FrameMetrics::ROOT_SCROLL_ID, + "Cannot find a content element in map for null or root IDs."); + nsIContent* content; + bool exists = GetContentMap().Get(aId, &content); + + if (exists) { + return content; + } else { + return nsnull; + } +} + /** * A namespace class for static layout utilities. */ @@ -3907,6 +3963,16 @@ nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot) } #endif +/* static */ +void +nsLayoutUtils::Shutdown() +{ + if (sContentMap) { + delete sContentMap; + sContentMap = NULL; + } +} + nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, const nsAString& aValue) : mContent(aContent), diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index a810e22da1a..59ce6b11f7d 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -83,6 +83,17 @@ class nsLayoutUtils public: typedef mozilla::layers::FrameMetrics::ViewID ViewID; + /** + * Finds previously assigned or generates a unique ViewID for the given + * content element. + */ + static ViewID FindIDFor(nsIContent* aContent); + + /** + * Find content for given ID. + */ + static nsIContent* FindContentFor(ViewID aId); + /** * Use heuristics to figure out the name of the child list that * aChildFrame is currently in. @@ -1290,6 +1301,8 @@ public: aPresContext->Type() == nsPresContext::eContext_PageLayout); } + static void Shutdown(); + #ifdef DEBUG /** * Assert that there are no duplicate continuations of the same frame diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 9b1a7767475..11a02866119 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -380,4 +380,6 @@ nsLayoutStatics::Shutdown() nsFrameList::Shutdown(); nsHTMLInputElement::DestroyUploadLastDir(); + + nsLayoutUtils::Shutdown(); }