mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 20:01:50 +00:00
Bug 873923, add a method to allow popups to be anchored at a rectangle, r=tn,mark,khuey
This commit is contained in:
parent
078bd82f31
commit
759d8c25e5
@ -129,6 +129,21 @@ interface PopupBoxObject : BoxObject
|
||||
boolean isContextMenu,
|
||||
Event? triggerEvent);
|
||||
|
||||
/**
|
||||
* Open the popup anchored at a specific screen rectangle. This function is
|
||||
* similar to openPopup except that that rectangle of the anchor is supplied
|
||||
* rather than an element. The anchor rectangle arguments are screen
|
||||
* coordinates.
|
||||
*/
|
||||
void openPopupAtScreenRect(optional DOMString position = "",
|
||||
long x,
|
||||
long y,
|
||||
long width,
|
||||
long height,
|
||||
boolean isContextMenu,
|
||||
boolean attributesOverride,
|
||||
Event? triggerEvent);
|
||||
|
||||
/**
|
||||
* Returns the state of the popup:
|
||||
* closed - the popup is closed
|
||||
|
@ -109,6 +109,22 @@ PopupBoxObject::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos,
|
||||
pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
|
||||
}
|
||||
|
||||
void
|
||||
PopupBoxObject::OpenPopupAtScreenRect(const nsAString& aPosition,
|
||||
int32_t aXPos, int32_t aYPos,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
bool aIsContextMenu,
|
||||
bool aAttributesOverride,
|
||||
Event* aTriggerEvent)
|
||||
{
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && mContent) {
|
||||
pm->ShowPopupAtScreenRect(mContent, aPosition,
|
||||
nsIntRect(aXPos, aYPos, aWidth, aHeight),
|
||||
aIsContextMenu, aAttributesOverride, aTriggerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PopupBoxObject::MoveTo(int32_t aLeft, int32_t aTop)
|
||||
{
|
||||
|
@ -75,6 +75,13 @@ public:
|
||||
bool aIsContextMenu,
|
||||
Event* aTriggerEvent);
|
||||
|
||||
void OpenPopupAtScreenRect(const nsAString& aPosition,
|
||||
int32_t aXPos, int32_t aYPos,
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
bool aIsContextMenu,
|
||||
bool aAttributesOverride,
|
||||
Event* aTriggerEvent);
|
||||
|
||||
void GetPopupState(nsString& aState);
|
||||
|
||||
nsINode* GetTriggerNode() const;
|
||||
|
@ -105,7 +105,8 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsStyleContext* aContext)
|
||||
mIsMenuLocked(false),
|
||||
mMouseTransparent(false),
|
||||
mHFlip(false),
|
||||
mVFlip(false)
|
||||
mVFlip(false),
|
||||
mAnchorType(MenuPopupAnchorType_Node)
|
||||
{
|
||||
// the preference name is backwards here. True means that the 'top' level is
|
||||
// the default, and false means that the 'parent' level is the default.
|
||||
@ -621,6 +622,7 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
|
||||
nsIContent* aTriggerContent,
|
||||
const nsAString& aPosition,
|
||||
int32_t aXPos, int32_t aYPos,
|
||||
MenuPopupAnchorType aAnchorType,
|
||||
bool aAttributesOverride)
|
||||
{
|
||||
EnsureWidget();
|
||||
@ -635,10 +637,12 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
|
||||
mHFlip = false;
|
||||
mAlignmentOffset = 0;
|
||||
|
||||
mAnchorType = aAnchorType;
|
||||
|
||||
// if aAttributesOverride is true, then the popupanchor, popupalign and
|
||||
// position attributes on the <popup> override those values passed in.
|
||||
// If false, those attributes are only used if the values passed in are empty
|
||||
if (aAnchorContent) {
|
||||
if (aAnchorContent || aAnchorType == MenuPopupAnchorType_Rect) {
|
||||
nsAutoString anchor, align, position, flip;
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::popupanchor, anchor);
|
||||
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::popupalign, align);
|
||||
@ -730,8 +734,7 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
|
||||
}
|
||||
}
|
||||
|
||||
mScreenXPos = -1;
|
||||
mScreenYPos = -1;
|
||||
mScreenRect = nsIntRect(-1, -1, 0, 0);
|
||||
|
||||
if (aAttributesOverride) {
|
||||
// Use |left| and |top| dimension attributes to position the popup if
|
||||
@ -744,12 +747,12 @@ nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
|
||||
if (!left.IsEmpty()) {
|
||||
int32_t x = left.ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err))
|
||||
mScreenXPos = x;
|
||||
mScreenRect.x = x;
|
||||
}
|
||||
if (!top.IsEmpty()) {
|
||||
int32_t y = top.ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err))
|
||||
mScreenYPos = y;
|
||||
mScreenRect.y = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -764,13 +767,26 @@ nsMenuPopupFrame::InitializePopupAtScreen(nsIContent* aTriggerContent,
|
||||
mPopupState = ePopupShowing;
|
||||
mAnchorContent = nullptr;
|
||||
mTriggerContent = aTriggerContent;
|
||||
mScreenXPos = aXPos;
|
||||
mScreenYPos = aYPos;
|
||||
mScreenRect = nsIntRect(aXPos, aYPos, 0, 0);
|
||||
mXPos = 0;
|
||||
mYPos = 0;
|
||||
mFlip = FlipType_Default;
|
||||
mPopupAnchor = POPUPALIGNMENT_NONE;
|
||||
mPopupAlignment = POPUPALIGNMENT_NONE;
|
||||
mIsContextMenu = aIsContextMenu;
|
||||
mAdjustOffsetForContextMenu = aIsContextMenu;
|
||||
mAnchorType = MenuPopupAnchorType_Point;
|
||||
}
|
||||
|
||||
void
|
||||
nsMenuPopupFrame::InitializePopupAtRect(nsIContent* aTriggerContent,
|
||||
const nsAString& aPosition,
|
||||
const nsIntRect& aRect,
|
||||
bool aAttributesOverride)
|
||||
{
|
||||
InitializePopup(nullptr, aTriggerContent, aPosition, 0, 0,
|
||||
MenuPopupAnchorType_Rect, aAttributesOverride);
|
||||
mScreenRect = aRect;
|
||||
}
|
||||
|
||||
void
|
||||
@ -790,18 +806,18 @@ nsMenuPopupFrame::InitializePopupWithAnchorAlign(nsIContent* aAnchorContent,
|
||||
// but doesn't use both together.
|
||||
if (aXPos == -1 && aYPos == -1) {
|
||||
mAnchorContent = aAnchorContent;
|
||||
mScreenXPos = -1;
|
||||
mScreenYPos = -1;
|
||||
mAnchorType = MenuPopupAnchorType_Node;
|
||||
mScreenRect = nsIntRect(-1, -1, 0, 0);
|
||||
mXPos = 0;
|
||||
mYPos = 0;
|
||||
InitPositionFromAnchorAlign(aAnchor, aAlign);
|
||||
}
|
||||
else {
|
||||
mAnchorContent = nullptr;
|
||||
mAnchorType = MenuPopupAnchorType_Point;
|
||||
mPopupAnchor = POPUPALIGNMENT_NONE;
|
||||
mPopupAlignment = POPUPALIGNMENT_NONE;
|
||||
mScreenXPos = aXPos;
|
||||
mScreenYPos = aYPos;
|
||||
mScreenRect = nsIntRect(aXPos, aYPos, 0, 0);
|
||||
mXPos = aXPos;
|
||||
mYPos = aYPos;
|
||||
}
|
||||
@ -1211,61 +1227,78 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
||||
rootFrame->GetView() == GetView()->GetParent(),
|
||||
"rootFrame's view is not our view's parent???");
|
||||
|
||||
// if the frame is not specified, use the anchor node passed to OpenPopup. If
|
||||
// that wasn't specified either, use the root frame. Note that mAnchorContent
|
||||
// might be a different document so its presshell must be used.
|
||||
if (!aAnchorFrame) {
|
||||
if (mAnchorContent) {
|
||||
aAnchorFrame = mAnchorContent->GetPrimaryFrame();
|
||||
// For anchored popups, the anchor rectangle. For non-anchored popups, the
|
||||
// size will be 0.
|
||||
nsRect anchorRect;
|
||||
|
||||
// Width of the parent, used when aSizedToPopup is true.
|
||||
int32_t parentWidth;
|
||||
|
||||
bool anchored = IsAnchored();
|
||||
if (anchored || aSizedToPopup) {
|
||||
// In order to deal with transforms, we need the root prescontext:
|
||||
nsPresContext* rootPresContext = presContext->GetRootPresContext();
|
||||
|
||||
// If we can't reach a root pres context, don't bother continuing:
|
||||
if (!rootPresContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aAnchorFrame) {
|
||||
aAnchorFrame = rootFrame;
|
||||
if (!aAnchorFrame)
|
||||
return NS_OK;
|
||||
// If anchored to a rectangle, use that rectangle. Otherwise, determine the
|
||||
// rectangle from the anchor.
|
||||
if (mAnchorType == MenuPopupAnchorType_Rect) {
|
||||
anchorRect = ToAppUnits(mScreenRect, presContext->AppUnitsPerCSSPixel());
|
||||
}
|
||||
else {
|
||||
// if the frame is not specified, use the anchor node passed to OpenPopup. If
|
||||
// that wasn't specified either, use the root frame. Note that mAnchorContent
|
||||
// might be a different document so its presshell must be used.
|
||||
if (!aAnchorFrame) {
|
||||
if (mAnchorContent) {
|
||||
aAnchorFrame = mAnchorContent->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
if (!aAnchorFrame) {
|
||||
aAnchorFrame = rootFrame;
|
||||
if (!aAnchorFrame)
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// And then we need its root frame for a reference
|
||||
nsIFrame* referenceFrame = rootPresContext->FrameManager()->GetRootFrame();
|
||||
|
||||
// the dimensions of the anchor
|
||||
nsRect parentRect = aAnchorFrame->GetRectRelativeToSelf();
|
||||
// Relative to the root
|
||||
anchorRect = nsLayoutUtils::TransformFrameRectToAncestor(aAnchorFrame,
|
||||
parentRect,
|
||||
referenceFrame);
|
||||
// Relative to the screen
|
||||
anchorRect.MoveBy(referenceFrame->GetScreenRectInAppUnits().TopLeft());
|
||||
|
||||
// In its own app units
|
||||
anchorRect =
|
||||
anchorRect.ScaleToOtherAppUnitsRoundOut(rootPresContext->AppUnitsPerDevPixel(),
|
||||
presContext->AppUnitsPerDevPixel());
|
||||
}
|
||||
|
||||
// The width is needed when aSizedToPopup is true
|
||||
parentWidth = anchorRect.width;
|
||||
}
|
||||
|
||||
// In order to deal with transforms, we need the root prescontext:
|
||||
nsPresContext* rootPresContext = presContext->GetRootPresContext();
|
||||
|
||||
// If we can't reach a root pres context, don't bother continuing:
|
||||
if (!rootPresContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// And then we need its root frame for a reference
|
||||
nsIFrame* referenceFrame = rootPresContext->FrameManager()->GetRootFrame();
|
||||
|
||||
// the dimensions of the anchor
|
||||
nsRect parentRect = aAnchorFrame->GetRectRelativeToSelf();
|
||||
// Relative to the root
|
||||
parentRect = nsLayoutUtils::TransformFrameRectToAncestor(aAnchorFrame,
|
||||
parentRect,
|
||||
referenceFrame);
|
||||
// Relative to the screen
|
||||
parentRect.MoveBy(referenceFrame->GetScreenRectInAppUnits().TopLeft());
|
||||
// In its own app units
|
||||
parentRect =
|
||||
parentRect.ScaleToOtherAppUnitsRoundOut(rootPresContext->AppUnitsPerDevPixel(),
|
||||
presContext->AppUnitsPerDevPixel());
|
||||
|
||||
// Set the popup's size to the preferred size. Below, this size will be
|
||||
// adjusted to fit on the screen or within the content area. If the anchor
|
||||
// is sized to the popup, use the anchor's width instead of the preferred
|
||||
// width. The preferred size should already be set by the parent frame.
|
||||
NS_ASSERTION(mPrefSize.width >= 0 || mPrefSize.height >= 0,
|
||||
"preferred size of popup not set");
|
||||
mRect.width = aSizedToPopup ? parentRect.width : mPrefSize.width;
|
||||
mRect.width = aSizedToPopup ? parentWidth : mPrefSize.width;
|
||||
mRect.height = mPrefSize.height;
|
||||
|
||||
// the screen position in app units where the popup should appear
|
||||
nsPoint screenPoint;
|
||||
|
||||
// For anchored popups, the anchor rectangle. For non-anchored popups, the
|
||||
// size will be 0.
|
||||
nsRect anchorRect = parentRect;
|
||||
|
||||
// indicators of whether the popup should be flipped or resized.
|
||||
FlipStyle hFlip = FlipStyle_None, vFlip = FlipStyle_None;
|
||||
|
||||
@ -1281,14 +1314,14 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
||||
bool isNoAutoHide = IsNoAutoHide();
|
||||
nsPopupLevel popupLevel = PopupLevel(isNoAutoHide);
|
||||
|
||||
if (IsAnchored()) {
|
||||
if (anchored) {
|
||||
// if we are anchored, there are certain things we don't want to do when
|
||||
// repositioning the popup to fit on the screen, such as end up positioned
|
||||
// over the anchor, for instance a popup appearing over the menu label.
|
||||
// When doing this reposition, we want to move the popup to the side with
|
||||
// the most room. The combination of anchor and alignment dictate if we
|
||||
// readjust above/below or to the left/right.
|
||||
if (mAnchorContent) {
|
||||
if (mAnchorContent || mAnchorType == MenuPopupAnchorType_Rect) {
|
||||
// move the popup according to the anchor and alignment. This will also
|
||||
// tell us which axis the popup is flush against in case we have to move
|
||||
// it around later. The AdjustPositionForAnchorAlign method accounts for
|
||||
@ -1321,18 +1354,20 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
||||
// the window is moved. Popups at the parent level follow the parent
|
||||
// window as it is moved and remained anchored, so we want to maintain the
|
||||
// anchoring instead.
|
||||
if (isNoAutoHide && popupLevel != ePopupLevelParent) {
|
||||
if (isNoAutoHide &&
|
||||
(popupLevel != ePopupLevelParent || mAnchorType == MenuPopupAnchorType_Rect)) {
|
||||
// Account for the margin that will end up being added to the screen coordinate
|
||||
// the next time SetPopupPosition is called.
|
||||
mScreenXPos = presContext->AppUnitsToIntCSSPixels(screenPoint.x - margin.left);
|
||||
mScreenYPos = presContext->AppUnitsToIntCSSPixels(screenPoint.y - margin.top);
|
||||
mAnchorType = MenuPopupAnchorType_Point;
|
||||
mScreenRect.x = presContext->AppUnitsToIntCSSPixels(screenPoint.x - margin.left);
|
||||
mScreenRect.y = presContext->AppUnitsToIntCSSPixels(screenPoint.y - margin.top);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the popup is positioned at a screen coordinate.
|
||||
// first convert the screen position in mScreenXPos and mScreenYPos from
|
||||
// CSS pixels into device pixels, ignoring any zoom as mScreenXPos and
|
||||
// mScreenYPos are unzoomed screen coordinates.
|
||||
// The popup is positioned at a screen coordinate.
|
||||
// First convert the screen position in mScreenRect from CSS pixels into
|
||||
// device pixels, ignoring any zoom as mScreenRect holds unzoomed screen
|
||||
// coordinates.
|
||||
int32_t factor = devContext->AppUnitsPerDevPixelAtUnitFullZoom();
|
||||
|
||||
// context menus should be offset by two pixels so that they don't appear
|
||||
@ -1346,9 +1381,9 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
||||
|
||||
// next, convert into app units accounting for the zoom
|
||||
screenPoint.x = presContext->DevPixelsToAppUnits(
|
||||
nsPresContext::CSSPixelsToAppUnits(mScreenXPos) / factor);
|
||||
nsPresContext::CSSPixelsToAppUnits(mScreenRect.x) / factor);
|
||||
screenPoint.y = presContext->DevPixelsToAppUnits(
|
||||
nsPresContext::CSSPixelsToAppUnits(mScreenYPos) / factor);
|
||||
nsPresContext::CSSPixelsToAppUnits(mScreenRect.y) / factor);
|
||||
anchorRect = nsRect(screenPoint, nsSize(0, 0));
|
||||
|
||||
// add the margins on the popup
|
||||
@ -1448,7 +1483,7 @@ nsMenuPopupFrame::SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aS
|
||||
if (aSizedToPopup) {
|
||||
nsBoxLayoutState state(PresContext());
|
||||
// XXXndeakin can parentSize.width still extend outside?
|
||||
SetBounds(state, nsRect(mRect.x, mRect.y, parentRect.width, mRect.height));
|
||||
SetBounds(state, nsRect(mRect.x, mRect.y, parentWidth, mRect.height));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2081,7 +2116,7 @@ void
|
||||
nsMenuPopupFrame::MoveTo(int32_t aLeft, int32_t aTop, bool aUpdateAttrs)
|
||||
{
|
||||
nsIWidget* widget = GetWidget();
|
||||
if ((mScreenXPos == aLeft && mScreenYPos == aTop) &&
|
||||
if ((mScreenRect.x == aLeft && mScreenRect.y == aTop) &&
|
||||
(!widget || widget->GetClientOffset() == mLastClientOffset)) {
|
||||
return;
|
||||
}
|
||||
@ -2102,8 +2137,10 @@ nsMenuPopupFrame::MoveTo(int32_t aLeft, int32_t aTop, bool aUpdateAttrs)
|
||||
}
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
mScreenXPos = aLeft - presContext->AppUnitsToIntCSSPixels(margin.left);
|
||||
mScreenYPos = aTop - presContext->AppUnitsToIntCSSPixels(margin.top);
|
||||
mAnchorType = aLeft == -1 || aTop == -1 ?
|
||||
MenuPopupAnchorType_Node : MenuPopupAnchorType_Point;
|
||||
mScreenRect.x = aLeft - presContext->AppUnitsToIntCSSPixels(margin.left);
|
||||
mScreenRect.y = aTop - presContext->AppUnitsToIntCSSPixels(margin.top);
|
||||
|
||||
SetPopupPosition(nullptr, true, false);
|
||||
|
||||
@ -2129,7 +2166,7 @@ nsMenuPopupFrame::MoveToAnchor(nsIContent* aAnchorContent,
|
||||
|
||||
nsPopupState oldstate = mPopupState;
|
||||
InitializePopup(aAnchorContent, mTriggerContent, aPosition,
|
||||
aXPos, aYPos, aAttributesOverride);
|
||||
aXPos, aYPos, MenuPopupAnchorType_Node, aAttributesOverride);
|
||||
// InitializePopup changed the state so reset it.
|
||||
mPopupState = oldstate;
|
||||
|
||||
|
@ -86,6 +86,12 @@ enum FlipType {
|
||||
FlipType_Slide = 3 // allow the arrow to "slide" instead of resizing
|
||||
};
|
||||
|
||||
enum MenuPopupAnchorType {
|
||||
MenuPopupAnchorType_Node = 0, // anchored to a node
|
||||
MenuPopupAnchorType_Point = 1, // unanchored and positioned at a screen point
|
||||
MenuPopupAnchorType_Rect = 2, // anchored at a screen rectangle
|
||||
};
|
||||
|
||||
// values are selected so that the direction can be flipped just by
|
||||
// changing the sign
|
||||
#define POPUPALIGNMENT_NONE 0
|
||||
@ -242,11 +248,11 @@ public:
|
||||
|
||||
nsView* GetRootViewForPopup(nsIFrame* aStartFrame);
|
||||
|
||||
// set the position of the popup either relative to the anchor aAnchorFrame
|
||||
// (or the frame for mAnchorContent if aAnchorFrame is null) or at a specific
|
||||
// point if a screen position (mScreenXPos and mScreenYPos) are set. The popup
|
||||
// will be adjusted so that it is on screen. If aIsMove is true, then the popup
|
||||
// is being moved, and should not be flipped.
|
||||
// Set the position of the popup either relative to the anchor aAnchorFrame
|
||||
// (or the frame for mAnchorContent if aAnchorFrame is null), anchored at a
|
||||
// rectangle, or at a specific point if a screen position is set. The popup
|
||||
// will be adjusted so that it is on screen. If aIsMove is true, then the
|
||||
// popup is being moved, and should not be flipped.
|
||||
nsresult SetPopupPosition(nsIFrame* aAnchorFrame, bool aIsMove, bool aSizedToPopup);
|
||||
|
||||
bool HasGeneratedChildren() { return mGeneratedChildren; }
|
||||
@ -283,8 +289,14 @@ public:
|
||||
nsIContent* aTriggerContent,
|
||||
const nsAString& aPosition,
|
||||
int32_t aXPos, int32_t aYPos,
|
||||
MenuPopupAnchorType aAnchorType,
|
||||
bool aAttributesOverride);
|
||||
|
||||
void InitializePopupAtRect(nsIContent* aTriggerContent,
|
||||
const nsAString& aPosition,
|
||||
const nsIntRect& aRect,
|
||||
bool aAttributesOverride);
|
||||
|
||||
/**
|
||||
* @param aIsContextMenu if true, then the popup is
|
||||
* positioned at a slight offset from aXPos/aYPos to ensure the
|
||||
@ -371,14 +383,14 @@ public:
|
||||
mozilla::LayoutDeviceIntPoint& aChange);
|
||||
|
||||
// Return true if the popup is positioned relative to an anchor.
|
||||
bool IsAnchored() const { return mScreenXPos == -1 && mScreenYPos == -1; }
|
||||
bool IsAnchored() const { return mAnchorType != MenuPopupAnchorType_Point; }
|
||||
|
||||
// Return the anchor if there is one.
|
||||
nsIContent* GetAnchor() const { return mAnchorContent; }
|
||||
|
||||
// Return the screen coordinates of the popup, or (-1, -1) if anchored.
|
||||
// This position is in CSS pixels.
|
||||
nsIntPoint ScreenPosition() const { return nsIntPoint(mScreenXPos, mScreenYPos); }
|
||||
nsIntPoint ScreenPosition() const { return mScreenRect.TopLeft(); }
|
||||
|
||||
nsIntPoint GetLastClientOffset() const { return mLastClientOffset; }
|
||||
|
||||
@ -507,8 +519,7 @@ protected:
|
||||
// override mXPos and mYPos.
|
||||
int32_t mXPos;
|
||||
int32_t mYPos;
|
||||
int32_t mScreenXPos;
|
||||
int32_t mScreenYPos;
|
||||
nsIntRect mScreenRect;
|
||||
|
||||
// If the panel prefers to "slide" rather than resize, then the arrow gets
|
||||
// positioned at this offset (along either the x or y axis, depending on
|
||||
@ -570,6 +581,9 @@ protected:
|
||||
bool mHFlip;
|
||||
bool mVFlip;
|
||||
|
||||
// How the popup is anchored.
|
||||
MenuPopupAnchorType mAnchorType;
|
||||
|
||||
static int8_t sDefaultLevelIsTop;
|
||||
|
||||
// If 0, never timed out. Otherwise, the value is in milliseconds.
|
||||
|
@ -672,7 +672,8 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu,
|
||||
|
||||
// there is no trigger event for menus
|
||||
InitTriggerEvent(nullptr, nullptr, nullptr);
|
||||
popupFrame->InitializePopup(menuFrame->GetAnchor(), nullptr, position, 0, 0, true);
|
||||
popupFrame->InitializePopup(menuFrame->GetAnchor(), nullptr, position, 0, 0,
|
||||
MenuPopupAnchorType_Node, true);
|
||||
|
||||
if (aAsynchronous) {
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
@ -704,7 +705,7 @@ nsXULPopupManager::ShowPopup(nsIContent* aPopup,
|
||||
InitTriggerEvent(aTriggerEvent, aPopup, getter_AddRefs(triggerContent));
|
||||
|
||||
popupFrame->InitializePopup(aAnchorContent, triggerContent, aPosition,
|
||||
aXPos, aYPos, aAttributesOverride);
|
||||
aXPos, aYPos, MenuPopupAnchorType_Node, aAttributesOverride);
|
||||
|
||||
FirePopupShowingEvent(aPopup, aIsContextMenu, aSelectFirstItem);
|
||||
}
|
||||
@ -726,6 +727,27 @@ nsXULPopupManager::ShowPopupAtScreen(nsIContent* aPopup,
|
||||
FirePopupShowingEvent(aPopup, aIsContextMenu, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULPopupManager::ShowPopupAtScreenRect(nsIContent* aPopup,
|
||||
const nsAString& aPosition,
|
||||
const nsIntRect& aRect,
|
||||
bool aIsContextMenu,
|
||||
bool aAttributesOverride,
|
||||
nsIDOMEvent* aTriggerEvent)
|
||||
{
|
||||
nsMenuPopupFrame* popupFrame = GetPopupFrameForContent(aPopup, true);
|
||||
if (!popupFrame || !MayShowPopup(popupFrame))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIContent> triggerContent;
|
||||
InitTriggerEvent(aTriggerEvent, aPopup, getter_AddRefs(triggerContent));
|
||||
|
||||
popupFrame->InitializePopupAtRect(triggerContent, aPosition,
|
||||
aRect, aAttributesOverride);
|
||||
|
||||
FirePopupShowingEvent(aPopup, aIsContextMenu, false);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULPopupManager::ShowTooltipAtScreen(nsIContent* aPopup,
|
||||
nsIContent* aTriggerContent,
|
||||
|
@ -405,6 +405,16 @@ public:
|
||||
bool aIsContextMenu,
|
||||
nsIDOMEvent* aTriggerEvent);
|
||||
|
||||
/* Open a popup anchored at a screen rectangle specified by aRect.
|
||||
* The remaining arguments are similar to ShowPopup.
|
||||
*/
|
||||
void ShowPopupAtScreenRect(nsIContent* aPopup,
|
||||
const nsAString& aPosition,
|
||||
const nsIntRect& aRect,
|
||||
bool aIsContextMenu,
|
||||
bool aAttributesOverride,
|
||||
nsIDOMEvent* aTriggerEvent);
|
||||
|
||||
/**
|
||||
* Open a tooltip at a specific screen position specified by aXPos and aYPos,
|
||||
* measured in CSS pixels.
|
||||
|
@ -69,7 +69,28 @@
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="openPopupAtScreenRect">
|
||||
<parameter name="aPosition"/>
|
||||
<parameter name="aX"/>
|
||||
<parameter name="aY"/>
|
||||
<parameter name="aWidth"/>
|
||||
<parameter name="aHeight"/>
|
||||
<parameter name="aIsContextMenu"/>
|
||||
<parameter name="aAttributesOverride"/>
|
||||
<parameter name="aTriggerEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
try {
|
||||
var popupBox = this.popupBoxObject;
|
||||
if (popupBox)
|
||||
popupBox.openPopupAtScreenRect(aPosition, aX, aY, aWidth, aHeight,
|
||||
aIsContextMenu, aAttributesOverride, aTriggerEvent);
|
||||
} catch(e) {}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showPopup">
|
||||
<parameter name="element"/>
|
||||
<parameter name="xpos"/>
|
||||
@ -94,7 +115,7 @@
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
|
||||
<method name="hidePopup">
|
||||
<parameter name="cancel"/>
|
||||
<body>
|
||||
|
Loading…
x
Reference in New Issue
Block a user