Backout bug 779684 for topcrash

This commit is contained in:
David Zbarsky 2012-10-15 14:35:50 -04:00
parent 45f6f3a578
commit e1da975f5f
12 changed files with 463 additions and 206 deletions

View File

@ -65,6 +65,7 @@
#include "nsCaret.h"
#include "nsSubDocumentFrame.h"
#include "nsIFrameTraversal.h"
#include "nsLayoutCID.h"
#include "nsLayoutUtils.h"
#include "nsIInterfaceRequestorUtils.h"
@ -113,6 +114,8 @@ using namespace mozilla::dom;
static const nsIntPoint kInvalidRefPoint = nsIntPoint(-1,-1);
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
static bool sLeftClickOnly = true;
static bool sKeyCausesActivation = true;
static uint32_t sESMInstanceCount = 0;

View File

@ -31,7 +31,7 @@
#include "nsLayoutUtils.h"
#include "nsIPresShell.h"
#include "nsIContentViewer.h"
#include "nsFrameIterator.h"
#include "nsFrameTraversal.h"
#include "nsObjectFrame.h"
#include "nsEventDispatcher.h"
#include "nsEventStateManager.h"
@ -2270,8 +2270,15 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
if (nodeValue.Length() == (uint32_t)startOffset && !isFormControl &&
startContent != aDocument->GetRootElement()) {
// Yes, indeed we were at the end of the last node
nsFrameIterator frameTraversal(presContext, startFrame,
eLeaf, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
presContext, startFrame,
eLeaf,
false, // aVisual
false, // aLockInScrollView
true // aFollowOOFs
);
NS_ENSURE_SUCCESS(rv, rv);
nsIFrame *newCaretFrame = nullptr;
nsCOMPtr<nsIContent> newCaretContent = startContent;
@ -2279,8 +2286,8 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
do {
// Continue getting the next frame until the primary content for the frame
// we are on changes - we don't want to be stuck in the same place
frameTraversal.Next();
newCaretFrame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
frameTraversal->Next();
newCaretFrame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
if (nullptr == newCaretFrame)
break;
newCaretContent = newCaretFrame->GetContent();
@ -2696,14 +2703,21 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
continue;
}
nsFrameIterator frameTraversal(presContext, startFrame,
ePreOrder, nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
presContext, startFrame,
ePreOrder,
false, // aVisual
false, // aLockInScrollView
true // aFollowOOFs
);
NS_ENSURE_SUCCESS(rv, rv);
if (iterStartContent == aRootContent) {
if (!aForward) {
frameTraversal.Last();
frameTraversal->Last();
} else if (aRootContent->IsFocusable()) {
frameTraversal.Next();
frameTraversal->Next();
}
}
else if (getNextFrame &&
@ -2712,13 +2726,13 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
// Need to do special check in case we're in an imagemap which has multiple
// content nodes per frame, so don't skip over the starting frame.
if (aForward)
frameTraversal.Next();
frameTraversal->Next();
else
frameTraversal.Prev();
frameTraversal->Prev();
}
// Walk frames to find something tabbable matching mCurrentTabIndex
nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
while (frame) {
// TabIndex not set defaults to 0 for form elements, anchors and other
// elements that are normally focusable. Tabindex defaults to -1
@ -2788,10 +2802,10 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
Element* rootElement = subdoc->GetRootElement();
nsIPresShell* subShell = subdoc->GetShell();
if (rootElement && subShell) {
nsresult rv = GetNextTabbableContent(subShell, rootElement,
aOriginalStartContent, rootElement,
aForward, (aForward ? 1 : 0),
false, aResultContent);
rv = GetNextTabbableContent(subShell, rootElement,
aOriginalStartContent, rootElement,
aForward, (aForward ? 1 : 0),
false, aResultContent);
NS_ENSURE_SUCCESS(rv, rv);
if (*aResultContent)
return NS_OK;
@ -2835,10 +2849,10 @@ nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
// again.
do {
if (aForward)
frameTraversal.Next();
frameTraversal->Next();
else
frameTraversal.Prev();
frame = static_cast<nsIFrame*>(frameTraversal.CurrentItem());
frameTraversal->Prev();
frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
} while (frame && frame->GetPrevContinuation());
}

View File

@ -43,7 +43,8 @@ EXPORTS = \
nsDisplayListInvalidation.h \
nsFrameManager.h \
nsFrameManagerBase.h \
nsFrameIterator.h \
nsFrameTraversal.h \
nsIFrameTraversal.h \
nsILayoutDebugger.h \
nsILayoutHistoryState.h \
nsIPercentHeightObserver.h \
@ -79,7 +80,7 @@ CPPSRCS = \
nsDisplayListInvalidation.cpp \
nsDocumentViewer.cpp \
nsFrameManager.cpp \
nsFrameIterator.cpp \
nsFrameTraversal.cpp \
nsGenConList.cpp \
nsLayoutDebugger.cpp \
nsLayoutHistoryState.cpp \

View File

@ -1,107 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef NSFRAMEITERATOR_H
#define NSFRAMEITERATOR_H
#include "mozilla/StandardInteger.h"
class nsPresContext;
class nsIFrame;
enum nsIteratorType {
eLeaf,
ePreOrder,
ePostOrder
};
class nsFrameIterator
{
public:
nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, uint32_t aFlags);
~nsFrameIterator() {}
void First();
void Next();
nsIFrame* CurrentItem();
bool IsDone();
void Last();
void Prev();
enum FrameIteratorFlags {
FLAG_NONE = 0,
FLAG_LOCK_SCROLL = 1 << 1,
FLAG_FOLLOW_OUT_OF_FLOW = 1 << 2,
FLAG_VISUAL = 1 << 3
};
protected:
void setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
nsIFrame *getCurrent(){return mCurrent;}
void setStart(nsIFrame *aFrame){mStart = aFrame;}
nsIFrame *getStart(){return mStart;}
nsIFrame *getLast(){return mLast;}
void setLast(nsIFrame *aFrame){mLast = aFrame;}
int8_t getOffEdge(){return mOffEdge;}
void setOffEdge(int8_t aOffEdge){mOffEdge = aOffEdge;}
void SetLockInScrollView(bool aLockScroll){mLockScroll = aLockScroll;}
/*
Our own versions of the standard frame tree navigation
methods, which, if the iterator is following out-of-flows,
apply the following rules for placeholder frames:
- If a frame HAS a placeholder frame, getting its parent
gets the placeholder's parent.
- If a frame's first child or next/prev sibling IS a
placeholder frame, then we instead return the real frame.
- If a frame HAS a placeholder frame, getting its next/prev
sibling gets the placeholder frame's next/prev sibling.
These are all applied recursively to support multiple levels of
placeholders.
*/
nsIFrame* GetParentFrame(nsIFrame* aFrame);
// like GetParentFrame but returns null once a popup frame is reached
nsIFrame* GetParentFrameNotPopup(nsIFrame* aFrame);
nsIFrame* GetFirstChild(nsIFrame* aFrame);
nsIFrame* GetLastChild(nsIFrame* aFrame);
nsIFrame* GetNextSibling(nsIFrame* aFrame);
nsIFrame* GetPrevSibling(nsIFrame* aFrame);
/*
These methods are different in visual mode to have the
semantics of "get first child in visual order", "get last child in visual
order", "get next sibling in visual order" and "get previous sibling in visual
order".
*/
nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
nsIFrame* GetLastChildInner(nsIFrame* aFrame);
nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);
nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame);
bool IsPopupFrame(nsIFrame* aFrame);
nsPresContext* mPresContext;
nsIFrame *mStart;
nsIFrame *mCurrent;
nsIFrame *mLast; //the last one that was in current;
int8_t mOffEdge; //0= no -1 to far prev, 1 to far next;
nsIteratorType mType;
bool mLockScroll;
bool mFollowOOFs;
bool mVisual;
};
#endif //NSFRAMEITERATOR_H

View File

@ -2,34 +2,215 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsFrameIterator.h"
#include "nsIFrame.h"
#include "nsCOMPtr.h"
#include "nsGkAtoms.h"
#include "nsFrameTraversal.h"
#include "nsFrameList.h"
#include "nsPlaceholderFrame.h"
nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, uint32_t aFlags)
: mPresContext(aPresContext)
, mOffEdge(0)
, mType(aType)
class nsFrameIterator : public nsIFrameEnumerator
{
mFollowOOFs = (aFlags & FLAG_FOLLOW_OUT_OF_FLOW) != 0;
mLockScroll = (aFlags & FLAG_LOCK_SCROLL) != 0;
mVisual = (aFlags & FLAG_VISUAL) != 0;
if (mFollowOOFs && aStart)
public:
typedef nsIFrame::ChildListID ChildListID;
NS_DECL_ISUPPORTS
virtual ~nsFrameIterator() {}
virtual void First();
virtual void Next();
virtual nsIFrame* CurrentItem();
virtual bool IsDone();
virtual void Last();
virtual void Prev();
nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockScroll, bool aFollowOOFs);
protected:
void setCurrent(nsIFrame *aFrame){mCurrent = aFrame;}
nsIFrame *getCurrent(){return mCurrent;}
void setStart(nsIFrame *aFrame){mStart = aFrame;}
nsIFrame *getStart(){return mStart;}
nsIFrame *getLast(){return mLast;}
void setLast(nsIFrame *aFrame){mLast = aFrame;}
PRInt8 getOffEdge(){return mOffEdge;}
void setOffEdge(PRInt8 aOffEdge){mOffEdge = aOffEdge;}
void SetLockInScrollView(bool aLockScroll){mLockScroll = aLockScroll;}
/*
Our own versions of the standard frame tree navigation
methods, which, if the iterator is following out-of-flows,
apply the following rules for placeholder frames:
- If a frame HAS a placeholder frame, getting its parent
gets the placeholder's parent.
- If a frame's first child or next/prev sibling IS a
placeholder frame, then we instead return the real frame.
- If a frame HAS a placeholder frame, getting its next/prev
sibling gets the placeholder frame's next/prev sibling.
These are all applied recursively to support multiple levels of
placeholders.
*/
nsIFrame* GetParentFrame(nsIFrame* aFrame);
// like GetParentFrame but returns null once a popup frame is reached
nsIFrame* GetParentFrameNotPopup(nsIFrame* aFrame);
nsIFrame* GetFirstChild(nsIFrame* aFrame);
nsIFrame* GetLastChild(nsIFrame* aFrame);
nsIFrame* GetNextSibling(nsIFrame* aFrame);
nsIFrame* GetPrevSibling(nsIFrame* aFrame);
/*
These methods are overridden by the bidi visual iterator to have the
semantics of "get first child in visual order", "get last child in visual
order", "get next sibling in visual order" and "get previous sibling in visual
order".
*/
virtual nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
virtual nsIFrame* GetLastChildInner(nsIFrame* aFrame);
virtual nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
virtual nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);
nsIFrame* GetPlaceholderFrame(nsIFrame* aFrame);
bool IsPopupFrame(nsIFrame* aFrame);
nsPresContext* mPresContext;
bool mLockScroll;
bool mFollowOOFs;
nsIteratorType mType;
private:
nsIFrame *mStart;
nsIFrame *mCurrent;
nsIFrame *mLast; //the last one that was in current;
PRInt8 mOffEdge; //0= no -1 to far prev, 1 to far next;
};
// Bidi visual iterator
class nsVisualIterator: public nsFrameIterator
{
public:
nsVisualIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockScroll, bool aFollowOOFs) :
nsFrameIterator(aPresContext, aStart, aType, aLockScroll, aFollowOOFs) {}
protected:
nsIFrame* GetFirstChildInner(nsIFrame* aFrame);
nsIFrame* GetLastChildInner(nsIFrame* aFrame);
nsIFrame* GetNextSiblingInner(nsIFrame* aFrame);
nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame);
};
/************IMPLEMENTATIONS**************/
nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nullptr;
nsCOMPtr<nsIFrameTraversal> t(new nsFrameTraversal());
*aResult = t;
NS_ADDREF(*aResult);
return NS_OK;
}
nsresult
NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsPresContext* aPresContext,
nsIFrame *aStart,
nsIteratorType aType,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs)
{
if (!aEnumerator || !aStart)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIFrameEnumerator> trav;
if (aVisual) {
trav = new nsVisualIterator(aPresContext, aStart, aType,
aLockInScrollView, aFollowOOFs);
} else {
trav = new nsFrameIterator(aPresContext, aStart, aType,
aLockInScrollView, aFollowOOFs);
}
trav.forget(aEnumerator);
return NS_OK;
}
nsFrameTraversal::nsFrameTraversal()
{
}
nsFrameTraversal::~nsFrameTraversal()
{
}
NS_IMPL_ISUPPORTS1(nsFrameTraversal,nsIFrameTraversal)
NS_IMETHODIMP
nsFrameTraversal::NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsPresContext* aPresContext,
nsIFrame *aStart,
PRInt32 aType,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs)
{
return NS_NewFrameTraversal(aEnumerator, aPresContext, aStart,
static_cast<nsIteratorType>(aType),
aVisual, aLockInScrollView, aFollowOOFs);
}
// nsFrameIterator implementation
NS_IMPL_ISUPPORTS1(nsFrameIterator, nsIFrameEnumerator)
nsFrameIterator::nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart,
nsIteratorType aType, bool aLockInScrollView,
bool aFollowOOFs)
{
mOffEdge = 0;
mPresContext = aPresContext;
if (aFollowOOFs && aStart)
aStart = nsPlaceholderFrame::GetRealFrameFor(aStart);
setStart(aStart);
setCurrent(aStart);
setLast(aStart);
mType = aType;
SetLockInScrollView(aLockInScrollView);
mFollowOOFs = aFollowOOFs;
}
nsIFrame*
nsFrameIterator::CurrentItem()
{
return mOffEdge ? nullptr : mCurrent;
if (mOffEdge)
return nullptr;
return mCurrent;
}
bool
nsFrameIterator::IsDone()
{
@ -65,7 +246,7 @@ nsFrameIterator::Last()
while ((result = GetLastChild(parent))) {
parent = result;
}
setCurrent(parent);
if (!parent)
setOffEdge(1);
@ -146,7 +327,7 @@ nsFrameIterator::Prev()
if (result)
parent = result;
}
if (parent != getCurrent()) {
result = parent;
} else {
@ -189,7 +370,7 @@ nsFrameIterator::GetParentFrame(nsIFrame* aFrame)
aFrame = GetPlaceholderFrame(aFrame);
if (aFrame)
return aFrame->GetParent();
return nullptr;
}
@ -203,7 +384,7 @@ nsFrameIterator::GetParentFrameNotPopup(nsIFrame* aFrame)
if (!IsPopupFrame(parent))
return parent;
}
return nullptr;
}
@ -215,7 +396,7 @@ nsFrameIterator::GetFirstChild(nsIFrame* aFrame)
return nullptr;
if (result && mFollowOOFs) {
result = nsPlaceholderFrame::GetRealFrameFor(result);
if (IsPopupFrame(result))
result = GetNextSibling(result);
}
@ -230,7 +411,7 @@ nsFrameIterator::GetLastChild(nsIFrame* aFrame)
return nullptr;
if (result && mFollowOOFs) {
result = nsPlaceholderFrame::GetRealFrameFor(result);
if (IsPopupFrame(result))
result = GetPrevSibling(result);
}
@ -275,42 +456,25 @@ nsFrameIterator::GetPrevSibling(nsIFrame* aFrame)
nsIFrame*
nsFrameIterator::GetFirstChildInner(nsIFrame* aFrame) {
if (mVisual) {
return aFrame->PrincipalChildList().GetNextVisualFor(nullptr);
}
return aFrame->GetFirstPrincipalChild();
}
nsIFrame*
nsFrameIterator::GetLastChildInner(nsIFrame* aFrame) {
if (mVisual) {
return aFrame->PrincipalChildList().GetPrevVisualFor(nullptr);
}
return aFrame->PrincipalChildList().LastChild();
}
nsIFrame*
nsFrameIterator::GetNextSiblingInner(nsIFrame* aFrame) {
if (mVisual) {
nsIFrame* parent = GetParentFrame(aFrame);
if (!parent)
return nullptr;
return parent->PrincipalChildList().GetNextVisualFor(aFrame);
}
return aFrame->GetNextSibling();
}
nsIFrame*
nsFrameIterator::GetPrevSiblingInner(nsIFrame* aFrame) {
if (mVisual) {
nsIFrame* parent = GetParentFrame(aFrame);
if (!parent)
return nullptr;
return parent->PrincipalChildList().GetPrevVisualFor(aFrame);
}
return aFrame->GetPrevSibling();
}
nsIFrame*
nsFrameIterator::GetPlaceholderFrame(nsIFrame* aFrame)
{
@ -335,3 +499,30 @@ nsFrameIterator::IsPopupFrame(nsIFrame* aFrame)
aFrame->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_POPUP);
}
// nsVisualIterator implementation
nsIFrame*
nsVisualIterator::GetFirstChildInner(nsIFrame* aFrame) {
return aFrame->PrincipalChildList().GetNextVisualFor(nullptr);
}
nsIFrame*
nsVisualIterator::GetLastChildInner(nsIFrame* aFrame) {
return aFrame->PrincipalChildList().GetPrevVisualFor(nullptr);
}
nsIFrame*
nsVisualIterator::GetNextSiblingInner(nsIFrame* aFrame) {
nsIFrame* parent = GetParentFrame(aFrame);
if (!parent)
return nullptr;
return parent->PrincipalChildList().GetNextVisualFor(aFrame);
}
nsIFrame*
nsVisualIterator::GetPrevSiblingInner(nsIFrame* aFrame) {
nsIFrame* parent = GetParentFrame(aFrame);
if (!parent)
return nullptr;
return parent->PrincipalChildList().GetPrevVisualFor(aFrame);
}

