зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 8243da10a171 (bug 1302470)
This commit is contained in:
Родитель
7de6273ae5
Коммит
9a38c0010b
|
@ -821,7 +821,7 @@ public:
|
|||
* frames under the area of a rectangle that receives a mouse event,
|
||||
* or nullptr if there is no such frame.
|
||||
* @param aRect the rect, relative to the frame origin
|
||||
* @param aOutFrames an array to append all the frames found
|
||||
* @param aOutFrames an array to add all the frames found
|
||||
* @param aFlags some combination of FrameForPointFlags
|
||||
*/
|
||||
static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
|
||||
|
|
|
@ -18,7 +18,7 @@ interface nsIDocShell;
|
|||
|
||||
/****************************** nsTypeAheadFind ******************************/
|
||||
|
||||
[scriptable, uuid(3cfe7906-f189-45a0-8abe-8e4437a23cae)]
|
||||
[scriptable, uuid(ae501e28-c57f-4692-ac74-410e1bed98b7)]
|
||||
interface nsITypeAheadFind : nsISupports
|
||||
{
|
||||
/****************************** Initializer ******************************/
|
||||
|
@ -58,7 +58,7 @@ interface nsITypeAheadFind : nsISupports
|
|||
void collapseSelection();
|
||||
|
||||
/* Check if a range is visible */
|
||||
boolean isRangeVisible(in nsIDOMRange aRange, in boolean aFlushLayout);
|
||||
boolean isRangeVisible(in nsIDOMRange aRange, in boolean aMustBeInViewPort);
|
||||
|
||||
/******************************* Attributes ******************************/
|
||||
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "mozilla/dom/Link.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
#include "nsTypeAheadFind.h"
|
||||
|
||||
|
@ -71,6 +70,8 @@ NS_IMPL_CYCLE_COLLECTION(nsTypeAheadFind, mFoundLink, mFoundEditable,
|
|||
mStartPointRange, mEndPointRange, mSoundInterface,
|
||||
mFind, mFoundRange)
|
||||
|
||||
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
||||
|
||||
#define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
|
||||
|
||||
nsTypeAheadFind::nsTypeAheadFind():
|
||||
|
@ -435,7 +436,8 @@ nsTypeAheadFind::FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly,
|
|||
}
|
||||
|
||||
bool usesIndependentSelection;
|
||||
if (!IsRangeVisible(presShell, presContext, returnRange, true,
|
||||
if (!IsRangeVisible(presShell, presContext, returnRange,
|
||||
aIsFirstVisiblePreferred, false,
|
||||
getter_AddRefs(mStartPointRange),
|
||||
&usesIndependentSelection) ||
|
||||
(aIsLinksOnly && !isInsideLink) ||
|
||||
|
@ -815,7 +817,8 @@ nsTypeAheadFind::GetSearchContainers(nsISupports *aContainer,
|
|||
// Ensure visible range, move forward if necessary
|
||||
// This uses ignores the return value, but usese the side effect of
|
||||
// IsRangeVisible. It returns the first visible range after searchRange
|
||||
IsRangeVisible(presShell, presContext, mSearchRange, true,
|
||||
IsRangeVisible(presShell, presContext, mSearchRange,
|
||||
aIsFirstVisiblePreferred, true,
|
||||
getter_AddRefs(mStartPointRange), nullptr);
|
||||
}
|
||||
else {
|
||||
|
@ -1158,7 +1161,7 @@ nsTypeAheadFind::GetFoundRange(nsIDOMRange** aFoundRange)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsTypeAheadFind::IsRangeVisible(nsIDOMRange *aRange,
|
||||
bool aFlushLayout,
|
||||
bool aMustBeInViewPort,
|
||||
bool *aResult)
|
||||
{
|
||||
// Jump through hoops to extract the docShell from the range.
|
||||
|
@ -1175,7 +1178,8 @@ nsTypeAheadFind::IsRangeVisible(nsIDOMRange *aRange,
|
|||
nsCOMPtr<nsIPresShell> presShell (docShell->GetPresShell());
|
||||
RefPtr<nsPresContext> presContext = presShell->GetPresContext();
|
||||
nsCOMPtr<nsIDOMRange> startPointRange = new nsRange(presShell->GetDocument());
|
||||
*aResult = IsRangeVisible(presShell, presContext, aRange, aFlushLayout,
|
||||
*aResult = IsRangeVisible(presShell, presContext, aRange,
|
||||
aMustBeInViewPort, false,
|
||||
getter_AddRefs(startPointRange),
|
||||
nullptr);
|
||||
return NS_OK;
|
||||
|
@ -1184,8 +1188,8 @@ nsTypeAheadFind::IsRangeVisible(nsIDOMRange *aRange,
|
|||
bool
|
||||
nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
|
||||
nsPresContext *aPresContext,
|
||||
nsIDOMRange *aRange,
|
||||
bool aFlushLayout,
|
||||
nsIDOMRange *aRange, bool aMustBeInViewPort,
|
||||
bool aGetTopVisibleLeaf,
|
||||
nsIDOMRange **aFirstVisibleRange,
|
||||
bool *aUsesIndependentSelection)
|
||||
{
|
||||
|
@ -1195,12 +1199,8 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
|
|||
// We need to know if the range start is visible.
|
||||
// Otherwise, return the first visible range start
|
||||
// in aFirstVisibleRange
|
||||
|
||||
aRange->CloneRange(aFirstVisibleRange);
|
||||
|
||||
if (aFlushLayout) {
|
||||
aPresShell->FlushPendingNotifications(Flush_Layout);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
aRange->GetStartContainer(getter_AddRefs(node));
|
||||
|
||||
|
@ -1209,25 +1209,10 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
|
|||
return false;
|
||||
|
||||
nsIFrame *frame = content->GetPrimaryFrame();
|
||||
if (!frame)
|
||||
if (!frame)
|
||||
return false; // No frame! Not visible then.
|
||||
|
||||
// Having a primary frame doesn't mean that the range is visible inside the
|
||||
// viewport. Do a hit-test to determine that quickly and properly.
|
||||
AutoTArray<nsIFrame*,8> frames;
|
||||
nsIFrame *rootFrame = aPresShell->GetRootFrame();
|
||||
RefPtr<nsRange> range = static_cast<nsRange*>(aRange);
|
||||
RefPtr<mozilla::dom::DOMRectList> rects = range->GetClientRects(true, false);
|
||||
for (uint32_t i = 0; i < rects->Length(); ++i) {
|
||||
RefPtr<mozilla::dom::DOMRect> rect = rects->Item(i);
|
||||
nsRect r(nsPresContext::CSSPixelsToAppUnits((float)rect->X()),
|
||||
nsPresContext::CSSPixelsToAppUnits((float)rect->Y()),
|
||||
nsPresContext::CSSPixelsToAppUnits((float)rect->Width()),
|
||||
nsPresContext::CSSPixelsToAppUnits((float)rect->Height()));
|
||||
nsLayoutUtils::GetFramesForArea(rootFrame, r, frames,
|
||||
nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
|
||||
}
|
||||
if (!frames.Length())
|
||||
if (!frame->StyleVisibility()->IsVisible())
|
||||
return false;
|
||||
|
||||
// Detect if we are _inside_ a text control, or something else with its own
|
||||
|
@ -1237,7 +1222,89 @@ nsTypeAheadFind::IsRangeVisible(nsIPresShell *aPresShell,
|
|||
(frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
|
||||
}
|
||||
|
||||
return true;
|
||||
// ---- We have a frame ----
|
||||
if (!aMustBeInViewPort)
|
||||
return true; // Don't need it to be on screen, just in rendering tree
|
||||
|
||||
// Get the next in flow frame that contains the range start
|
||||
int32_t startRangeOffset, startFrameOffset, endFrameOffset;
|
||||
aRange->GetStartOffset(&startRangeOffset);
|
||||
while (true) {
|
||||
frame->GetOffsets(startFrameOffset, endFrameOffset);
|
||||
if (startRangeOffset < endFrameOffset)
|
||||
break;
|
||||
|
||||
nsIFrame *nextContinuationFrame = frame->GetNextContinuation();
|
||||
if (nextContinuationFrame)
|
||||
frame = nextContinuationFrame;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Set up the variables we need, return true if we can't get at them all
|
||||
const uint16_t kMinPixels = 12;
|
||||
nscoord minDistance = nsPresContext::CSSPixelsToAppUnits(kMinPixels);
|
||||
|
||||
// Get the bounds of the current frame, relative to the current view.
|
||||
// We don't use the more accurate AccGetBounds, because that is
|
||||
// more expensive and the STATE_OFFSCREEN flag that this is used
|
||||
// for only needs to be a rough indicator
|
||||
nsRectVisibility rectVisibility = nsRectVisibility_kAboveViewport;
|
||||
|
||||
if (!aGetTopVisibleLeaf && !frame->GetRect().IsEmpty()) {
|
||||
rectVisibility =
|
||||
aPresShell->GetRectVisibility(frame,
|
||||
nsRect(nsPoint(0,0), frame->GetSize()),
|
||||
minDistance);
|
||||
|
||||
if (rectVisibility != nsRectVisibility_kAboveViewport) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
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
|
||||
false // aSkipPopupChecks
|
||||
);
|
||||
|
||||
if (!frameTraversal)
|
||||
return false;
|
||||
|
||||
while (rectVisibility == nsRectVisibility_kAboveViewport) {
|
||||
frameTraversal->Next();
|
||||
frame = frameTraversal->CurrentItem();
|
||||
if (!frame)
|
||||
return false;
|
||||
|
||||
if (!frame->GetRect().IsEmpty()) {
|
||||
rectVisibility =
|
||||
aPresShell->GetRectVisibility(frame,
|
||||
nsRect(nsPoint(0,0), frame->GetSize()),
|
||||
minDistance);
|
||||
}
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
nsCOMPtr<nsIDOMNode> firstVisibleNode = do_QueryInterface(frame->GetContent());
|
||||
|
||||
if (firstVisibleNode) {
|
||||
frame->GetOffsets(startFrameOffset, endFrameOffset);
|
||||
(*aFirstVisibleRange)->SetStart(firstVisibleNode, startFrameOffset);
|
||||
(*aFirstVisibleRange)->SetEnd(firstVisibleNode, endFrameOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPresShell>
|
||||
|
|
|
@ -56,8 +56,8 @@ protected:
|
|||
// *aNewRange may not be collapsed. If you want to collapse it in a
|
||||
// particular way, you need to do it yourself.
|
||||
bool IsRangeVisible(nsIPresShell *aPresShell, nsPresContext *aPresContext,
|
||||
nsIDOMRange *aRange, bool aFlushLayout,
|
||||
nsIDOMRange **aNewRange,
|
||||
nsIDOMRange *aRange, bool aMustBeVisible,
|
||||
bool aGetTopVisibleLeaf, nsIDOMRange **aNewRange,
|
||||
bool *aUsesIndependentSelection);
|
||||
nsresult FindItNow(nsIPresShell *aPresShell, bool aIsLinksOnly,
|
||||
bool aIsFirstVisiblePreferred, bool aFindPrev,
|
||||
|
|
|
@ -573,8 +573,7 @@ this.FinderIterator = {
|
|||
let range = window.document.createRange();
|
||||
range.setStart(frameEl, 0);
|
||||
range.setEnd(frameEl, 0);
|
||||
// Pass `true` to flush layout.
|
||||
if (!finder._fastFind.isRangeVisible(range, true))
|
||||
if (!finder._fastFind.isRangeVisible(range, this._getDocShell(range), true))
|
||||
continue;
|
||||
// All conditions pass, so push the current frame and its children on the
|
||||
// stack.
|
||||
|
|
Загрузка…
Ссылка в новой задаче