Bug 956162 - Implement @flip="none" for popups to allow them to appear off-screen without flipping or resizing. r=Enn

--HG--
extra : rebase_source : f5ddca505eb8a3b234718df1ae01c9a49a02a361
This commit is contained in:
Matthew Noorenberghe 2014-01-22 20:09:03 +00:00
parent 4a2291060e
commit ea7f5d5b8f
3 changed files with 24 additions and 13 deletions

View File

@ -217,6 +217,7 @@
hidden="true" hidden="true"
noautofocus="true" noautofocus="true"
noautohide="true" noautohide="true"
flip="none"
consumeoutsideclicks="false"> consumeoutsideclicks="false">
<box id="UITourHighlight"></box> <box id="UITourHighlight"></box>
</panel> </panel>

View File

@ -87,7 +87,7 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContex
mPopupAnchor(POPUPALIGNMENT_NONE), mPopupAnchor(POPUPALIGNMENT_NONE),
mPosition(POPUPPOSITION_UNKNOWN), mPosition(POPUPPOSITION_UNKNOWN),
mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT), mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT),
mFlipBoth(false), mFlip(FlipType_Default),
mIsOpenChanged(false), mIsOpenChanged(false),
mIsContextMenu(false), mIsContextMenu(false),
mAdjustOffsetForContextMenu(false), mAdjustOffsetForContextMenu(false),
@ -581,8 +581,13 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
position.Assign(aPosition); position.Assign(aPosition);
} }
mFlipBoth = flip.EqualsLiteral("both"); if (flip.EqualsLiteral("none")) {
mSlide = flip.EqualsLiteral("slide"); mFlip = FlipType_None;
} else if (flip.EqualsLiteral("both")) {
mFlip = FlipType_Both;
} else if (flip.EqualsLiteral("slide")) {
mFlip = FlipType_Slide;
}
position.CompressWhitespace(); position.CompressWhitespace();
int32_t spaceIdx = position.FindChar(' '); int32_t spaceIdx = position.FindChar(' ');
@ -685,8 +690,7 @@ nsMenuPopupFrame::InitializePopupAtScreen(nsIContent* aTriggerContent,
mTriggerContent = aTriggerContent; mTriggerContent = aTriggerContent;
mScreenXPos = aXPos; mScreenXPos = aXPos;
mScreenYPos = aYPos; mScreenYPos = aYPos;
mFlipBoth = false; mFlip = FlipType_Default;
mSlide = false;
mPopupAnchor = POPUPALIGNMENT_NONE; mPopupAnchor = POPUPALIGNMENT_NONE;
mPopupAlignment = POPUPALIGNMENT_NONE; mPopupAlignment = POPUPALIGNMENT_NONE;
mIsContextMenu = aIsContextMenu; mIsContextMenu = aIsContextMenu;
@ -703,8 +707,7 @@ nsMenuPopupFrame::InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
mPopupState = ePopupShowing; mPopupState = ePopupShowing;
mAdjustOffsetForContextMenu = false; mAdjustOffsetForContextMenu = false;
mFlipBoth = false; mFlip = FlipType_Default;
mSlide = false;
// this popup opening function is provided for backwards compatibility // this popup opening function is provided for backwards compatibility
// only. It accepts either coordinates or an anchor and alignment value // only. It accepts either coordinates or an anchor and alignment value
@ -981,7 +984,7 @@ nsMenuPopupFrame::AdjustPositionForAnchorAlign(nsRect& anchorRect,
break; break;
default: default:
{ {
FlipStyle anchorEdge = mFlipBoth ? FlipStyle_Inside : FlipStyle_None; FlipStyle anchorEdge = mFlip == FlipType_Both ? FlipStyle_Inside : FlipStyle_None;
aHFlip = (popupAnchor == -popupAlign) ? FlipStyle_Outside : anchorEdge; aHFlip = (popupAnchor == -popupAlign) ? FlipStyle_Outside : anchorEdge;
if (((popupAnchor > 0) == (popupAlign > 0)) || if (((popupAnchor > 0) == (popupAlign > 0)) ||
(popupAnchor == POPUPALIGNMENT_TOPLEFT && popupAlign == POPUPALIGNMENT_TOPLEFT)) (popupAnchor == POPUPALIGNMENT_TOPLEFT && popupAlign == POPUPALIGNMENT_TOPLEFT))
@ -1271,9 +1274,9 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove)
vFlip = FlipStyle_Outside; vFlip = FlipStyle_Outside;
} }
// If a panel is being moved, don't constrain or flip it. But always do this for // If a panel is being moved or has flip="none", don't constrain or flip it. But always do this for
// content shells, so that the popup doesn't extend outside the containing frame. // content shells, so that the popup doesn't extend outside the containing frame.
if (mInContentShell || !aIsMove || mPopupType != ePopupTypePanel) { if (mInContentShell || (mFlip != FlipType_None && (!aIsMove || mPopupType != ePopupTypePanel))) {
nsRect screenRect = GetConstraintRect(anchorRect, rootScreenRect); nsRect screenRect = GetConstraintRect(anchorRect, rootScreenRect);
// ensure that anchorRect is on screen // ensure that anchorRect is on screen
@ -1303,7 +1306,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove)
// but we can only slide on one axis - the other axis must be "flipped or // but we can only slide on one axis - the other axis must be "flipped or
// resized" as normal. // resized" as normal.
bool slideHorizontal = false, slideVertical = false; bool slideHorizontal = false, slideVertical = false;
if (mSlide) { if (mFlip == FlipType_Slide) {
int8_t position = GetAlignmentPosition(); int8_t position = GetAlignmentPosition();
slideHorizontal = position >= POPUPPOSITION_BEFORESTART && slideHorizontal = position >= POPUPPOSITION_BEFORESTART &&
position <= POPUPPOSITION_AFTEREND; position <= POPUPPOSITION_AFTEREND;

View File

@ -65,6 +65,14 @@ enum FlipStyle {
FlipStyle_Inside = 2 FlipStyle_Inside = 2
}; };
// Values for the flip attribute
enum FlipType {
FlipType_Default = 0,
FlipType_None = 1, // don't try to flip or translate to stay onscreen
FlipType_Both = 2, // flip in both directions
FlipType_Slide = 3 // allow the arrow to "slide" instead of resizing
};
// values are selected so that the direction can be flipped just by // values are selected so that the direction can be flipped just by
// changing the sign // changing the sign
#define POPUPALIGNMENT_NONE 0 #define POPUPALIGNMENT_NONE 0
@ -459,8 +467,7 @@ protected:
// One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
int8_t mConsumeRollupEvent; int8_t mConsumeRollupEvent;
bool mFlipBoth; // flip in both directions FlipType mFlip; // Whether to flip
bool mSlide; // allow the arrow to "slide" instead of resizing
bool mIsOpenChanged; // true if the open state changed since the last layout bool mIsOpenChanged; // true if the open state changed since the last layout
bool mIsContextMenu; // true for context menus bool mIsContextMenu; // true for context menus