View File

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef NSFRAMETRAVERSAL_H
#define NSFRAMETRAVERSAL_H
#include "nsIFrame.h"
#include "nsIFrameTraversal.h"
nsresult NS_NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsPresContext* aPresContext,
nsIFrame *aStart,
nsIteratorType aType,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs);
nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
class nsFrameTraversal : public nsIFrameTraversal
{
public:
nsFrameTraversal();
virtual ~nsFrameTraversal();
NS_DECL_ISUPPORTS
NS_IMETHOD NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsPresContext* aPresContext,
nsIFrame *aStart,
PRInt32 aType,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs);
};
#endif //NSFRAMETRAVERSAL_H

View File

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef NSIFRAMETRAVERSAL_H
#define NSIFRAMETRAVERSAL_H
#include "nsISupports.h"
#include "nsIFrame.h"
#define NS_IFRAMEENUMERATOR_IID \
{ 0x7c633f5d, 0x91eb, 0x494e, \
{ 0xa1, 0x40, 0x17, 0x46, 0x17, 0x4c, 0x23, 0xd3 } }
class nsIFrameEnumerator : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFRAMEENUMERATOR_IID)
virtual void First() = 0;
virtual void Next() = 0;
virtual nsIFrame* CurrentItem() = 0;
virtual bool IsDone() = 0;
virtual void Last() = 0;
virtual void Prev() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrameEnumerator, NS_IFRAMEENUMERATOR_IID)
enum nsIteratorType {
eLeaf,
ePreOrder,
ePostOrder
};
// {9d469828-9bf2-4151-a385-05f30219221b}
#define NS_IFRAMETRAVERSAL_IID \
{ 0x9d469828, 0x9bf2, 0x4151, { 0xa3, 0x85, 0x05, 0xf3, 0x02, 0x19, 0x22, 0x1b } }
class nsIFrameTraversal : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFRAMETRAVERSAL_IID)
/**
* Create a frame iterator with the specified properties.
* @param aEnumerator [out] the created iterator
* @param aPresContext [in]
* @param aStart [in] the frame to start iterating from
* @param aType [in] the type of the iterator: leaf, pre-order, or post-order
* @param aVisual [in] whether the iterator should traverse frames in visual
* bidi order
* @param aLockInScrollView [in] whether to stop iterating when exiting a
* scroll view
* @param aFollowOOFs [in] whether the iterator should follow out-of-flows.
* If true, when reaching a placeholder frame while going down will get
* the real frame. Going back up will go on past the placeholder,
* so the placeholders are logically part of the frame tree.
*/
NS_IMETHOD NewFrameTraversal(nsIFrameEnumerator **aEnumerator,
nsPresContext* aPresContext,
nsIFrame *aStart,
PRInt32 aType,
bool aVisual,
bool aLockInScrollView,
bool aFollowOOFs) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIFrameTraversal, NS_IFRAMETRAVERSAL_IID)
#endif //NSIFRAMETRAVERSAL_H

