Bug 1188185 - Zoomed View appears when the two links are the same link. r=kats

This commit is contained in:
dominique vincent 2015-07-31 15:22:46 +02:00
parent df305143e3
commit 30f7490d25

View File

@ -34,7 +34,7 @@ namespace mozilla {
* designing for touch events will take their own steps to account for
* inaccurate touch events.
*
* IsElementClickable() encapsulates the heuristic that determines whether an
* GetClickableAncestor() encapsulates the heuristic that determines whether an
* element is expected to respond to mouse events. An element is deemed
* "clickable" if it has registered listeners for "click", "mousedown" or
* "mouseup", or is on a whitelist of element tags (<a>, <button>, <input>,
@ -48,7 +48,7 @@ namespace mozilla {
* event radii are disabled), we always use that element. Otherwise we collect
* all frames intersecting a rectangle around the event position (taking CSS
* transforms into account) and choose the best candidate in GetClosest().
* Only IsElementClickable() candidates are considered; if none are found,
* Only GetClickableAncestor() candidates are considered; if none are found,
* then we revert to targeting the element under the event position.
* We ignore candidates outside the document subtree rooted by the
* document of the element directly under the event position. This ensures that
@ -187,8 +187,8 @@ IsDescendant(nsIFrame* aFrame, nsIContent* aAncestor, nsAutoString* aLabelTarget
return false;
}
static bool
IsElementClickable(nsIFrame* aFrame, nsIAtom* stopAt = nullptr, nsAutoString* aLabelTargetId = nullptr)
static nsIContent*
GetClickableAncestor(nsIFrame* aFrame, nsIAtom* stopAt = nullptr, nsAutoString* aLabelTargetId = nullptr)
{
// Input events propagate up the content tree so we'll follow the content
// ancestors to look for elements accepting the click.
@ -198,19 +198,19 @@ IsElementClickable(nsIFrame* aFrame, nsIAtom* stopAt = nullptr, nsAutoString* aL
break;
}
if (HasTouchListener(content) || HasMouseListener(content)) {
return true;
return content;
}
if (content->IsAnyOfHTMLElements(nsGkAtoms::button,
nsGkAtoms::input,
nsGkAtoms::select,
nsGkAtoms::textarea)) {
return true;
return content;
}
if (content->IsHTMLElement(nsGkAtoms::label)) {
if (aLabelTargetId) {
content->GetAttr(kNameSpaceID_None, nsGkAtoms::_for, *aLabelTargetId);
}
return true;
return content;
}
// Bug 921928: we don't have access to the content of remote iframe.
@ -221,7 +221,7 @@ IsElementClickable(nsIFrame* aFrame, nsIAtom* stopAt = nullptr, nsAutoString* aL
nsGkAtoms::_true, eIgnoreCase) &&
content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
nsGkAtoms::_true, eIgnoreCase)) {
return true;
return content;
}
// See nsCSSFrameConstructor::FindXULTagData. This code is not
@ -236,24 +236,24 @@ IsElementClickable(nsIFrame* aFrame, nsIAtom* stopAt = nullptr, nsAutoString* aL
nsGkAtoms::menulist,
nsGkAtoms::scrollbarbutton,
nsGkAtoms::resizer)) {
return true;
return content;
}
static nsIContent::AttrValuesArray clickableRoles[] =
{ &nsGkAtoms::button, &nsGkAtoms::key, nullptr };
if (content->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::role,
clickableRoles, eIgnoreCase) >= 0) {
return true;
return content;
}
if (content->IsEditable()) {
return true;
return content;
}
nsCOMPtr<nsIURI> linkURI;
if (content->IsLink(getter_AddRefs(linkURI))) {
return true;
return content;
}
}
return false;
return nullptr;
}
static nscoord
@ -362,6 +362,7 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
nsIFrame* aRestrictToDescendants, nsIContent* aClickableAncestor,
nsTArray<nsIFrame*>& aCandidates, int32_t* aElementsInCluster)
{
std::vector<nsIContent*> mContentsInCluster; // List of content elements in the cluster without duplicate
nsIFrame* bestTarget = nullptr;
// Lower is better; distance is in appunits
float bestDistance = 1e6f;
@ -375,7 +376,6 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
nsRegion region;
region.And(exposedRegion, borderBox);
if (region.IsEmpty()) {
PET_LOG(" candidate %p had empty hit region\n", f);
continue;
@ -388,12 +388,13 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
}
nsAutoString labelTargetId;
if (aClickableAncestor) {
if (!IsDescendant(f, aClickableAncestor, &labelTargetId)) {
PET_LOG(" candidate %p is not a descendant of required ancestor\n", f);
continue;
}
} else if (!IsElementClickable(f, nsGkAtoms::body, &labelTargetId)) {
if (aClickableAncestor && !IsDescendant(f, aClickableAncestor, &labelTargetId)) {
PET_LOG(" candidate %p is not a descendant of required ancestor\n", f);
continue;
}
nsIContent* clickableContent = GetClickableAncestor(f, nsGkAtoms::body, &labelTargetId);
if (!aClickableAncestor && !clickableContent) {
PET_LOG(" candidate %p was not clickable\n", f);
continue;
}
@ -403,7 +404,7 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
PET_LOG(" candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
continue;
}
if (!nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
if (!aClickableAncestor && !nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
PET_LOG(" candidate %p was not descendant of restrictroot %p\n", f, aRestrictToDescendants);
continue;
}
@ -413,7 +414,9 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
// If this element is present in the current list, do not count the frame in
// the cluster elements counter
if (labelTargetId.IsEmpty() || !IsElementPresent(aCandidates, labelTargetId)) {
(*aElementsInCluster)++;
if (std::find(mContentsInCluster.begin(), mContentsInCluster.end(), clickableContent) == mContentsInCluster.end()) {
mContentsInCluster.push_back(clickableContent);
}
}
// distance is in appunits
@ -430,6 +433,7 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
bestTarget = f;
}
}
*aElementsInCluster = mContentsInCluster.size();
return bestTarget;
}
@ -524,12 +528,14 @@ FindFrameTargetedByInputEvent(WidgetGUIEvent* aEvent,
return target;
}
nsIContent* clickableAncestor = nullptr;
if (target && IsElementClickable(target, nsGkAtoms::body)) {
if (!IsElementClickableAndReadable(target, aEvent, prefs)) {
aEvent->AsMouseEventBase()->hitCluster = true;
if (target) {
clickableAncestor = GetClickableAncestor(target, nsGkAtoms::body);
if (clickableAncestor) {
if (!IsElementClickableAndReadable(target, aEvent, prefs)) {
aEvent->AsMouseEventBase()->hitCluster = true;
}
PET_LOG("Target %p is clickable\n", target);
}
PET_LOG("Target %p is clickable\n", target);
clickableAncestor = target->GetContent();
}
// Do not modify targeting for actual mouse hardware; only for mouse
@ -544,7 +550,7 @@ FindFrameTargetedByInputEvent(WidgetGUIEvent* aEvent,
// If the exact target is non-null, only consider candidate targets in the same
// document as the exact target. Otherwise, if an ancestor document has
// a mouse event handler for example, targets that are !IsElementClickable can
// a mouse event handler for example, targets that are !GetClickableAncestor can
// never be targeted --- something nsSubDocumentFrame in an ancestor document
// would be targeted instead.
nsIFrame* restrictToDescendants = target ?