From 60903ce73c43b54050bab2f0fccea58637bad466 Mon Sep 17 00:00:00 2001 From: "roc+%cs.cmu.edu" Date: Sun, 4 Sep 2005 20:04:23 +0000 Subject: [PATCH] Bug 306222. Make nsIFrame::GetContentAndOffsetsFromPoint, and nsIFrameSelection::HandleDrag, take coordinates relative to the current frame, not some random view. r+sr=roc,patch by Eli Friedman --- content/events/src/nsDOMUIEvent.cpp | 4 +- layout/base/nsIFrameSelection.h | 2 +- layout/generic/nsBlockFrame.cpp | 6 ++- layout/generic/nsFrame.cpp | 83 +++++++++-------------------- layout/generic/nsGfxScrollFrame.cpp | 19 ------- layout/generic/nsGfxScrollFrame.h | 29 ---------- layout/generic/nsIFrame.h | 3 ++ layout/generic/nsTextFrame.cpp | 36 +++++-------- 8 files changed, 49 insertions(+), 133 deletions(-) diff --git a/content/events/src/nsDOMUIEvent.cpp b/content/events/src/nsDOMUIEvent.cpp index 471348e3d97d..fdc9f43fcefc 100644 --- a/content/events/src/nsDOMUIEvent.cpp +++ b/content/events/src/nsDOMUIEvent.cpp @@ -326,7 +326,7 @@ nsDOMUIEvent::GetRangeParent(nsIDOMNode** aRangeParent) nsCOMPtr parent; PRInt32 offset, endOffset; PRBool beginOfContent; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(mEvent, + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, targetFrame); if (NS_SUCCEEDED(targetFrame->GetContentAndOffsetsFromPoint(mPresContext, pt, @@ -357,7 +357,7 @@ nsDOMUIEvent::GetRangeOffset(PRInt32* aRangeOffset) nsIContent* parent = nsnull; PRInt32 endOffset; PRBool beginOfContent; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(mEvent, + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, targetFrame); if (NS_SUCCEEDED(targetFrame->GetContentAndOffsetsFromPoint(mPresContext, pt, diff --git a/layout/base/nsIFrameSelection.h b/layout/base/nsIFrameSelection.h index 6a1489bcc724..f237d3788485 100644 --- a/layout/base/nsIFrameSelection.h +++ b/layout/base/nsIFrameSelection.h @@ -190,7 +190,7 @@ public: /** HandleDrag extends the selection to contain the frame closest to aPoint. * @param aPresContext is the context to use when figuring out what frame contains the point. * @param aFrame is the parent of all frames to use when searching for the closest frame to the point. - * @param aPoint is relative to aFrame's parent view. + * @param aPoint is relative to aFrame */ NS_IMETHOD HandleDrag(nsPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint) = 0; diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index eaa6e4ee02ed..4feadbb47de3 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -6588,11 +6588,15 @@ nsBlockFrame::HandleEvent(nsPresContext* aPresContext, if (NS_FAILED(result = GetClosestLine(it, pt, closestLine))) return result; + // XXX mDesiredX needs to be in GetOffsetFromView coords + nsPoint offset; + nsIView* view; + mainframe->GetOffsetFromView(offset, &view); //we will now ask where to go. if we cant find what we want"aka another block frame" //we drill down again pos.mShell = shell; pos.mDirection = eDirNext; - pos.mDesiredX = pt.x; + pos.mDesiredX = pt.x + offset.x; pos.mScrollViewStop = PR_FALSE; pos.mIsKeyboardSelect = PR_FALSE; result = nsFrame::GetNextPrevLineFromeBlockFrame(aPresContext, diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 197f868b626e..71ded9ff9bd1 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1361,7 +1361,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext, PRInt32 startOffset = 0, endOffset = 0; PRBool beginFrameContent = PR_FALSE; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this); + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); rv = GetContentAndOffsetsFromPoint(aPresContext, pt, getter_AddRefs(content), startOffset, endOffset, beginFrameContent); @@ -1601,7 +1601,7 @@ nsFrame::HandleMultiplePress(nsPresContext* aPresContext, nsCOMPtr newContent; PRBool beginContent = PR_FALSE; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this); + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); rv = GetContentAndOffsetsFromPoint(aPresContext, pt, @@ -1753,7 +1753,7 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext, if (NS_SUCCEEDED(result) && parentContent) { frameselection->HandleTableSelection(parentContent, contentOffset, target, me); } else { - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this); + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); frameselection->HandleDrag(aPresContext, this, pt); } @@ -1850,8 +1850,7 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext, PRInt32 startOffset = 0, endOffset = 0; PRBool beginFrameContent = PR_FALSE; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(me, - this); + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(me, this); result = GetContentAndOffsetsFromPoint(aPresContext, pt, getter_AddRefs(content), startOffset, endOffset, @@ -1919,7 +1918,6 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, // to if it fails the getposition call, make it yourself also only // look at primary list nsIFrame *closestFrame = nsnull; - nsIView *view = GetClosestView(); nsIFrame *kid = GetFirstChild(nsnull); if (kid) { @@ -1934,30 +1932,6 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, // that don't have a proper parent-child relationship! PRBool skipThisKid = (kid->GetStateBits() & NS_FRAME_GENERATED_CONTENT) != 0; -#if 0 - if (!skipThisKid) { - // The frame's content is not generated. Now check - // if it is anonymous content! - - nsIContent* kidContent = kid->GetContent(); - if (kidContent) { - nsCOMPtr content = kidContent->GetParent(); - - if (content) { - PRInt32 kidCount = content->ChildCount(); - PRInt32 kidIndex = content->IndexOf(kidContent); - - // IndexOf() should return -1 for the index if it doesn't - // find kidContent in it's child list. - - if (kidIndex < 0 || kidIndex >= kidCount) { - // Must be anonymous content! So skip it! - skipThisKid = PR_TRUE; - } - } - } - } -#endif //XXX we USED to skip anonymous content i dont think we should anymore leaving this here as a flah if (skipThisKid) { kid = kid->GetNextSibling(); @@ -1968,13 +1942,7 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, // relationship. Now see if the aPoint inside it's bounding // rect or close by. - nsPoint offsetPoint(0,0); - nsIView * kidView = nsnull; - kid->GetOffsetFromView(offsetPoint, &kidView); - nsRect rect = kid->GetRect(); - rect.x = offsetPoint.x; - rect.y = offsetPoint.y; nscoord fromTop = aPoint.y - rect.y; nscoord fromBottom = aPoint.y - rect.y - rect.height; @@ -2030,29 +1998,18 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, // the coordinates because GetPosition() expects // them to be relative to the closest view. - nsPoint newPoint = aPoint; - nsIView *closestView = closestFrame->GetClosestView(); - - if (closestView && view != closestView) - newPoint -= closestView->GetOffsetTo(view); - - // printf(" 0x%.8x 0x%.8x %4d %4d\n", - // closestFrame, closestView, closestXDistance, closestYDistance); - - return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent, - aContentOffset, aContentOffsetEnd,aBeginFrameContent); + nsPoint newPoint = aPoint - closestFrame->GetOffsetTo(this); + return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, + aNewContent, + aContentOffset, + aContentOffsetEnd, + aBeginFrameContent); } } if (!mContent) return NS_ERROR_NULL_POINTER; - nsPoint offsetPoint; - GetOffsetFromView(offsetPoint, &view); - nsRect thisRect = GetRect(); - thisRect.x = offsetPoint.x; - thisRect.y = offsetPoint.y; - NS_IF_ADDREF(*aNewContent = mContent->GetParent()); if (*aNewContent){ @@ -2066,6 +2023,7 @@ nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX, aContentOffset = contentOffset; //its clear save the result aBeginFrameContent = PR_TRUE; + nsRect thisRect(nsPoint(0, 0), GetSize()); if (thisRect.Contains(aPoint)) aContentOffsetEnd = aContentOffset +1; else @@ -3336,12 +3294,16 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, rect = resultFrame->GetRect(); if (!rect.width || !rect.height) result = NS_ERROR_FAILURE; - else - result = resultFrame->GetContentAndOffsetsFromPoint(context,point, + else { + nsIView* view; + nsPoint offset; + resultFrame->GetOffsetFromView(offset, &view); + result = resultFrame->GetContentAndOffsetsFromPoint(context,point - offset, getter_AddRefs(aPos->mResultContent), aPos->mContentOffset, aPos->mContentOffsetEnd, aPos->mPreferLeft); + } if (NS_SUCCEEDED(result)) { PRBool selectable; @@ -3381,7 +3343,10 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext, point.x = aPos->mDesiredX; point.y = 0; - result = resultFrame->GetContentAndOffsetsFromPoint(context,point, + nsIView* view; + nsPoint offset; + resultFrame->GetOffsetFromView(offset, &view); + result = resultFrame->GetContentAndOffsetsFromPoint(context,point - offset, getter_AddRefs(aPos->mResultContent), aPos->mContentOffset, aPos->mContentOffsetEnd, aPos->mPreferLeft); if (NS_SUCCEEDED(result)) @@ -3679,7 +3644,6 @@ DrillDownToEndOfLine(nsIFrame* aFrame, PRInt32 aLineFrameCount, return NS_OK; } - NS_IMETHODIMP nsFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos) { @@ -3726,7 +3690,10 @@ nsFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos) nsPresContext *context = aPos->mShell->GetPresContext(); if (!context) return NS_OK; - result = GetContentAndOffsetsFromPoint(context,point, + nsIView* view; + nsPoint offset; + GetOffsetFromView(offset, &view); + result = GetContentAndOffsetsFromPoint(context,point - offset, getter_AddRefs(aPos->mResultContent), aPos->mContentOffset, endoffset, diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index e9e14bfc4813..5618593e0c9a 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1406,25 +1406,6 @@ nsGfxScrollFrameInner::NeedsClipWidget() const return PR_TRUE; } -nsresult -nsGfxScrollFrameInner::GetChildContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) -{ - // We need to overrride this to ensure that scrollbars are ignored - - // Since we definitely have a view, aPoint is relative to this frame's view. We - // need to make it relative to the scrolled frame. - nsPoint point = aPoint - mScrollableView->View()->GetOffsetTo(mOuter->GetView()); - - return mScrolledFrame->GetContentAndOffsetsFromPoint(aCX, point, aNewContent, - aContentOffset, aContentOffsetEnd, - aBeginFrameContent); -} - void nsGfxScrollFrameInner::CreateScrollableView() { diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 9bf03dba5f04..738d191eeeea 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -80,13 +80,6 @@ public: void PostScrollPortEvent(PRBool aOverflow, nsScrollPortEvent::orientType aType); void PostOverflowEvents(); - nsresult GetChildContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent); - // nsIScrollPositionListener NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY); @@ -235,17 +228,6 @@ public: NS_IMETHOD RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame); - - NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) { - return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, - aContentOffsetEnd, aBeginFrameContent); - } - virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const { return mInner.GetParentViewForChildFrame(aFrame); } @@ -381,17 +363,6 @@ public: NS_IMETHOD RemoveFrame(nsIAtom* aListName, nsIFrame* aOldFrame); - - NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX, - const nsPoint& aPoint, - nsIContent ** aNewContent, - PRInt32& aContentOffset, - PRInt32& aContentOffsetEnd, - PRBool& aBeginFrameContent) { - return mInner.GetChildContentAndOffsetsFromPoint(aCX, aPoint, aNewContent, aContentOffset, - aContentOffsetEnd, aBeginFrameContent); - } - virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const { return mInner.GetParentViewForChildFrame(aFrame); } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index f1b792562688..348434239fa2 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -751,6 +751,9 @@ public: nsEvent* aEvent, nsIContent** aContent) = 0; + /** + * Find the content offset from a point. aPoint is in frame coordinates. + */ NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX, const nsPoint& aPoint, nsIContent ** aNewContent, diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 4b64fbb69622..b8d68b9aed49 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -2762,9 +2762,6 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext, if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing && !ts.mJustifying) { return NS_ERROR_INVALID_ARG; } - nsIView * view; - nsPoint origin; - GetOffsetFromView(origin, &view); /* This if clause is the cause of much pain. If aNewContent is set, then any * code path that returns an error must set aNewContent to null before returning, @@ -2782,7 +2779,7 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext, * If this clause is removed, then some of the bullet-proofing code * prefaced with "bug 56704" comments can be removed as well. */ - if (aPoint.x - origin.x < 0) + if (aPoint.x < 0) { *aNewContent = mContent; aOffset =0; @@ -2839,12 +2836,12 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext, if (prefInt) { - if (aPoint.y < origin.y)//above rectangle + if (aPoint.y < 0)//above rectangle { aOffset = mContentOffset; outofstylehandled = PR_TRUE; } - else if ((aPoint.y - origin.y) > mRect.height) + else if (aPoint.y > mRect.height) { aOffset = mContentOffset + mContentLength; outofstylehandled = PR_TRUE; @@ -2855,7 +2852,7 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext, //END STYLE RULE { //the following will first get the index into the PAINTBUFFER then the actual content - nscoord adjustedX = PR_MAX(0,aPoint.x-origin.x); + nscoord adjustedX = PR_MAX(0,aPoint.x); #ifdef IBMBIDI if (isOddLevel) @@ -3818,10 +3815,6 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext, return NS_ERROR_FAILURE; } - nsPoint origin; - nsIView * view; - GetOffsetFromView(origin, &view); - //IF STYLE SAYS TO SELECT TO END OF FRAME HERE... PRInt32 prefInt = nsContentUtils::GetIntPref("browser.drag_out_of_frame_style"); @@ -3829,13 +3822,13 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext, if (prefInt) { - if ((aPoint.y - origin.y) < 0)//above rectangle + if (aPoint.y < 0)//above rectangle { aContentOffset = mContentOffset; aContentOffsetEnd = aContentOffset; outofstylehandled = PR_TRUE; } - else if ((aPoint.y - origin.y) > mRect.height) + else if (aPoint.y > mRect.height) { aContentOffset = mContentOffset + mContentLength; aContentOffsetEnd = aContentOffset; @@ -3857,24 +3850,21 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext, rendContext->GetHints(clusterHint); clusterHint &= NS_RENDERING_HINT_TEXT_CLUSTERS; if (clusterHint) { - nsPoint pt; - pt.x = aPoint.x - origin.x; - pt.y = aPoint.y - origin.y; - indx = rendContext->GetPosition(text, textLength, pt); + indx = rendContext->GetPosition(text, textLength, aPoint); } else { #ifdef IBMBIDI PRBool getReversedPos = NS_GET_EMBEDDING_LEVEL(this) & 1; nscoord posX = (getReversedPos) ? - (mRect.width + origin.x) - (aPoint.x - origin.x) : aPoint.x; + (mRect.width) - (aPoint.x) : aPoint.x; - PRBool found = BinarySearchForPosition(rendContext, text, origin.x, 0, 0, + PRBool found = BinarySearchForPosition(rendContext, text, 0, 0, 0, PRInt32(textLength), PRInt32(posX) , //go to local coordinates indx, textWidth); #else - PRBool found = BinarySearchForPosition(rendContext, text, origin.x, 0, 0, + PRBool found = BinarySearchForPosition(rendContext, text, 0, 0, 0, PRInt32(textLength), PRInt32(aPoint.x) , //go to local coordinates indx, textWidth); @@ -3889,13 +3879,13 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext, #ifdef IBMBIDI if (getReversedPos) { - if (mRect.width - aPoint.x + origin.x > textWidth+charWidth ) { + if (mRect.width - aPoint.x> textWidth+charWidth ) { indx++; } } else #endif // IBMBIDI - if ((aPoint.x - origin.x) > textWidth+charWidth) { + if ((aPoint.x) > textWidth+charWidth) { indx++; } } @@ -4851,7 +4841,7 @@ nsTextFrame::HandleMultiplePress(nsPresContext* aPresContext, PRInt32 startPos = 0; PRInt32 contentOffsetEnd = 0; nsCOMPtr newContent; - nsPoint pt = nsLayoutUtils::GetEventCoordinatesForNearestView(aEvent, this); + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); nsresult rv = GetPosition(aPresContext, pt, getter_AddRefs(newContent), startPos, contentOffsetEnd);