View File

@ -6,6 +6,10 @@
#ifndef nsLayoutCID_h__
#define nsLayoutCID_h__
// {1691E1F4-EE41-11d4-9885-00C04FA0CF4B}
#define NS_FRAMETRAVERSAL_CID \
{ 0x1691e1f4, 0xee41, 0x11d4, { 0x98, 0x85, 0x0, 0xc0, 0x4f, 0xa0, 0xcf, 0x4b } }
/* a6cf90f9-15b3-11d2-932e-00805f8add32 */
#define NS_LAYOUT_DEBUGGER_CID \
{ 0xa6cf90f9, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}

View File

@ -45,6 +45,7 @@
#include "nsContentAreaDragDrop.h"
#include "nsContentList.h"
#include "nsBox.h"
#include "nsIFrameTraversal.h"
#include "nsLayoutCID.h"
#include "nsStyleSheetService.h"
#include "nsFocusManager.h"
@ -444,6 +445,8 @@ nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult);
nsresult NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult);
nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
nsresult NS_CreateFrameTraversal(nsIFrameTraversal** aResult);
nsresult NS_NewDomSelection(nsISelection** aResult);
nsresult NS_NewContentViewer(nsIContentViewer** aResult);
nsresult NS_NewGenRegularIterator(nsIContentIterator** aResult);
@ -498,6 +501,7 @@ MAKE_CTOR(CreateNewFrameUtil, nsIFrameUtil, NS_NewFra
MAKE_CTOR(CreateNewLayoutDebugger, nsILayoutDebugger, NS_NewLayoutDebugger)
#endif
MAKE_CTOR(CreateNewFrameTraversal, nsIFrameTraversal, NS_CreateFrameTraversal)
MAKE_CTOR(CreateNewPresShell, nsIPresShell, NS_NewPresShell)
MAKE_CTOR(CreateNewBoxObject, nsIBoxObject, NS_NewBoxObject)
@ -692,6 +696,7 @@ Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
NS_DEFINE_NAMED_CID(NS_FRAME_UTIL_CID);
NS_DEFINE_NAMED_CID(NS_LAYOUT_DEBUGGER_CID);
#endif
NS_DEFINE_NAMED_CID(NS_FRAMETRAVERSAL_CID);
NS_DEFINE_NAMED_CID(NS_PRESSHELL_CID);
NS_DEFINE_NAMED_CID(NS_BOXOBJECT_CID);
#ifdef MOZ_XUL
@ -977,6 +982,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_FRAME_UTIL_CID, false, NULL, CreateNewFrameUtil },
{ &kNS_LAYOUT_DEBUGGER_CID, false, NULL, CreateNewLayoutDebugger },
#endif
{ &kNS_FRAMETRAVERSAL_CID, false, NULL, CreateNewFrameTraversal },
{ &kNS_PRESSHELL_CID, false, NULL, CreateNewPresShell },
{ &kNS_BOXOBJECT_CID, false, NULL, CreateNewBoxObject },
#ifdef MOZ_XUL

