diff --git a/mozilla/content/shared/public/nsXULAtomList.h b/mozilla/content/shared/public/nsXULAtomList.h index 0cb5de8129a..d5d01cec2eb 100644 --- a/mozilla/content/shared/public/nsXULAtomList.h +++ b/mozilla/content/shared/public/nsXULAtomList.h @@ -81,6 +81,8 @@ XUL_ATOM(acceltext, "acceltext") // Text to use for the accelerator XUL_ATOM(popupset, "popupset") // Contains popup menus, context menus, and tooltips XUL_ATOM(popup, "popup") // The popup for a context menu, popup menu, or tooltip XUL_ATOM(menugenerated, "menugenerated") // Internal +XUL_ATOM(popupanchor, "popupanchor") // Anchor for popups +XUL_ATOM(popupalign, "popupalign") // Alignment for popups XUL_ATOM(key, "key") // A key element XUL_ATOM(broadcaster, "broadcaster") // A broadcaster diff --git a/mozilla/layout/xul/base/src/nsMenuFrame.cpp b/mozilla/layout/xul/base/src/nsMenuFrame.cpp index 3e8ae9c7f9b..e4cd44a24d4 100644 --- a/mozilla/layout/xul/base/src/nsMenuFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuFrame.cpp @@ -518,11 +518,32 @@ nsMenuFrame::OpenMenuInternal(PRBool aActivateFlag) mMenuParent->SetActive(PR_TRUE); // Sync up the view. + nsCOMPtr menuPopupContent; + menuPopup->GetContent(getter_AddRefs(menuPopupContent)); + + nsAutoString popupAnchor, popupAlign; + + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupanchor, popupAnchor); + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupalign, popupAlign); + PRBool onMenuBar = PR_TRUE; if (mMenuParent) mMenuParent->IsMenuBar(onMenuBar); - menuPopup->SyncViewWithFrame(mPresContext, onMenuBar, this, -1, -1); + if (onMenuBar) { + if (popupAnchor == "") + popupAnchor = "bottomleft"; + if (popupAlign == "") + popupAlign = "topleft"; + } + else { + if (popupAnchor == "") + popupAnchor = "topright"; + if (popupAlign == "") + popupAlign = "topleft"; + } + + menuPopup->SyncViewWithFrame(mPresContext, popupAnchor, popupAlign, this, -1, -1); } ActivateMenu(PR_TRUE); @@ -650,11 +671,31 @@ nsMenuFrame::DidReflow(nsIPresContext* aPresContext, nsIFrame* frame = mPopupFrames.FirstChild(); nsMenuPopupFrame* menuPopup = (nsMenuPopupFrame*)frame; if (mMenuOpen && menuPopup) { + nsCOMPtr menuPopupContent; + menuPopup->GetContent(getter_AddRefs(menuPopupContent)); + nsAutoString popupAnchor, popupAlign; + + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupanchor, popupAnchor); + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupalign, popupAlign); + PRBool onMenuBar = PR_TRUE; if (mMenuParent) mMenuParent->IsMenuBar(onMenuBar); - menuPopup->SyncViewWithFrame(aPresContext, onMenuBar, this, -1, -1); + if (onMenuBar) { + if (popupAnchor == "") + popupAnchor = "bottomleft"; + if (popupAlign == "") + popupAlign = "topleft"; + } + else { + if (popupAnchor == "") + popupAnchor = "topright"; + if (popupAlign == "") + popupAlign = "topleft"; + } + + menuPopup->SyncViewWithFrame(aPresContext, popupAnchor, popupAlign, this, -1, -1); } return rv; diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp index f5a57de96de..497daf0162d 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -213,7 +213,8 @@ nsMenuPopupFrame::GetNearestEnclosingView(nsIPresContext* aPresContext, nsIFrame nsresult nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext* aPresContext, - PRBool aOnMenuBar, + const nsString& aPopupAnchor, + const nsString& aPopupAlign, nsIFrame* aFrame, PRInt32 aXPos, PRInt32 aYPos) { @@ -266,13 +267,41 @@ nsMenuPopupFrame::SyncViewWithFrame(nsIPresContext* aPresContext, ypos = NSIntPixelsToTwips(aYPos, p2t); xpos += offset.x; ypos += offset.y; - } else if (aOnMenuBar) { + } + else { xpos = parentPos.x + offset.x; - ypos = parentPos.y + parentRect.height + offset.y; - } else { - xpos = parentPos.x + parentRect.width + offset.x; ypos = parentPos.y + offset.y; + + if (aPopupAnchor == "topright" && aPopupAlign == "topleft") { + xpos += parentRect.width; + } + else if (aPopupAnchor == "topright" && aPopupAlign == "bottomright") { + xpos -= (mRect.width - parentRect.width); + ypos -= mRect.height; + } + else if (aPopupAnchor == "bottomright" && aPopupAlign == "bottomleft") { + xpos += parentRect.width; + ypos -= (mRect.height - parentRect.height); + } + else if (aPopupAnchor == "bottomright" && aPopupAlign == "topright") { + xpos -= (mRect.width - parentRect.width); + ypos += parentRect.height; + } + else if (aPopupAnchor == "topleft" && aPopupAlign == "topright") { + xpos -= mRect.width; + } + else if (aPopupAnchor == "topleft" && aPopupAlign == "bottomleft") { + ypos -= mRect.height; + } + else if (aPopupAnchor == "bottomleft" && aPopupAlign == "bottomright") { + xpos -= mRect.width; + ypos -= (mRect.height - parentRect.height); + } + else if (aPopupAnchor == "bottomleft" && aPopupAlign == "topleft") { + ypos += parentRect.height; + } } + viewManager->MoveViewTo(view, xpos, ypos); // Check if we fit on the screen, if not, resize and/or move so we do diff --git a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h index 9484098f369..7b4dd08752b 100644 --- a/mozilla/layout/xul/base/src/nsMenuPopupFrame.h +++ b/mozilla/layout/xul/base/src/nsMenuPopupFrame.h @@ -91,7 +91,8 @@ public: void GetViewOffset(nsIViewManager* aManager, nsIView* aView, nsPoint& aPoint); static void GetNearestEnclosingView(nsIPresContext* aPresContext, nsIFrame* aStartFrame, nsIView** aResult); - nsresult SyncViewWithFrame(nsIPresContext* aPresContext, PRBool aOnMenuBar, + nsresult SyncViewWithFrame(nsIPresContext* aPresContext, const nsString& aPopupAnchor, + const nsString& aPopupAlign, nsIFrame* aFrame, PRInt32 aXPos, PRInt32 aYPos); NS_IMETHOD CaptureMouseEvents(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); diff --git a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp index 52724b9ffb0..b35bad19bc4 100644 --- a/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp +++ b/mozilla/layout/xul/base/src/nsPopupSetFrame.cpp @@ -248,7 +248,20 @@ nsPopupSetFrame::DidReflow(nsIPresContext* aPresContext, // Sync up the view. nsIFrame* activeChild = GetActiveChild(); if (activeChild) { - ((nsMenuPopupFrame*)activeChild)->SyncViewWithFrame(aPresContext, PR_TRUE, mElementFrame, mXPos, mYPos); + + nsCOMPtr menuPopupContent; + activeChild->GetContent(getter_AddRefs(menuPopupContent)); + nsAutoString popupAnchor, popupAlign; + + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupanchor, popupAnchor); + menuPopupContent->GetAttribute(kNameSpaceID_None, nsXULAtoms::popupalign, popupAlign); + + if (popupAnchor == "") + popupAnchor = "bottomleft"; + if (popupAlign == "") + popupAlign = "topleft"; + + ((nsMenuPopupFrame*)activeChild)->SyncViewWithFrame(aPresContext, popupAnchor, popupAlign, mElementFrame, mXPos, mYPos); } return nsBoxFrame::DidReflow(aPresContext, aStatus); diff --git a/mozilla/layout/xul/content/src/nsXULAtomList.h b/mozilla/layout/xul/content/src/nsXULAtomList.h index 0cb5de8129a..d5d01cec2eb 100644 --- a/mozilla/layout/xul/content/src/nsXULAtomList.h +++ b/mozilla/layout/xul/content/src/nsXULAtomList.h @@ -81,6 +81,8 @@ XUL_ATOM(acceltext, "acceltext") // Text to use for the accelerator XUL_ATOM(popupset, "popupset") // Contains popup menus, context menus, and tooltips XUL_ATOM(popup, "popup") // The popup for a context menu, popup menu, or tooltip XUL_ATOM(menugenerated, "menugenerated") // Internal +XUL_ATOM(popupanchor, "popupanchor") // Anchor for popups +XUL_ATOM(popupalign, "popupalign") // Alignment for popups XUL_ATOM(key, "key") // A key element XUL_ATOM(broadcaster, "broadcaster") // A broadcaster