Bug 312225. When we flip a menu vertically to keep it off the bottom of the screen, we need to reverse the 2px vertical offset from the mouse cursor that we introduce for context menus.

This commit is contained in:
roc+@cs.cmu.edu 2008-04-23 14:25:34 -07:00
Родитель b7f62b8621
Коммит 7f0ad58213
5 изменённых файлов: 35 добавлений и 12 удалений

Просмотреть файл

@ -470,13 +470,6 @@ nsXULPopupListener::LaunchPopup(nsIDOMEvent* aEvent, nsIContent* aTargetContent)
mouseEvent->GetScreenX(&xPos);
mouseEvent->GetScreenY(&yPos);
if (mIsContext) {
// position the menu two pixels down and to the right from the current
// mouse position. This makes it easier to dismiss the menu by just clicking
xPos += 2;
yPos += 2;
}
pm->ShowPopupAtScreen(mPopupContent, xPos, yPos, mIsContext, aEvent);
}

Просмотреть файл

@ -422,6 +422,10 @@ public:
* measured in CSS pixels.
*
* This fires the popupshowing event synchronously.
*
* If aIsContextMenu is true, the popup is positioned at a slight
* offset from aXPos/aYPos to ensure that it is not under the mouse
* cursor.
*/
void ShowPopupAtScreen(nsIContent* aPopup,
PRInt32 aXPos, PRInt32 aYPos,

Просмотреть файл

@ -110,6 +110,7 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContex
mPopupState(ePopupClosed),
mIsOpenChanged(PR_FALSE),
mIsContextMenu(PR_FALSE),
mAdjustOffsetForContextMenu(PR_FALSE),
mGeneratedChildren(PR_FALSE),
mMenuCanOverlapOSBar(PR_FALSE),
mShouldAutoPosition(PR_TRUE),
@ -381,6 +382,7 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
mAnchorContent = aAnchorContent;
mXPos = aXPos;
mYPos = aYPos;
mAdjustOffsetForContextMenu = PR_FALSE;
// if aAttributesOverride is true, then the popupanchor, popupalign and
// position attributes on the <popup> override those values passed in.
@ -476,7 +478,8 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
}
void
nsMenuPopupFrame::InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos)
nsMenuPopupFrame::InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos,
PRBool aIsContextMenu)
{
EnsureWidget();
@ -486,6 +489,8 @@ nsMenuPopupFrame::InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos)
mScreenYPos = aYPos;
mPopupAnchor = POPUPALIGNMENT_NONE;
mPopupAlignment = POPUPALIGNMENT_NONE;
mIsContextMenu = aIsContextMenu;
mAdjustOffsetForContextMenu = aIsContextMenu;
}
void
@ -497,6 +502,7 @@ nsMenuPopupFrame::InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
EnsureWidget();
mPopupState = ePopupShowing;
mAdjustOffsetForContextMenu = PR_FALSE;
// this popup opening function is provided for backwards compatibility
// only. It accepts either coordinates or an anchor and alignment value
@ -947,6 +953,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame)
nsRect rootScreenRect = rootFrame->GetScreenRect();
nsIDeviceContext* devContext = PresContext()->DeviceContext();
nscoord offsetForContextMenu = 0;
if (mScreenXPos == -1 && mScreenYPos == -1) {
// if we are anchored to our parent, there are certain things we don't want to do
// when repositioning the view to fit on the screen, such as end up positioned over
@ -986,11 +993,19 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame)
screenViewLocX = nsPresContext::CSSPixelsToAppUnits(mScreenXPos) / factor;
screenViewLocY = nsPresContext::CSSPixelsToAppUnits(mScreenYPos) / factor;
if (mAdjustOffsetForContextMenu) {
PRInt32 offsetForContextMenuDev =
nsPresContext::CSSPixelsToAppUnits(2) / factor;
offsetForContextMenu = presContext->DevPixelsToAppUnits(offsetForContextMenuDev);
}
// next, convert back into app units accounting for the scaling,
// and add the margins on the popup
GetStyleMargin()->GetMargin(margin);
screenViewLocX = presContext->DevPixelsToAppUnits(screenViewLocX) + margin.left;
screenViewLocY = presContext->DevPixelsToAppUnits(screenViewLocY) + margin.top;
screenViewLocX = presContext->DevPixelsToAppUnits(screenViewLocX) +
margin.left + offsetForContextMenu;
screenViewLocY = presContext->DevPixelsToAppUnits(screenViewLocY) +
margin.top + offsetForContextMenu;
// determine the x and y position by subtracting the desired screen
// position from the screen position of the root frame.
@ -1213,6 +1228,9 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame)
} else {
// More space above our desired point. Flip and resize to fit in this
// space.
// First move screenViewLocY and ypos up because the offset needs to flip
screenViewLocY -= 2*offsetForContextMenu;
ypos -= 2*offsetForContextMenu;
if (mRect.height > screenViewLocY - screenTopTwips) {
// We wouldn't fit. Shorten before flipping.
mRect.height = screenViewLocY - screenTopTwips;

Просмотреть файл

@ -228,7 +228,13 @@ public:
PRInt32 aXPos, PRInt32 aYPos,
PRBool aAttributesOverride);
void InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos);
/**
* @param aIsContextMenu if true, then the popup is
* positioned at a slight offset from aXPos/aYPos to ensure the
* (presumed) mouse position is not over the menu.
*/
void InitializePopupAtScreen(PRInt32 aXPos, PRInt32 aYPos,
PRBool aIsContextMenu);
void InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
nsAString& aAnchor,
@ -327,6 +333,8 @@ protected:
PRPackedBool mIsOpenChanged; // true if the open state changed since the last layout
PRPackedBool mIsContextMenu; // true for context menus
// true if we need to offset the popup to ensure it's not under the mouse
PRPackedBool mAdjustOffsetForContextMenu;
PRPackedBool mGeneratedChildren; // true if the contents have been created
PRPackedBool mMenuCanOverlapOSBar; // can we appear over the taskbar/menubar?

Просмотреть файл

@ -469,7 +469,7 @@ nsXULPopupManager::ShowPopupAtScreen(nsIContent* aPopup,
SetTriggerEvent(aTriggerEvent, aPopup);
popupFrame->InitializePopupAtScreen(aXPos, aYPos);
popupFrame->InitializePopupAtScreen(aXPos, aYPos, aIsContextMenu);
FirePopupShowingEvent(aPopup, nsnull, popupFrame->PresContext(),
popupFrame->PopupType(), aIsContextMenu, PR_FALSE);