diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 7e8e8ea88de2..90d073b83e3e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -89,6 +89,7 @@ #include "imgIContainer.h" #include "nsIImageLoadingContent.h" #include "nsCOMPtr.h" +#include "nsListControlFrame.h" #ifdef MOZ_SVG #include "nsSVGUtils.h" @@ -3233,6 +3234,38 @@ nsLayoutUtils::GetFrameTransparency(nsIFrame* aBackgroundFrame, return eTransparencyOpaque; } +/* static */ PRBool +nsLayoutUtils::IsPopup(nsIFrame* aFrame) +{ + nsIAtom* frameType = aFrame->GetType(); + + // We're a popup if we're the list control frame dropdown for a combobox. + if (frameType == nsGkAtoms::listControlFrame) { + nsListControlFrame* listControlFrame = static_cast(aFrame); + + if (listControlFrame) { + return listControlFrame->IsInDropDownMode(); + } + } + + // ... or if we're a XUL menupopup frame. + return (frameType == nsGkAtoms::menuPopupFrame); +} + +/* static */ nsIFrame* +nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame) +{ + nsIFrame* f = aFrame; + for (;;) { + if (IsPopup(f)) + return f; + nsIFrame* parent = GetCrossDocParentFrame(f); + if (!parent) + return f; + f = parent; + } +} + static PRBool IsNonzeroCoord(const nsStyleCoord& aCoord) { diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 90dafda63ab6..cea1328f953d 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1019,6 +1019,18 @@ public: static nsTransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame, nsIFrame* aCSSRootFrame); + /** + * A frame is a popup if it has its own floating window. Menus, panels + * and combobox dropdowns are popups. + */ + static PRBool IsPopup(nsIFrame* aFrame); + + /** + * Find the nearest "display root". This is the nearest enclosing + * popup frame or the root prescontext's root frame. + */ + static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); + /** * Get textrun construction flags determined by a given style; in particular * some combination of: diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 9de54442c354..c9ea5369cb10 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -1020,12 +1020,6 @@ nsListControlFrame::CaptureMouseEvents(PRBool aGrabMouseEvents) // code paths, if any exist). if (aGrabMouseEvents && IsInDropDownMode() && nsComboboxControlFrame::ToolkitHasNativePopup()) return; - - nsIView* view = GetScrolledFrame()->GetView(); - - NS_ASSERTION(view, "no view???"); - if (NS_UNLIKELY(!view)) - return; if (aGrabMouseEvents) { nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6f83a7e2a70e..1fb3d03bfe65 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1422,7 +1422,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, nsPlaceholderFrame* placeholder = static_cast(aChild); aChild = placeholder->GetOutOfFlowFrame(); NS_ASSERTION(aChild, "No out of flow frame?"); - if (!aChild || aChild->GetType() == nsGkAtoms::menuPopupFrame) + if (!aChild || nsLayoutUtils::IsPopup(aChild)) return NS_OK; // update for the new child disp = aChild->GetStyleDisplay();