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. // Return the anchor if there is one.
nsIContent* GetAnchor() const { return mAnchorContent; } nsIContent* GetAnchor() const { return mAnchorContent; }
// Return the screen coordinates of the popup, or (-1, -1) if anchored. // Return the screen coordinates in CSS pixels of the popup,
// This position is in CSS pixels. // or (-1, -1, 0, 0) if anchored.
nsIntPoint ScreenPosition() const { return mScreenRect.TopLeft(); } nsIntRect GetScreenAnchorRect() const { return mScreenRect; }
nsIntPoint GetLastClientOffset() const { return mLastClientOffset; } 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 // when the click was over the anchor. This way, clicking on a menu doesn't
// reopen the menu. // reopen the menu.
if ((consumeResult == ConsumeOutsideClicks_ParentOnly || noRollupOnAnchor) && pos) { 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 // 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 // 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 // an individual icon, while clicking elsewhere within a button or other
// container doesn't result in us re-opening the popup. // container doesn't result in us re-opening the popup.
if (anchor) { if (anchor) {
nsAutoString consumeAnchor; nsAutoString consumeAnchor;
anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor, anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor,
consumeAnchor); consumeAnchor);
if (!consumeAnchor.IsEmpty()) { if (!consumeAnchor.IsEmpty()) {
nsIDocument* doc = anchor->GetOwnerDocument(); nsIDocument* doc = anchor->GetOwnerDocument();
nsIContent* newAnchor = doc->GetElementById(consumeAnchor); nsIContent* newAnchor = doc->GetElementById(consumeAnchor);
if (newAnchor) { if (newAnchor) {
anchor = 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
// 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
// position, but the only thing that would happen is that the mouse // event will get consumed, so here only a quick coordinates check is
// 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.
// done rather than a slower complete check of what is at that location. if (anchorRect.Contains(*pos)) {
if (anchor->GetPrimaryFrame()->GetScreenRect().Contains(*pos)) { if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
if (consumeResult == ConsumeOutsideClicks_ParentOnly) { consume = true;
consume = true; }
}
if (noRollupOnAnchor) { if (noRollupOnAnchor) {
rollup = false; rollup = false;
}
} }
} }
} }