Bug 1206133 - Add popuppositioning state and popuppositioned event to improve arrow panel position handling. r=enndeakin

MozReview-Commit-ID: Dh1npORCQ6J
This commit is contained in:
Kirk Steuber
2016-08-16 15:33:05 -07:00
parent d2a51bc471
commit 2c1ac87580
13 changed files with 272 additions and 61 deletions

View File

@@ -436,7 +436,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
if (!isOpen) {
// if the popup is not open, only do layout while showing or if the menu
// is sized to the popup
shouldPosition = (mPopupState == ePopupShowing);
shouldPosition = (mPopupState == ePopupShowing || mPopupState == ePopupPositioning);
if (!shouldPosition && !aSizedToPopup) {
RemoveStateBits(NS_FRAME_FIRST_REFLOW);
return;
@@ -476,7 +476,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
bool needCallback = false;
if (shouldPosition) {
SetPopupPosition(aAnchor, false, aSizedToPopup);
SetPopupPosition(aAnchor, false, aSizedToPopup, mPopupState == ePopupPositioning);
needCallback = true;
}
@@ -502,7 +502,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
}
if (rePosition) {
SetPopupPosition(aAnchor, false, aSizedToPopup);
SetPopupPosition(aAnchor, false, aSizedToPopup, false);
}
nsPresContext* pc = PresContext();
@@ -561,7 +561,7 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
bool
nsMenuPopupFrame::ReflowFinished()
{
SetPopupPosition(mReflowCallbackData.mAnchor, false, mReflowCallbackData.mSizedToPopup);
SetPopupPosition(mReflowCallbackData.mAnchor, false, mReflowCallbackData.mSizedToPopup, false);
mReflowCallbackData.Clear();
@@ -865,7 +865,7 @@ nsMenuPopupFrame::ShowPopup(bool aIsContextMenu)
InvalidateFrameSubtree();
if (mPopupState == ePopupShowing) {
if (mPopupState == ePopupShowing || mPopupState == ePopupPositioning) {
mPopupState = ePopupOpening;
mIsOpenChanged = true;
@@ -906,7 +906,8 @@ nsMenuPopupFrame::HidePopup(bool aDeselectMenu, nsPopupState aNewState)
ClearPopupShownDispatcher();
// don't hide the popup when it isn't open
if (mPopupState == ePopupClosed || mPopupState == ePopupShowing)
if (mPopupState == ePopupClosed || mPopupState == ePopupShowing ||
mPopupState == ePopupPositioning)
return;
// clear the trigger content if the popup is being closed. But don't clear
@@ -1184,6 +1185,8 @@ nsMenuPopupFrame::FlipOrResize(nscoord& aScreenPoint, nscoord aSize,
nscoord aOffsetForContextMenu, FlipStyle aFlip,
bool* aFlipSide)
{
*aFlipSide = false;
// all of the coordinates used here are in app units relative to the screen
nscoord popupSize = aSize;
if (aScreenPoint < aScreenBegin) {
@@ -1284,7 +1287,7 @@ nsMenuPopupFrame::FlipOrResize(nscoord& aScreenPoint, nscoord aSize,
}
nsresult
nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aSizedToPopup)
nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aSizedToPopup, bool aNotify)
{
if (!mShouldAutoPosition)
return NS_OK;
@@ -1589,6 +1592,17 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
SetXULBounds(state, mRect);
}
// If the popup is in the positioned state or if it is shown and the position
// or size changed, dispatch a popuppositioned event if the popup wants it.
nsIntRect newRect(screenPoint.x, screenPoint.y, mRect.width, mRect.height);
if (mPopupState == ePopupPositioning ||
(mPopupState == ePopupShown && !newRect.IsEqualEdges(mUsedScreenRect))) {
mUsedScreenRect = newRect;
if (aNotify) {
nsXULPopupPositionedEvent::DispatchIfNeeded(mContent, false, false);
}
}
return NS_OK;
}
@@ -2270,7 +2284,7 @@ nsMenuPopupFrame::MoveTo(const CSSIntPoint& aPos, bool aUpdateAttrs)
mScreenRect.x = aPos.x - presContext->AppUnitsToIntCSSPixels(margin.left);
mScreenRect.y = aPos.y - presContext->AppUnitsToIntCSSPixels(margin.top);
SetPopupPosition(nullptr, true, false);
SetPopupPosition(nullptr, true, false, true);
nsCOMPtr<nsIContent> popup = mContent;
if (aUpdateAttrs && (popup->HasAttr(kNameSpaceID_None, nsGkAtoms::left) ||
@@ -2299,7 +2313,7 @@ nsMenuPopupFrame::MoveToAnchor(nsIContent* aAnchorContent,
mPopupState = oldstate;
// Pass false here so that flipping and adjusting to fit on the screen happen.
SetPopupPosition(nullptr, false, false);
SetPopupPosition(nullptr, false, false, true);
}
bool