зеркало из https://github.com/mozilla/gecko-dev.git
Bug 728913 - Remove the nsMenuFrame::mPopupFrame member and store it in a nsFrameList* frame property instead (as needed). r=bz
This commit is contained in:
Родитель
c1f99b666b
Коммит
d1874aa971
|
@ -61,7 +61,7 @@ class nsBoxLayoutState;
|
|||
#define NS_STATE_CURRENTLY_IN_DEBUG NS_FRAME_STATE_BIT(25)
|
||||
//#define NS_STATE_SET_TO_DEBUG NS_FRAME_STATE_BIT(26) moved to nsBox.h
|
||||
//#define NS_STATE_DEBUG_WAS_SET NS_FRAME_STATE_BIT(27) moved to nsBox.h
|
||||
// NS_FRAME_STATE_BIT(28) not used anymore
|
||||
#define NS_STATE_MENU_HAS_POPUP_LIST NS_FRAME_STATE_BIT(28) /* used on nsMenuFrame */
|
||||
#define NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK NS_FRAME_STATE_BIT(29)
|
||||
#define NS_STATE_EQUAL_SIZE NS_FRAME_STATE_BIT(30)
|
||||
//#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31) moved to nsIFrame.h
|
||||
|
|
|
@ -87,6 +87,13 @@ using namespace mozilla;
|
|||
#define NSCONTEXTMENUISMOUSEUP 1
|
||||
#endif
|
||||
|
||||
static void
|
||||
AssertNotCalled(void* aPropertyValue)
|
||||
{
|
||||
NS_ERROR("popup list should never be destroyed by the FramePropertyTable");
|
||||
}
|
||||
NS_DECLARE_FRAME_PROPERTY(PopupListProperty, AssertNotCalled)
|
||||
|
||||
static PRInt32 gEatMouseMove = false;
|
||||
|
||||
const PRInt32 kBlinkDelay = 67; // milliseconds
|
||||
|
@ -207,9 +214,6 @@ NS_QUERYFRAME_HEAD(nsMenuFrame)
|
|||
NS_QUERYFRAME_ENTRY(nsMenuFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
//
|
||||
// nsMenuFrame cntr
|
||||
//
|
||||
nsMenuFrame::nsMenuFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
||||
nsBoxFrame(aShell, aContext),
|
||||
mIsMenu(false),
|
||||
|
@ -217,11 +221,9 @@ nsMenuFrame::nsMenuFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
|||
mIgnoreAccelTextChange(false),
|
||||
mType(eMenuType_Normal),
|
||||
mMenuParent(nsnull),
|
||||
mPopupFrame(nsnull),
|
||||
mBlinkState(0)
|
||||
{
|
||||
|
||||
} // cntr
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuFrame::SetParent(nsIFrame* aParent)
|
||||
|
@ -302,7 +304,8 @@ nsFrameList
|
|||
nsMenuFrame::GetChildList(ChildListID aListID) const
|
||||
{
|
||||
if (kPopupList == aListID) {
|
||||
return nsFrameList(mPopupFrame, mPopupFrame);
|
||||
nsFrameList* list = GetPopupList();
|
||||
return list ? *list : nsFrameList::EmptyList();
|
||||
}
|
||||
return nsBoxFrame::GetChildList(aListID);
|
||||
}
|
||||
|
@ -311,8 +314,44 @@ void
|
|||
nsMenuFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
||||
{
|
||||
nsBoxFrame::GetChildLists(aLists);
|
||||
nsFrameList popupList(mPopupFrame, mPopupFrame);
|
||||
popupList.AppendIfNonempty(aLists, kPopupList);
|
||||
nsFrameList* list = GetPopupList();
|
||||
if (list) {
|
||||
list->AppendIfNonempty(aLists, kPopupList);
|
||||
}
|
||||
}
|
||||
|
||||
nsMenuPopupFrame*
|
||||
nsMenuFrame::GetPopup()
|
||||
{
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
return popupList ? static_cast<nsMenuPopupFrame*>(popupList->FirstChild()) :
|
||||
nsnull;
|
||||
}
|
||||
|
||||
nsFrameList*
|
||||
nsMenuFrame::GetPopupList() const
|
||||
{
|
||||
if (!HasPopup()) {
|
||||
return nsnull;
|
||||
}
|
||||
nsFrameList* prop =
|
||||
static_cast<nsFrameList*>(Properties().Get(PopupListProperty()));
|
||||
NS_ASSERTION(prop && prop->GetLength() == 1 &&
|
||||
prop->FirstChild()->GetType() == nsGkAtoms::menuPopupFrame,
|
||||
"popup list should have exactly one nsMenuPopupFrame");
|
||||
return prop;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuFrame::DestroyPopupList()
|
||||
{
|
||||
NS_ASSERTION(HasPopup(), "huh?");
|
||||
nsFrameList* prop =
|
||||
static_cast<nsFrameList*>(Properties().Remove(PopupListProperty()));
|
||||
NS_ASSERTION(prop && prop->IsEmpty(),
|
||||
"popup list must exist and be empty when destroying");
|
||||
RemoveStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
|
||||
delete prop;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -320,9 +359,12 @@ nsMenuFrame::SetPopupFrame(nsFrameList& aFrameList)
|
|||
{
|
||||
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
|
||||
if (e.get()->GetType() == nsGkAtoms::menuPopupFrame) {
|
||||
// Remove this frame from the list and set it as mPopupFrame
|
||||
mPopupFrame = (nsMenuPopupFrame *)e.get();
|
||||
aFrameList.RemoveFrame(e.get());
|
||||
// Remove the frame from the list and store it in a nsFrameList* property.
|
||||
nsIFrame* popupFrame = e.get();
|
||||
aFrameList.RemoveFrame(popupFrame);
|
||||
nsFrameList* popupList = new nsFrameList(popupFrame, popupFrame);
|
||||
Properties().Set(PopupListProperty(), popupList);
|
||||
AddStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +374,7 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::SetInitialChildList(ChildListID aListID,
|
||||
nsFrameList& aChildList)
|
||||
{
|
||||
NS_ASSERTION(!mPopupFrame, "already have a popup frame set");
|
||||
NS_ASSERTION(!HasPopup(), "SetInitialChildList called twice?");
|
||||
if (aListID == kPrincipalList || aListID == kPopupList) {
|
||||
SetPopupFrame(aChildList);
|
||||
}
|
||||
|
@ -365,8 +407,11 @@ nsMenuFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mMenuParent->CurrentMenuIsBeingDestroyed();
|
||||
}
|
||||
|
||||
if (mPopupFrame)
|
||||
mPopupFrame->DestroyFrom(aDestructRoot);
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
if (popupList) {
|
||||
popupList->DestroyFramesFrom(aDestructRoot);
|
||||
DestroyPopupList();
|
||||
}
|
||||
|
||||
nsBoxFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
@ -675,8 +720,8 @@ nsMenuFrame::CloseMenu(bool aDeselectMenu)
|
|||
|
||||
// Close the menu asynchronously
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && mPopupFrame)
|
||||
pm->HidePopup(mPopupFrame->GetContent(), false, aDeselectMenu, true);
|
||||
if (pm && HasPopup())
|
||||
pm->HidePopup(GetPopup()->GetContent(), false, aDeselectMenu, true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -713,9 +758,10 @@ nsMenuFrame::DoLayout(nsBoxLayoutState& aState)
|
|||
// lay us out
|
||||
nsresult rv = nsBoxFrame::DoLayout(aState);
|
||||
|
||||
if (mPopupFrame) {
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (popupFrame) {
|
||||
bool sizeToPopup = IsSizedToPopup(mContent, false);
|
||||
mPopupFrame->LayoutPopup(aState, this, sizeToPopup);
|
||||
popupFrame->LayoutPopup(aState, this, sizeToPopup);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -733,8 +779,9 @@ nsMenuFrame::SetDebug(nsBoxLayoutState& aState, bool aDebug)
|
|||
if (debugChanged)
|
||||
{
|
||||
nsBoxFrame::SetDebug(aState, aDebug);
|
||||
if (mPopupFrame)
|
||||
SetDebug(aState, mPopupFrame, aDebug);
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (popupFrame)
|
||||
SetDebug(aState, popupFrame, aDebug);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -797,7 +844,8 @@ nsMenuFrame::Enter(nsGUIEvent *aEvent)
|
|||
bool
|
||||
nsMenuFrame::IsOpen()
|
||||
{
|
||||
return mPopupFrame && mPopupFrame->IsOpen();
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
return popupFrame && popupFrame->IsOpen();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1248,21 +1296,15 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::RemoveFrame(ChildListID aListID,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mPopupFrame == aOldFrame) {
|
||||
// Go ahead and remove this frame.
|
||||
mPopupFrame->Destroy();
|
||||
mPopupFrame = nsnull;
|
||||
nsFrameList* popupList = GetPopupList();
|
||||
if (popupList && popupList->DestroyFrameIfPresent(aOldFrame)) {
|
||||
DestroyPopupList();
|
||||
PresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
||||
NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
return nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1270,9 +1312,9 @@ nsMenuFrame::InsertFrames(ChildListID aListID,
|
|||
nsIFrame* aPrevFrame,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
if (!mPopupFrame && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
SetPopupFrame(aFrameList);
|
||||
if (mPopupFrame) {
|
||||
if (HasPopup()) {
|
||||
#ifdef DEBUG_LAYOUT
|
||||
nsBoxLayoutState state(PresContext());
|
||||
SetDebug(state, aFrameList, mState & NS_STATE_CURRENTLY_IN_DEBUG);
|
||||
|
@ -1287,7 +1329,7 @@ nsMenuFrame::InsertFrames(ChildListID aListID,
|
|||
if (aFrameList.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
if (NS_UNLIKELY(aPrevFrame == mPopupFrame)) {
|
||||
if (NS_UNLIKELY(aPrevFrame && aPrevFrame == GetPopup())) {
|
||||
aPrevFrame = nsnull;
|
||||
}
|
||||
|
||||
|
@ -1298,9 +1340,9 @@ NS_IMETHODIMP
|
|||
nsMenuFrame::AppendFrames(ChildListID aListID,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
if (!mPopupFrame && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
if (!HasPopup() && (aListID == kPrincipalList || aListID == kPopupList)) {
|
||||
SetPopupFrame(aFrameList);
|
||||
if (mPopupFrame) {
|
||||
if (HasPopup()) {
|
||||
|
||||
#ifdef DEBUG_LAYOUT
|
||||
nsBoxLayoutState state(PresContext());
|
||||
|
@ -1326,9 +1368,10 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
|
|||
nsSize tmpSize(-1, 0);
|
||||
nsIBox::AddCSSPrefSize(this, tmpSize, widthSet, heightSet);
|
||||
if (!widthSet && GetFlex(aState) == 0) {
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return false;
|
||||
tmpSize = mPopupFrame->GetPrefSize(aState);
|
||||
tmpSize = popupFrame->GetPrefSize(aState);
|
||||
|
||||
// Produce a size such that:
|
||||
// (1) the menu and its popup can be the same width
|
||||
|
@ -1340,7 +1383,7 @@ nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
|
|||
GetBorderAndPadding(borderPadding);
|
||||
|
||||
// if there is a scroll frame, add the desired width of the scrollbar as well
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(mPopupFrame->GetFirstPrincipalChild());
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(popupFrame->GetFirstPrincipalChild());
|
||||
nscoord scrollbarWidth = 0;
|
||||
if (scrollFrame) {
|
||||
scrollbarWidth =
|
||||
|
@ -1380,10 +1423,11 @@ nsMenuFrame::GetPrefSize(nsBoxLayoutState& aState)
|
|||
NS_IMETHODIMP
|
||||
nsMenuFrame::GetActiveChild(nsIDOMElement** aResult)
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsMenuFrame* menuFrame = mPopupFrame->GetCurrentMenuItem();
|
||||
nsMenuFrame* menuFrame = popupFrame->GetCurrentMenuItem();
|
||||
if (!menuFrame) {
|
||||
*aResult = nsnull;
|
||||
}
|
||||
|
@ -1399,12 +1443,13 @@ nsMenuFrame::GetActiveChild(nsIDOMElement** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (!aChild) {
|
||||
// Remove the current selection
|
||||
mPopupFrame->ChangeMenuItem(nsnull, false);
|
||||
popupFrame->ChangeMenuItem(nsnull, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1412,17 +1457,18 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
|||
|
||||
nsIFrame* kid = child->GetPrimaryFrame();
|
||||
if (kid && kid->GetType() == nsGkAtoms::menuFrame)
|
||||
mPopupFrame->ChangeMenuItem(static_cast<nsMenuFrame *>(kid), false);
|
||||
popupFrame->ChangeMenuItem(static_cast<nsMenuFrame *>(kid), false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* nsMenuFrame::GetScrollTargetFrame()
|
||||
{
|
||||
if (!mPopupFrame)
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (!popupFrame)
|
||||
return nsnull;
|
||||
nsIFrame* childFrame = mPopupFrame->GetFirstPrincipalChild();
|
||||
nsIFrame* childFrame = popupFrame->GetFirstPrincipalChild();
|
||||
if (childFrame)
|
||||
return mPopupFrame->GetScrollFrame(childFrame);
|
||||
return popupFrame->GetScrollFrame(childFrame);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,16 @@ public:
|
|||
virtual nsMenuParent *GetMenuParent() { return mMenuParent; }
|
||||
const nsAString& GetRadioGroupName() { return mGroupName; }
|
||||
nsMenuType GetMenuType() { return mType; }
|
||||
nsMenuPopupFrame* GetPopup() { return mPopupFrame; }
|
||||
nsMenuPopupFrame* GetPopup();
|
||||
|
||||
/**
|
||||
* @return true if this frame has a popup child frame.
|
||||
*/
|
||||
bool HasPopup() const
|
||||
{
|
||||
return (GetStateBits() & NS_STATE_MENU_HAS_POPUP_LIST) != 0;
|
||||
}
|
||||
|
||||
|
||||
// nsMenuFrame methods
|
||||
|
||||
|
@ -226,10 +235,23 @@ protected:
|
|||
friend class nsASyncMenuInitialization;
|
||||
friend class nsMenuAttributeChangedEvent;
|
||||
|
||||
// initialize mPopupFrame to the first popup frame within
|
||||
// aChildList. Removes the popup, if any, from aChildList.
|
||||
/**
|
||||
* Initialize the popup list to the first popup frame within
|
||||
* aChildList. Removes the popup, if any, from aChildList.
|
||||
*/
|
||||
void SetPopupFrame(nsFrameList& aChildList);
|
||||
|
||||
/**
|
||||
* Get the popup frame list from the frame property.
|
||||
* @return the property value if it exists, nsnull otherwise.
|
||||
*/
|
||||
nsFrameList* GetPopupList() const;
|
||||
|
||||
/**
|
||||
* Destroy the popup list property. The list must exist and be empty.
|
||||
*/
|
||||
void DestroyPopupList();
|
||||
|
||||
// set mMenuParent to the nearest enclosing menu bar or menupopup frame of
|
||||
// aParent (or aParent itself). This is called when initializing the frame,
|
||||
// so aParent should be the expected parent of this frame.
|
||||
|
@ -275,9 +297,6 @@ protected:
|
|||
|
||||
nsMenuParent* mMenuParent; // Our parent menu.
|
||||
|
||||
// the popup for this menu, owned
|
||||
nsMenuPopupFrame* mPopupFrame;
|
||||
|
||||
// Reference to the mediator which wraps this frame.
|
||||
nsRefPtr<nsMenuTimerMediator> mTimerMediator;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче