Bug 987040 - Part 2: Add a flag indicate whether CollectClientRects should flush layout or not. r=ehsan

This commit is contained in:
Morris Tseng 2014-07-23 23:06:00 +02:00
Родитель bdc2515786
Коммит cc9241e019
4 изменённых файлов: 32 добавлений и 22 удалений

Просмотреть файл

@ -2749,13 +2749,17 @@ static void ExtractRectFromOffset(nsIFrame* aFrame,
}
static nsTextFrame*
GetTextFrameForContent(nsIContent* aContent)
GetTextFrameForContent(nsIContent* aContent, bool aFlushLayout)
{
nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
if (presShell) {
presShell->FrameConstructor()->EnsureFrameForTextNode(
static_cast<nsGenericDOMDataNode*>(aContent));
aContent->OwnerDoc()->FlushPendingNotifications(Flush_Layout);
if (aFlushLayout) {
aContent->OwnerDoc()->FlushPendingNotifications(Flush_Layout);
}
nsIFrame* frame = aContent->GetPrimaryFrame();
if (frame && frame->GetType() == nsGkAtoms::textFrame) {
return static_cast<nsTextFrame*>(frame);
@ -2766,9 +2770,10 @@ GetTextFrameForContent(nsIContent* aContent)
static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
nsIContent* aContent, int32_t aStartOffset,
int32_t aEndOffset, bool aClampToEdge)
int32_t aEndOffset, bool aClampToEdge,
bool aFlushLayout)
{
nsTextFrame* textFrame = GetTextFrameForContent(aContent);
nsTextFrame* textFrame = GetTextFrameForContent(aContent, aFlushLayout);
if (textFrame) {
nsIFrame* relativeTo = nsLayoutUtils::GetContainingBlockForClientRect(textFrame);
for (nsTextFrame* f = textFrame; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
@ -2801,7 +2806,7 @@ nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
nsRange* aRange,
nsINode* aStartParent, int32_t aStartOffset,
nsINode* aEndParent, int32_t aEndOffset,
bool aClampToEdge)
bool aClampToEdge, bool aFlushLayout)
{
// Hold strong pointers across the flush
nsCOMPtr<nsINode> startContainer = aStartParent;
@ -2812,11 +2817,12 @@ nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
return;
}
aStartParent->OwnerDoc()->FlushPendingNotifications(Flush_Layout);
// Recheck whether we're still in the document
if (!aStartParent->IsInDoc()) {
return;
if (aFlushLayout) {
aStartParent->OwnerDoc()->FlushPendingNotifications(Flush_Layout);
// Recheck whether we're still in the document
if (!aStartParent->IsInDoc()) {
return;
}
}
RangeSubtreeIterator iter;
@ -2828,7 +2834,7 @@ nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
// the range is collapsed, only continue if the cursor is in a text node
nsCOMPtr<nsIContent> content = do_QueryInterface(aStartParent);
if (content && content->IsNodeOfType(nsINode::eTEXT)) {
nsTextFrame* textFrame = GetTextFrameForContent(content);
nsTextFrame* textFrame = GetTextFrameForContent(content, aFlushLayout);
if (textFrame) {
int32_t outOffset;
nsIFrame* outFrame;
@ -2858,10 +2864,12 @@ nsRange::CollectClientRects(nsLayoutUtils::RectCallback* aCollector,
if (node == startContainer) {
int32_t offset = startContainer == endContainer ?
aEndOffset : content->GetText()->GetLength();
GetPartialTextRect(aCollector, content, aStartOffset, offset, aClampToEdge);
GetPartialTextRect(aCollector, content, aStartOffset, offset,
aClampToEdge, aFlushLayout);
continue;
} else if (node == endContainer) {
GetPartialTextRect(aCollector, content, 0, aEndOffset, aClampToEdge);
GetPartialTextRect(aCollector, content, 0, aEndOffset,
aClampToEdge, aFlushLayout);
continue;
}
}
@ -2883,7 +2891,7 @@ nsRange::GetBoundingClientRect(nsIDOMClientRect** aResult)
}
already_AddRefed<DOMRect>
nsRange::GetBoundingClientRect(bool aClampToEdge)
nsRange::GetBoundingClientRect(bool aClampToEdge, bool aFlushLayout)
{
nsRefPtr<DOMRect> rect = new DOMRect(ToSupports(this));
if (!mStartParent) {
@ -2892,7 +2900,7 @@ nsRange::GetBoundingClientRect(bool aClampToEdge)
nsLayoutUtils::RectAccumulator accumulator;
CollectClientRects(&accumulator, this, mStartParent, mStartOffset,
mEndParent, mEndOffset, aClampToEdge);
mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
nsRect r = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect :
accumulator.mResultRect;
@ -2908,7 +2916,7 @@ nsRange::GetClientRects(nsIDOMClientRectList** aResult)
}
already_AddRefed<DOMRectList>
nsRange::GetClientRects(bool aClampToEdge)
nsRange::GetClientRects(bool aClampToEdge, bool aFlushLayout)
{
if (!mStartParent) {
return nullptr;
@ -2920,7 +2928,7 @@ nsRange::GetClientRects(bool aClampToEdge)
nsLayoutUtils::RectListBuilder builder(rectList);
CollectClientRects(&builder, this, mStartParent, mStartOffset,
mEndParent, mEndOffset, aClampToEdge);
mEndParent, mEndOffset, aClampToEdge, aFlushLayout);
return rectList.forget();
}

Просмотреть файл

@ -217,8 +217,10 @@ public:
void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
void SurroundContents(nsINode& aNode, ErrorResult& aErr);
already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true);
already_AddRefed<DOMRectList> GetClientRects(bool aClampToEdge = true);
already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
bool aFlushLayout = true);
already_AddRefed<DOMRectList> GetClientRects(bool aClampToEdge = true,
bool aFlushLayout = true);
nsINode* GetParentObject() const { return mOwner; }
virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE MOZ_FINAL;
@ -260,7 +262,7 @@ public:
nsRange* aRange,
nsINode* aStartParent, int32_t aStartOffset,
nsINode* aEndParent, int32_t aEndOffset,
bool aClampToEdge);
bool aClampToEdge, bool aFlushLayout);
typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
protected:

Просмотреть файл

@ -9279,7 +9279,7 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, in
nsresult rv = aSel->GetRangeAt(0, getter_AddRefs(range));
if (NS_SUCCEEDED(rv) && range) {
nsRefPtr<nsRange> nsrange = static_cast<nsRange*>(range.get());
init.mBoundingClientRect = nsrange->GetBoundingClientRect(true);
init.mBoundingClientRect = nsrange->GetBoundingClientRect(true, false);
range->ToString(init.mSelectedText);
init.mReason = aReason;
}

Просмотреть файл

@ -382,7 +382,7 @@ SelectionCarets::UpdateSelectionCarets()
nsLayoutUtils::FirstAndLastRectCollector collector;
nsRange::CollectClientRects(&collector, range,
range->GetStartParent(), range->StartOffset(),
range->GetEndParent(), range->EndOffset(), true);
range->GetEndParent(), range->EndOffset(), true, true);
nsIFrame* canvasFrame = mPresShell->GetCanvasFrame();
nsIFrame* rootFrame = mPresShell->GetRootFrame();