View File

@ -49,7 +49,7 @@
#include "nsCSSPseudoElements.h"
#include "nsCSSFrameConstructor.h"
#include "nsFrameIterator.h"
#include "nsFrameTraversal.h"
#include "nsStyleChangeList.h"
#include "nsIDOMRange.h"
#include "nsRange.h"
@ -5811,12 +5811,17 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
//resultFrame is not a block frame
result = NS_ERROR_FAILURE;
uint32_t flags = nsFrameIterator::FLAG_NONE;
if (aPos->mScrollViewStop) {
flags |= nsFrameIterator::FLAG_LOCK_SCROLL;
}
nsFrameIterator frameTraversal(aPresContext, resultFrame,
ePostOrder, flags);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
aPresContext, resultFrame,
ePostOrder,
false, // aVisual
aPos->mScrollViewStop,
false // aFollowOOFs
);
if (NS_FAILED(result))
return result;
nsIFrame *storeOldResultFrame = resultFrame;
while ( !found ){
nsPoint point;
@ -5830,7 +5835,7 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
return result;
point.y = tempRect.height + offset.y;
//special check. if we allow non-text selection then we can allow a hit location to fall before a table.
//special check. if we allow non-text selection then we can allow a hit location to fall before a table.
//otherwise there is no way to get and click signal to fall before a table (it being a line iterator itself)
nsIPresShell *shell = aPresContext->GetPresShell();
if (!shell)
@ -5893,8 +5898,8 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
if (aPos->mDirection == eDirNext && (resultFrame == nearStoppingFrame))
break;
//always try previous on THAT line if that fails go the other way
frameTraversal.Prev();
resultFrame = frameTraversal.CurrentItem();
frameTraversal->Prev();
resultFrame = frameTraversal->CurrentItem();
if (!resultFrame)
return NS_ERROR_FAILURE;
}
@ -5902,12 +5907,13 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
if (!found){
resultFrame = storeOldResultFrame;
uint32_t flags = nsFrameIterator::FLAG_NONE;
if (aPos->mScrollViewStop) {
flags |= nsFrameIterator::FLAG_LOCK_SCROLL;
}
frameTraversal = nsFrameIterator(aPresContext, resultFrame,
eLeaf, flags);
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
aPresContext, resultFrame,
eLeaf,
false, // aVisual
aPos->mScrollViewStop,
false // aFollowOOFs
);
}
while ( !found ){
nsPoint point(aPos->mDesiredX, 0);
@ -5938,8 +5944,8 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
if (aPos->mDirection == eDirNext && (resultFrame == farStoppingFrame))
break;
//previous didnt work now we try "next"
frameTraversal.Next();
nsIFrame *tempFrame = frameTraversal.CurrentItem();
frameTraversal->Next();
nsIFrame *tempFrame = frameTraversal->CurrentItem();
if (!tempFrame)
break;
resultFrame = tempFrame;
@ -6663,22 +6669,23 @@ nsIFrame::GetFrameFromDirection(nsDirection aDirection, bool aVisual,
return NS_ERROR_FAILURE; //we are done. cannot jump lines
}
uint32_t flags = nsFrameIterator::FLAG_FOLLOW_OUT_OF_FLOW;
if (aScrollViewStop) {
flags |= nsFrameIterator::FLAG_LOCK_SCROLL;
}
if (aVisual && presContext->BidiEnabled()) {
flags |= nsFrameIterator::FLAG_VISUAL;
}
nsFrameIterator frameTraversal(presContext, traversedFrame,
eLeaf, flags);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
presContext, traversedFrame,
eLeaf,
aVisual && presContext->BidiEnabled(),
aScrollViewStop,
true // aFollowOOFs
);
if (NS_FAILED(result))
return result;
if (aDirection == eDirNext)
frameTraversal.Next();
frameTraversal->Next();
else
frameTraversal.Prev();
frameTraversal->Prev();
traversedFrame = frameTraversal.CurrentItem();
traversedFrame = frameTraversal->CurrentItem();
if (!traversedFrame)
return NS_ERROR_FAILURE;
traversedFrame->IsSelectable(&selectable, nullptr);

