Bug 1094056 - Use nsCaret::GetGeometryForFrame to determine position of selection carets. r=roc

This commit is contained in:
Morris Tseng 2014-11-11 22:54:00 +01:00
Родитель 179821a35d
Коммит 8733cb18e1
4 изменённых файлов: 25 добавлений и 68 удалений

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

@ -377,19 +377,6 @@ IsRightToLeft(nsIFrame* aFrame)
aFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
}
/*
* Reduce rect to 1 css pixel width along either left or right edge base on
* aToRightEdge parameter.
*/
static void
ReduceRectToVerticalEdge(nsRect& aRect, bool aToRightEdge)
{
if (aToRightEdge) {
aRect.x = aRect.XMost() - AppUnitsPerCSSPixel();
}
aRect.width = AppUnitsPerCSSPixel();
}
static nsIFrame*
FindFirstNodeWithFrame(nsIDocument* aDocument,
nsRange* aRange,
@ -472,16 +459,6 @@ SelectionCarets::UpdateSelectionCarets()
nsRefPtr<nsRange> firstRange = selection->GetRangeAt(0);
nsRefPtr<nsRange> lastRange = selection->GetRangeAt(rangeCount - 1);
nsLayoutUtils::FirstAndLastRectCollector collectorStart;
nsRange::CollectClientRects(&collectorStart, firstRange,
firstRange->GetStartParent(), firstRange->StartOffset(),
firstRange->GetEndParent(), firstRange->EndOffset(), true, true);
nsLayoutUtils::FirstAndLastRectCollector collectorEnd;
nsRange::CollectClientRects(&collectorEnd, lastRange,
lastRange->GetStartParent(), lastRange->StartOffset(),
lastRange->GetEndParent(), lastRange->EndOffset(), true, true);
nsIFrame* canvasFrame = mPresShell->GetCanvasFrame();
nsIFrame* rootFrame = mPresShell->GetRootFrame();
@ -522,17 +499,29 @@ SelectionCarets::UpdateSelectionCarets()
bool startFrameIsRTL = IsRightToLeft(startFrame);
bool endFrameIsRTL = IsRightToLeft(endFrame);
// If start frame is LTR, then place start caret in first rect's leftmost
// otherwise put it to first rect's rightmost.
ReduceRectToVerticalEdge(collectorStart.mFirstRect, startFrameIsRTL);
mPresShell->FlushPendingNotifications(Flush_Layout);
nsRect firstRectInRootFrame =
nsCaret::GetGeometryForFrame(startFrame, startOffset, nullptr);
nsRect lastRectInRootFrame =
nsCaret::GetGeometryForFrame(endFrame, endOffset, nullptr);
// Contrary to start frame, if end frame is LTR, put end caret to last
// rect's rightmost position, otherwise, put it to last rect's leftmost.
ReduceRectToVerticalEdge(collectorEnd.mLastRect, !endFrameIsRTL);
// GetGeometryForFrame may return a rect that outside frame's rect. So
// constrain rect inside frame's rect.
firstRectInRootFrame = firstRectInRootFrame.ForceInside(startFrame->GetRectRelativeToSelf());
lastRectInRootFrame = lastRectInRootFrame.ForceInside(endFrame->GetRectRelativeToSelf());
nsRect firstRectInCanvasFrame = firstRectInRootFrame;
nsRect lastRectInCanvasFrame =lastRectInRootFrame;
nsLayoutUtils::TransformRect(startFrame, rootFrame, firstRectInRootFrame);
nsLayoutUtils::TransformRect(endFrame, rootFrame, lastRectInRootFrame);
nsLayoutUtils::TransformRect(startFrame, canvasFrame, firstRectInCanvasFrame);
nsLayoutUtils::TransformRect(endFrame, canvasFrame, lastRectInCanvasFrame);
firstRectInRootFrame.Inflate(AppUnitsPerCSSPixel(), 0);
lastRectInRootFrame.Inflate(AppUnitsPerCSSPixel(), 0);
nsAutoTArray<nsIFrame*, 16> hitFramesInFirstRect;
nsLayoutUtils::GetFramesForArea(rootFrame,
collectorStart.mFirstRect,
firstRectInRootFrame,
hitFramesInFirstRect,
nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
nsLayoutUtils::IGNORE_CROSS_DOC |
@ -540,7 +529,7 @@ SelectionCarets::UpdateSelectionCarets()
nsAutoTArray<nsIFrame*, 16> hitFramesInLastRect;
nsLayoutUtils::GetFramesForArea(rootFrame,
collectorEnd.mLastRect,
lastRectInRootFrame,
hitFramesInLastRect,
nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
nsLayoutUtils::IGNORE_CROSS_DOC |
@ -549,11 +538,8 @@ SelectionCarets::UpdateSelectionCarets()
SetStartFrameVisibility(hitFramesInFirstRect.Contains(startFrame));
SetEndFrameVisibility(hitFramesInLastRect.Contains(endFrame));
nsLayoutUtils::TransformRect(rootFrame, canvasFrame, collectorStart.mFirstRect);
nsLayoutUtils::TransformRect(rootFrame, canvasFrame, collectorEnd.mLastRect);
SetStartFramePos(collectorStart.mFirstRect.BottomLeft());
SetEndFramePos(collectorEnd.mLastRect.BottomRight());
SetStartFramePos(firstRectInCanvasFrame.BottomLeft());
SetEndFramePos(lastRectInCanvasFrame.BottomRight());
SetVisibility(true);
// If range select only one character, append tilt class name to it.

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

@ -149,6 +149,9 @@ class nsCaret MOZ_FINAL : public nsISelectionListener
uint8_t aBidiLevel,
nsIFrame** aReturnFrame,
int32_t* aReturnOffset);
static nsRect GetGeometryForFrame(nsIFrame* aFrame,
int32_t aFrameOffset,
nscoord* aBidiIndicatorSize);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
@ -168,9 +171,6 @@ protected:
};
static Metrics ComputeMetrics(nsIFrame* aFrame, int32_t aOffset,
nscoord aCaretHeight);
static nsRect GetGeometryForFrame(nsIFrame* aFrame,
int32_t aFrameOffset,
nscoord* aBidiIndicatorSize);
void ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
nsRect* aCaretRect, nsRect* aHookRect);

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

@ -3400,20 +3400,6 @@ void nsLayoutUtils::RectListBuilder::AddRect(const nsRect& aRect) {
mRectList->Append(rect);
}
nsLayoutUtils::FirstAndLastRectCollector::FirstAndLastRectCollector()
: mSeenFirstRect(false)
{
}
void nsLayoutUtils::FirstAndLastRectCollector::AddRect(const nsRect& aRect) {
if (!mSeenFirstRect) {
mSeenFirstRect = true;
mFirstRect = aRect;
}
mLastRect = aRect;
}
nsIFrame* nsLayoutUtils::GetContainingBlockForClientRect(nsIFrame* aFrame)
{
return aFrame->PresContext()->PresShell()->GetRootFrame();

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

@ -1026,21 +1026,6 @@ public:
virtual void AddRect(const nsRect& aRect);
};
/**
* SelectionCaret draws carets base on range. The carets are at begin
* and end position of range's client rects. This class help us to
* collect first and last rect for drawing carets.
*/
struct FirstAndLastRectCollector : public RectCallback {
nsRect mFirstRect;
nsRect mLastRect;
bool mSeenFirstRect;
FirstAndLastRectCollector();
virtual void AddRect(const nsRect& aRect);
};
static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame);
enum {