Bug 1328030 - Improve selecting content that contains elements with anonymous content (form controls etc). r=smaug

Two changes:
In nsIFrame::GetFrameFromDirection, detect frames that are in
a different anonynous content tree than 'this' and then just keep
traversing frames until we get one that isn't.

In nsFrame::GetLastLeaf: the old code did allow the first child frame
to be IsRootOfNativeAnonymousSubtree (it just checked siblings).
I think this was unintentional and that we should check the first
child too (and return its parent in that case, i.e. never return
something that is IsRootOfNativeAnonymousSubtree here).
This commit is contained in:
Mats Palmgren 2017-01-11 16:57:27 +01:00
parent ccfe5b9092
commit 47b455e007

View File

@ -8315,12 +8315,27 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual,
if (NS_FAILED(result))
return result;
if (aDirection == eDirNext)
frameTraversal->Next();
else
frameTraversal->Prev();
auto Advance = [&frameTraversal, aDirection] () {
if (aDirection == eDirNext) {
frameTraversal->Next();
} else {
frameTraversal->Prev();
}
return frameTraversal->CurrentItem();
};
traversedFrame = frameTraversal->CurrentItem();
traversedFrame = Advance();
if (nsIContent* content = GetContent()) {
// Advance until the frame is inside the same tree as 'this'.
for (nsIContent* traversedContent;
traversedFrame &&
!traversedFrame->IsGeneratedContentFrame() &&
(traversedContent = traversedFrame->GetContent()) &&
!nsContentUtils::IsInSameAnonymousTree(content, traversedContent);) {
traversedFrame = Advance();
}
}
// Skip anonymous elements, but watch out for generated content
if (!traversedFrame ||
@ -9177,23 +9192,31 @@ nsFrame::DoGetParentStyleContext(nsIFrame** aProviderFrame) const
void
nsFrame::GetLastLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
{
if (!aFrame || !*aFrame)
if (!aFrame || !*aFrame) {
return;
nsIFrame *child = *aFrame;
//if we are a block frame then go for the last line of 'this'
while (1){
}
nsIFrame* child = *aFrame;
while (true) {
child = child->PrincipalChildList().FirstChild();
if (!child)
return;//nothing to do
nsIFrame* siblingFrame;
nsIContent* content;
//ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
//see bug 278197 comment #12 #13 for details
while ((siblingFrame = child->GetNextSibling()) &&
(content = siblingFrame->GetContent()) &&
!content->IsRootOfNativeAnonymousSubtree())
child = siblingFrame;
*aFrame = child;
if (!child) {
return; // done
}
// Ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
// see bug 278197 comment #12 #13 for details.
nsIFrame* nonAnonymousChild = nullptr;
const nsIContent* content;
while (child &&
(content = child->GetContent()) &&
!content->IsRootOfNativeAnonymousSubtree()) {
nonAnonymousChild = child;
child = child->GetNextSibling();
}
if (!nonAnonymousChild) {
return;
}
*aFrame = child = nonAnonymousChild;
}
}