View File

@ -40,12 +40,14 @@
#include "nsTextFragment.h"
// for IBMBIDI
#include "nsFrameIterator.h"
#include "nsFrameTraversal.h"
#include "nsILineIterator.h"
#include "nsGkAtoms.h"
#include "nsIFrameTraversal.h"
#include "nsLayoutUtils.h"
#include "nsLayoutCID.h"
#include "nsBidiPresUtils.h"
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "nsTextFrame.h"
#include "nsIDOMText.h"
@ -1245,17 +1247,30 @@ nsFrameSelection::GetFrameFromLevel(nsIFrame *aFrameIn,
uint8_t foundLevel = 0;
nsIFrame *foundFrame = aFrameIn;
nsFrameIterator frameTraversal(mShell->GetPresContext(), aFrameIn,
eLeaf, nsFrameIterator::FLAG_NONE);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
nsresult result;
nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID,&result));
if (NS_FAILED(result))
return result;
result = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
mShell->GetPresContext(), aFrameIn,
eLeaf,
false, // aVisual
false, // aLockInScrollView
false // aFollowOOFs
);
if (NS_FAILED(result))
return result;
do {
*aFrameOut = foundFrame;
if (aDirection == eDirNext)
frameTraversal.Next();
frameTraversal->Next();
else
frameTraversal.Prev();
frameTraversal->Prev();
foundFrame = frameTraversal.CurrentItem();
foundFrame = frameTraversal->CurrentItem();
if (!foundFrame)
return NS_ERROR_FAILURE;
foundLevel = NS_GET_EMBEDDING_LEVEL(foundFrame);

View File

@ -25,7 +25,7 @@
#include "nsIDOMNode.h"
#include "mozilla/dom/Element.h"
#include "nsIFrame.h"
#include "nsFrameIterator.h"
#include "nsFrameTraversal.h"
#include "nsIImageDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLElement.h"
@ -63,6 +63,8 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsTypeAheadFind)
NS_IMPL_RELEASE(nsTypeAheadFind)
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
nsTypeAheadFind::nsTypeAheadFind():
@ -1112,12 +1114,23 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
// We know that the target range isn't usable because it's not in the
// view port. Move range forward to first visible point,
// this speeds us up a lot in long documents
nsFrameIterator frameTraversal(aPresContext, frame,
eLeaf, nsFrameIterator::FLAG_NONE);
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID));
if (trav)
trav->NewFrameTraversal(getter_AddRefs(frameTraversal),
aPresContext, frame,
eLeaf,
false, // aVisual
false, // aLockInScrollView
false // aFollowOOFs
);
if (!frameTraversal)
return false;
while (rectVisibility == nsRectVisibility_kAboveViewport) {
frameTraversal.Next();
frame = frameTraversal.CurrentItem();
frameTraversal->Next();
frame = frameTraversal->CurrentItem();
if (!frame)
return false;