Bug 489127 - nodesFromRect required for better usability on mobile devices (part 1+2) [r=roc]

This commit is contained in:
Felipe Gomes 2010-04-07 20:31:26 -04:00
parent a437509342
commit 960464193b
13 changed files with 181 additions and 120 deletions

View File

@ -885,8 +885,9 @@ void nsDisplayList::DeleteAll() {
}
}
nsIFrame* nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
nsDisplayItem::HitTestState* aState) const {
void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
nsDisplayItem::HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) const {
PRInt32 itemBufferStart = aState->mItemBuffer.Length();
nsDisplayItem* item;
for (item = GetBottom(); item; item = item->GetAbove()) {
@ -898,21 +899,23 @@ nsIFrame* nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
item = aState->mItemBuffer[i];
aState->mItemBuffer.SetLength(i);
if (item->GetBounds(aBuilder).Contains(aPt)) {
nsIFrame* f = item->HitTest(aBuilder, aPt, aState);
// Handle the XUL 'mousethrough' feature and 'pointer-events'.
if (f) {
if (aRect.Intersects(item->GetBounds(aBuilder))) {
nsTArray<nsIFrame*> outFrames;
item->HitTest(aBuilder, aRect, aState, &outFrames);
for (PRUint32 j = 0; j < outFrames.Length(); j++) {
nsIFrame *f = outFrames.ElementAt(j);
// Handle the XUL 'mousethrough' feature and 'pointer-events'.
if (!f->GetMouseThrough() &&
f->GetStyleVisibility()->mPointerEvents != NS_STYLE_POINTER_EVENTS_NONE) {
aState->mItemBuffer.SetLength(itemBufferStart);
return f;
aOutFrames->AppendElement(f);
}
}
}
}
NS_ASSERTION(aState->mItemBuffer.Length() == PRUint32(itemBufferStart),
"How did we forget to pop some elements?");
return nsnull;
}
static void Sort(nsDisplayList* aList, PRInt32 aCount, nsDisplayList::SortLEQ aCmp,
@ -1386,10 +1389,10 @@ nsDisplayWrapList::~nsDisplayWrapList() {
mList.DeleteAll();
}
nsIFrame*
nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) {
return mList.HitTest(aBuilder, aPt, aState);
void
nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
mList.HitTest(aBuilder, aRect, aState, aOutFrames);
}
nsRect
@ -1885,23 +1888,24 @@ PRBool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
#endif
/* HitTest does some fun stuff with matrix transforms to obtain the answer. */
nsIFrame *nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
nsPoint aPt,
HitTestState *aState)
void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
const nsRect& aRect,
HitTestState *aState,
nsTArray<nsIFrame*> *aOutFrames)
{
/* Here's how this works:
* 1. Get the matrix. If it's singular, abort (clearly we didn't hit
* anything).
* 2. Invert the matrix.
* 3. Use it to transform the point into the correct space.
* 4. Pass that point down through to the list's version of HitTest.
* 3. Use it to transform the rect into the correct space.
* 4. Pass that rect down through to the list's version of HitTest.
*/
float factor = nsPresContext::AppUnitsPerCSSPixel();
gfxMatrix matrix =
GetResultingTransformMatrix(mFrame, aBuilder->ToReferenceFrame(mFrame),
factor, nsnull);
if (matrix.IsSingular())
return nsnull;
return;
/* We want to go from transformed-space to regular space.
* Thus we have to invert the matrix, which normally does
@ -1910,27 +1914,45 @@ nsIFrame *nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
matrix.Invert();
/* Now, apply the transform and pass it down the channel. */
gfxPoint result = matrix.Transform(gfxPoint(NSAppUnitsToFloatPixels(aPt.x, factor),
NSAppUnitsToFloatPixels(aPt.y, factor)));
nsRect resultingRect;
if (aRect.width == 1 && aRect.height == 1) {
gfxPoint point = matrix.Transform(gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
NSAppUnitsToFloatPixels(aRect.y, factor)));
resultingRect = nsRect(NSFloatPixelsToAppUnits(float(point.x), factor),
NSFloatPixelsToAppUnits(float(point.y), factor),
1, 1);
} else {
gfxRect originalRect(NSAppUnitsToFloatPixels(aRect.x, factor),
NSAppUnitsToFloatPixels(aRect.y, factor),
NSAppUnitsToFloatPixels(aRect.width, factor),
NSAppUnitsToFloatPixels(aRect.height, factor));
gfxRect rect = matrix.TransformBounds(originalRect);
resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
NSFloatPixelsToAppUnits(float(rect.Y()), factor),
NSFloatPixelsToAppUnits(float(rect.Width()), factor),
NSFloatPixelsToAppUnits(float(rect.Height()), factor));
}
#ifdef DEBUG_HIT
printf("Frame: %p\n", dynamic_cast<void *>(mFrame));
printf(" Untransformed point: (%f, %f)\n", result.x, result.y);
printf(" Untransformed point: (%f, %f)\n", resultingRect.X(), resultingRect.Y());
PRUint32 originalFrameCount = aOutFrames.Length();
#endif
nsIFrame* resultFrame =
mStoredList.HitTest(aBuilder,
nsPoint(NSFloatPixelsToAppUnits(float(result.x), factor),
NSFloatPixelsToAppUnits(float(result.y), factor)), aState);
mStoredList.HitTest(aBuilder, resultingRect, aState, aOutFrames);
#ifdef DEBUG_HIT
if (resultFrame)
printf(" Hit! Time: %f, frame: %p\n", static_cast<double>(clock()),
dynamic_cast<void *>(resultFrame));
if (originalFrameCount != aOutFrames.Length())
printf(" Hit! Time: %f, first frame: %p\n", static_cast<double>(clock()),
dynamic_cast<void *>(aOutFrames.ElementAt(0)));
printf("=== end of hit test ===\n");
#endif
return resultFrame;
}
/* The bounding rectangle for the object is the overflow rectangle translated
@ -2085,14 +2107,15 @@ PRBool nsDisplaySVGEffects::IsOpaque(nsDisplayListBuilder* aBuilder)
return PR_FALSE;
}
nsIFrame*
nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState)
void
nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
if (!nsSVGIntegrationUtils::HitTestFrameForEffects(mEffectsFrame,
aPt - aBuilder->ToReferenceFrame(mEffectsFrame)))
return nsnull;
return mList.HitTest(aBuilder, aPt, aState);
nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
if (nsSVGIntegrationUtils::HitTestFrameForEffects(mEffectsFrame,
rectCenter - aBuilder->ToReferenceFrame(mEffectsFrame))) {
mList.HitTest(aBuilder, aRect, aState, aOutFrames);
}
}
void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,

View File

@ -515,8 +515,8 @@ public:
* @return the frame that the point is considered over, or nsnull if
* this is not over any frame
*/
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return nsnull; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
/**
* @return the frame that this display item is based on. This is used to sort
* items by z-index and content order and for some other uses. For some items
@ -871,8 +871,9 @@ public:
* Find the topmost display item that returns a non-null frame, and return
* the frame.
*/
nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
nsDisplayItem::HitTestState* aState) const;
void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
nsDisplayItem::HitTestState* aState,
nsTArray<nsIFrame*> *aOutFrames) const;
/**
* This class represents a sublist of consecutive items in an nsDisplayList.
@ -1310,8 +1311,11 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
aOutFrames->AppendElement(mFrame);
}
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
@ -1409,8 +1413,11 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
aOutFrames->AppendElement(mFrame);
}
NS_DISPLAY_DECL_NAME("EventReceiver")
};
@ -1440,8 +1447,8 @@ public:
nsDisplayWrapList(nsIFrame* aFrame, nsDisplayItem* aItem);
virtual ~nsDisplayWrapList();
virtual Type GetType() { return TYPE_WRAPLIST; }
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder);
@ -1587,8 +1594,8 @@ public:
virtual Type GetType() { return TYPE_SVG_EFFECTS; }
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
return mBounds + aBuilder->ToReferenceFrame(mEffectsFrame);
}
@ -1644,8 +1651,8 @@ public:
nsDisplayWrapList* GetStoredList() { return &mStoredList; }
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder *aBuilder, nsPoint aPt,
HitTestState *aState);
virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder);

View File

@ -140,9 +140,9 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) {
return mFrame;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);

View File

@ -186,20 +186,20 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("FieldSetBorderBackground")
};
nsIFrame* nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt, HitTestState* aState)
void nsDisplayFieldSetBorderBackground::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
// aPt is guaranteed to be in this item's bounds. We do the hit test based on the
// frame bounds even though our background doesn't cover the whole frame.
// It's not clear whether this is correct.
return mFrame;
aOutFrames->AppendElement(mFrame);
}
void

View File

@ -96,32 +96,34 @@ public:
: nsDisplayWrapList(aFrame, aItem) {}
nsDisplayOptionEventGrabber(nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aFrame, aList) {}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
NS_DISPLAY_DECL_NAME("OptionEventGrabber")
virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem);
};
nsIFrame* nsDisplayOptionEventGrabber::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt, HitTestState* aState)
void nsDisplayOptionEventGrabber::HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
nsIFrame* frame = mList.HitTest(aBuilder, aPt, aState);
nsTArray<nsIFrame*> outFrames;
mList.HitTest(aBuilder, aRect, aState, &outFrames);
if (frame) {
nsIFrame* selectedFrame = frame;
for (PRUint32 i = 0; i < outFrames.Length(); i++) {
nsIFrame* selectedFrame = outFrames.ElementAt(i);
while (selectedFrame &&
!nsSelectsAreaFrame::IsOptionElementFrame(selectedFrame)) {
selectedFrame = selectedFrame->GetParent();
}
if (selectedFrame) {
return selectedFrame;
aOutFrames->AppendElement(selectedFrame);
} else {
// keep the original result, which could be this frame
aOutFrames->AppendElement(outFrames.ElementAt(i));
}
// else, keep the original result, which could be this frame
}
return frame;
}
nsDisplayWrapList* nsDisplayOptionEventGrabber::WrapWithClone(

View File

@ -194,8 +194,10 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("Bullet")

View File

@ -1625,8 +1625,10 @@ public:
// REVIEW: see old GetFrameForPoint
// Receives events in its bounds
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("FramesetBorder")

View File

@ -3879,9 +3879,11 @@ public:
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame);
}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) {
return nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize()).Contains(aPt) ? mFrame : nsnull;
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
if (nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize()).Intersects(aRect)) {
aOutFrames->AppendElement(mFrame);
}
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);

View File

@ -430,19 +430,30 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("SVGEventReceiver")
};
nsIFrame*
nsDisplaySVG::HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState)
void
nsDisplaySVG::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
return static_cast<nsSVGOuterSVGFrame*>(mFrame)->
GetFrameForPoint(aPt - aBuilder->ToReferenceFrame(mFrame));
nsRect rectAtOrigin = aRect - aBuilder->ToReferenceFrame(mFrame);
nsRect thisRect(nsPoint(0,0), static_cast<nsSVGOuterSVGFrame*>(mFrame)->GetSize());
if (!thisRect.Intersects(rectAtOrigin))
return;
nsPoint rectCenter(rectAtOrigin.x + rectAtOrigin.width / 2,
rectAtOrigin.y + rectAtOrigin.height / 2);
nsIFrame* frame = nsSVGUtils::HitTestChildren(static_cast<nsSVGOuterSVGFrame*>(mFrame),
rectCenter);
if (frame) {
aOutFrames->AppendElement(frame);
}
}
void

View File

@ -394,8 +394,10 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);

View File

@ -1264,11 +1264,12 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) {
virtual void HitTest(nsDisplayListBuilder* aBuilder, nsRect aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
static_cast<nsBoxFrame*>(mFrame)->
DisplayDebugInfoFor(this, aPt - aBuilder->ToReferenceFrame(mFrame));
return PR_TRUE;
DisplayDebugInfoFor(this, rectCenter - aBuilder->ToReferenceFrame(mFrame));
aOutFrames->AppendElement(this);
}
virtual void Paint(nsDisplayListBuilder* aBuilder
nsIRenderingContext* aCtx);
@ -2136,31 +2137,38 @@ public:
nsDisplayXULEventRedirector(nsIFrame* aFrame, nsDisplayList* aList,
nsIFrame* aTargetFrame)
: nsDisplayWrapList(aFrame, aList), mTargetFrame(aTargetFrame) {}
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
NS_DISPLAY_DECL_NAME("XULEventRedirector")
private:
nsIFrame* mTargetFrame;
};
nsIFrame* nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt, HitTestState* aState)
void nsDisplayXULEventRedirector::HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
nsIFrame* frame = mList.HitTest(aBuilder, aPt, aState);
if (!frame)
return nsnull;
nsTArray<nsIFrame*> outFrames;
mList.HitTest(aBuilder, aRect, aState, &outFrames);
for (nsIContent* content = frame->GetContent();
content && content != mTargetFrame->GetContent();
content = content->GetParent()) {
if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
nsGkAtoms::_true, eCaseMatters)) {
// Events are allowed on 'frame', so let it go.
return frame;
PRInt32 originalLength = aOutFrames->Length();
for (PRUint32 i = 0; i < originalLength; i++) {
for (nsIContent* content = outFrames.ElementAt(i)->GetContent();
content && content != mTargetFrame->GetContent();
content = content->GetParent()) {
if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
nsGkAtoms::_true, eCaseMatters)) {
// Events are allowed on 'frame', so let it go.
aOutFrames->AppendElement(outFrames.ElementAt(i));
}
}
}
// If no hits were found, treat it as a hit on the target frame itself
if (aOutFrames->Length() == originalLength) {
aOutFrames->AppendElement(mTargetFrame);
}
// Treat it as a hit on the target frame itself.
return mTargetFrame;
}
class nsXULEventRedirectorWrapper : public nsDisplayWrapper

View File

@ -116,8 +116,10 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState) { return mFrame; }
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
aOutFrames->AppendElement(mFrame);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("XULGroupBackground")

View File

@ -99,24 +99,25 @@ public:
}
#endif
virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt,
HitTestState* aState);
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget")
};
nsIFrame*
nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder,
nsPoint aPt, HitTestState* aState)
void
nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
nsPoint pt = aPt - aBuilder->ToReferenceFrame(mFrame);
// If we are in either the first 4 pixels or the last 4 pixels, we're going to
nsRect rect = aRect - aBuilder->ToReferenceFrame(mFrame);
// If we are in either in the first 4 pixels or the last 4 pixels, we're going to
// do something really strange. Check for an adjacent splitter.
PRBool left = PR_FALSE;
PRBool right = PR_FALSE;
if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= pt.x)
if (mFrame->GetSize().width - nsPresContext::CSSPixelsToAppUnits(4) <= rect.XMost()) {
right = PR_TRUE;
else if (nsPresContext::CSSPixelsToAppUnits(4) > pt.x)
} else if (nsPresContext::CSSPixelsToAppUnits(4) > rect.x) {
left = PR_TRUE;
}
// Swap left and right for RTL trees in order to find the correct splitter
if (mFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
@ -135,11 +136,10 @@ nsDisplayXULTreeColSplitterTarget::HitTest(nsDisplayListBuilder* aBuilder,
if (child && child->GetContent()->NodeInfo()->Equals(nsGkAtoms::splitter,
kNameSpaceID_XUL)) {
return child;
aOutFrames->AppendElement(child);
}
}
return nsnull;
}
nsresult