Bug 1182607, use the right rectangle for a popup anchored at a rectangle when determining if the mouse click was over the anchor, r=tn

This commit is contained in:
Neil Deakin 2015-07-20 08:59:50 -04:00
parent 47ff74eac6
commit 79233aaef4
2 changed files with 40 additions and 29 deletions

View File

@ -390,9 +390,9 @@ public:
// 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 mScreenRect.TopLeft(); }
// Return the screen coordinates in CSS pixels of the popup,
// or (-1, -1, 0, 0) if anchored.
nsIntRect GetScreenAnchorRect() const { return mScreenRect; }
nsIntPoint GetLastClientOffset() const { return mLastClientOffset; }

View File

@ -227,38 +227,49 @@ nsXULPopupManager::Rollup(uint32_t aCount, bool aFlush,
// when the click was over the anchor. This way, clicking on a menu doesn't
// reopen the menu.
if ((consumeResult == ConsumeOutsideClicks_ParentOnly || noRollupOnAnchor) && pos) {
nsCOMPtr<nsIContent> anchor = item->Frame()->GetAnchor();
nsMenuPopupFrame* popupFrame = item->Frame();
nsIntRect anchorRect;
if (popupFrame->IsAnchored()) {
// Check if the popup has a screen anchor rectangle. If not, get the rectangle
// from the anchor element.
anchorRect = popupFrame->GetScreenAnchorRect();
if (anchorRect.x == -1 || anchorRect.y == -1) {
nsCOMPtr<nsIContent> anchor = popupFrame->GetAnchor();
// Check if the anchor has indicated another node to use for checking
// for roll-up. That way, we can anchor a popup on anonymous content or
// an individual icon, while clicking elsewhere within a button or other
// container doesn't result in us re-opening the popup.
if (anchor) {
nsAutoString consumeAnchor;
anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor,
consumeAnchor);
if (!consumeAnchor.IsEmpty()) {
nsIDocument* doc = anchor->GetOwnerDocument();
nsIContent* newAnchor = doc->GetElementById(consumeAnchor);
if (newAnchor) {
anchor = newAnchor;
// Check if the anchor has indicated another node to use for checking
// for roll-up. That way, we can anchor a popup on anonymous content or
// an individual icon, while clicking elsewhere within a button or other
// container doesn't result in us re-opening the popup.
if (anchor) {
nsAutoString consumeAnchor;
anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor,
consumeAnchor);
if (!consumeAnchor.IsEmpty()) {
nsIDocument* doc = anchor->GetOwnerDocument();
nsIContent* newAnchor = doc->GetElementById(consumeAnchor);
if (newAnchor) {
anchor = newAnchor;
}
}
}
if (anchor && anchor->GetPrimaryFrame()) {
anchorRect = anchor->GetPrimaryFrame()->GetScreenRect();
}
}
}
if (anchor && anchor->GetPrimaryFrame()) {
// It's possible that some other element is above the anchor at the same
// position, but the only thing that would happen is that the mouse
// event will get consumed, so here only a quick coordinates check is
// done rather than a slower complete check of what is at that location.
if (anchor->GetPrimaryFrame()->GetScreenRect().Contains(*pos)) {
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
consume = true;
}
// It's possible that some other element is above the anchor at the same
// position, but the only thing that would happen is that the mouse
// event will get consumed, so here only a quick coordinates check is
// done rather than a slower complete check of what is at that location.
if (anchorRect.Contains(*pos)) {
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
consume = true;
}
if (noRollupOnAnchor) {
rollup = false;
}
if (noRollupOnAnchor) {
rollup = false;
}
}
}