Fix for bug 83650 (textarea control has problems with caret positioning at end)

and bug 97207 (textarea pastes sometimes misplaced by failing to reposition).

  - Added new utility method GetOriginToViewOffset().

  - Modified nsPresShell::HandleEvent(), nsBoxFrame::GetFrameForPoint(),
    and nsContainerFrame::GetFrameForPointUsing() to factor in the
    offset from GetOriginToViewOffset() to insure that the point
    used is always transformed into the correct coordinate system.

Files modified:

    mozilla/layout/base/public/nsIFrame.h
    mozilla/layout/html/base/src/nsContainerFrame.cpp
    mozilla/layout/html/base/src/nsFrame.cpp
    mozilla/layout/html/base/src/nsFrame.h
    mozilla/layout/html/base/src/nsPresShell.cpp
    mozilla/layout/xul/base/src/nsBoxFrame.cpp

r=kmcclusk@netscape.com  sr=sfraser@netscape.com
This commit is contained in:
kin%netscape.com 2002-02-07 22:39:15 +00:00
parent ef530159bd
commit d38cee3cd4
11 changed files with 198 additions and 11 deletions

View File

@ -5880,13 +5880,27 @@ PresShell::HandleEvent(nsIView *aView,
}
}
else {
// This is because we want to give the point in the same
// coordinates as the frame's own Rect, so mRect.Contains(aPoint)
// works. However, this point is relative to the frame's rect, so
// we need to add on the origin of the rect.
// aEvent->point is relative to aView's upper left corner. We need
// a point that is in the same coordinate system as frame's rect
// so that the frame->mRect.Contains(aPoint) calls in
// GetFrameForPoint() work. The assumption here is that frame->GetView()
// will return aView, and frame's parent view is aView's parent.
nsPoint eventPoint;
frame->GetOrigin(eventPoint);
eventPoint += aEvent->point;
nsPoint originOffset;
nsIView *view = nsnull;
frame->GetOriginToViewOffset(mPresContext, originOffset, &view);
#ifdef DEBUG_kin
NS_ASSERTION(view == aView, "view != aView");
#endif // DEBUG_kin
if (view == aView)
eventPoint -= originOffset;
rv = frame->GetFrameForPoint(mPresContext, eventPoint, NS_FRAME_PAINT_LAYER_FOREGROUND, &mCurrentEventFrame);
if (rv != NS_OK) {
rv = frame->GetFrameForPoint(mPresContext, eventPoint, NS_FRAME_PAINT_LAYER_FLOATERS, &mCurrentEventFrame);

View File

@ -961,6 +961,18 @@ public:
nsPoint& aOffset,
nsIView** aView) const = 0;
/**
* Returns the offset from this frame's upper left corner to the upper
* left corner of the view returned by a call to GetView(). aOffset
* will contain the offset to the view or (0,0) if the frame has no
* view. aView will contain a pointer to the view returned by GetView().
* aView is optional, that is, you may pass null if you are not interested
* in getting a pointer to the view.
*/
NS_IMETHOD GetOriginToViewOffset(nsIPresContext* aPresContext,
nsPoint& aOffset,
nsIView** aView) const = 0;
/**
* Returns the window that contains this frame. If this frame has a
* view and the view has a window, then this frames window is

View File

@ -293,8 +293,16 @@ nsContainerFrame::GetFrameForPointUsing(nsIPresContext* aPresContext,
FirstChild(aPresContext, aList, &kid);
*aFrame = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
nsPoint originOffset;
nsIView *view = nsnull;
nsresult rv = GetOriginToViewOffset(aPresContext, originOffset, &view);
if (NS_SUCCEEDED(rv) && view)
tmp += originOffset;
while (nsnull != kid) {
nsresult rv = kid->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
rv = kid->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
if (NS_SUCCEEDED(rv) && hit) {
*aFrame = hit;

View File

@ -2042,6 +2042,62 @@ NS_IMETHODIMP nsFrame::GetOffsetFromView(nsIPresContext* aPresContext,
return NS_OK;
}
// The (x,y) value of the frame's upper left corner is always
// relative to its parentFrame's upper left corner, unless
// its parentFrame has a view associated with it, in which case, it
// will be relative to the upper left corner of the view returned
// by a call to parentFrame->GetView().
//
// This means that while drilling down the frame hierarchy, from
// parent to child frame, we sometimes need to take into account
// crossing these view boundaries, because the coordinate system
// changes from parent frame coordinate system, to the associated
// view's coordinate system.
//
// GetOriginToViewOffset() is a utility method that returns the
// offset necessary to map a point, relative to the frame's upper
// left corner, into the coordinate system of the view associated
// with the frame.
//
// If there is no view associated with the frame, the offset
// returned will always be (0,0).
NS_IMETHODIMP nsFrame::GetOriginToViewOffset(nsIPresContext* aPresContext,
nsPoint& aOffset,
nsIView** aView) const
{
NS_ENSURE_ARG_POINTER(aPresContext);
aOffset.MoveTo(0,0);
if (aView)
*aView = nsnull;
nsIView *view = nsnull;
nsresult rv = GetView(aPresContext, &view);
if (NS_SUCCEEDED(rv) && view) {
nsIView *parentView = nsnull;
nsPoint offsetToParentView;
rv = GetOffsetFromView(aPresContext, offsetToParentView, &parentView);
if (NS_SUCCEEDED(rv)) {
nsPoint viewPos;
rv = view->GetPosition(&viewPos.x, &viewPos.y);
if (NS_SUCCEEDED(rv)) {
aOffset = offsetToParentView - viewPos;
if (aView)
*aView = view;
}
}
}
return rv;
}
NS_IMETHODIMP nsFrame::GetWindow(nsIPresContext* aPresContext,
nsIWidget** aWindow) const
{

View File

@ -249,6 +249,7 @@ public:
NS_IMETHOD SetView(nsIPresContext* aPresContext, nsIView* aView);
NS_IMETHOD GetParentWithView(nsIPresContext* aPresContext, nsIFrame** aParent) const;
NS_IMETHOD GetOffsetFromView(nsIPresContext* aPresContext, nsPoint& aOffset, nsIView** aView) const;
NS_IMETHOD GetOriginToViewOffset(nsIPresContext *aPresContext, nsPoint& aOffset, nsIView **aView) const;
NS_IMETHOD GetWindow(nsIPresContext* aPresContext, nsIWidget**) const;
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;

View File

@ -961,6 +961,18 @@ public:
nsPoint& aOffset,
nsIView** aView) const = 0;
/**
* Returns the offset from this frame's upper left corner to the upper
* left corner of the view returned by a call to GetView(). aOffset
* will contain the offset to the view or (0,0) if the frame has no
* view. aView will contain a pointer to the view returned by GetView().
* aView is optional, that is, you may pass null if you are not interested
* in getting a pointer to the view.
*/
NS_IMETHOD GetOriginToViewOffset(nsIPresContext* aPresContext,
nsPoint& aOffset,
nsIView** aView) const = 0;
/**
* Returns the window that contains this frame. If this frame has a
* view and the view has a window, then this frames window is

View File

@ -293,8 +293,16 @@ nsContainerFrame::GetFrameForPointUsing(nsIPresContext* aPresContext,
FirstChild(aPresContext, aList, &kid);
*aFrame = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
nsPoint originOffset;
nsIView *view = nsnull;
nsresult rv = GetOriginToViewOffset(aPresContext, originOffset, &view);
if (NS_SUCCEEDED(rv) && view)
tmp += originOffset;
while (nsnull != kid) {
nsresult rv = kid->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
rv = kid->GetFrameForPoint(aPresContext, tmp, aWhichLayer, &hit);
if (NS_SUCCEEDED(rv) && hit) {
*aFrame = hit;

View File

@ -2042,6 +2042,62 @@ NS_IMETHODIMP nsFrame::GetOffsetFromView(nsIPresContext* aPresContext,
return NS_OK;
}
// The (x,y) value of the frame's upper left corner is always
// relative to its parentFrame's upper left corner, unless
// its parentFrame has a view associated with it, in which case, it
// will be relative to the upper left corner of the view returned
// by a call to parentFrame->GetView().
//
// This means that while drilling down the frame hierarchy, from
// parent to child frame, we sometimes need to take into account
// crossing these view boundaries, because the coordinate system
// changes from parent frame coordinate system, to the associated
// view's coordinate system.
//
// GetOriginToViewOffset() is a utility method that returns the
// offset necessary to map a point, relative to the frame's upper
// left corner, into the coordinate system of the view associated
// with the frame.
//
// If there is no view associated with the frame, the offset
// returned will always be (0,0).
NS_IMETHODIMP nsFrame::GetOriginToViewOffset(nsIPresContext* aPresContext,
nsPoint& aOffset,
nsIView** aView) const
{
NS_ENSURE_ARG_POINTER(aPresContext);
aOffset.MoveTo(0,0);
if (aView)
*aView = nsnull;
nsIView *view = nsnull;
nsresult rv = GetView(aPresContext, &view);
if (NS_SUCCEEDED(rv) && view) {
nsIView *parentView = nsnull;
nsPoint offsetToParentView;
rv = GetOffsetFromView(aPresContext, offsetToParentView, &parentView);
if (NS_SUCCEEDED(rv)) {
nsPoint viewPos;
rv = view->GetPosition(&viewPos.x, &viewPos.y);
if (NS_SUCCEEDED(rv)) {
aOffset = offsetToParentView - viewPos;
if (aView)
*aView = view;
}
}
}
return rv;
}
NS_IMETHODIMP nsFrame::GetWindow(nsIPresContext* aPresContext,
nsIWidget** aWindow) const
{

View File

@ -249,6 +249,7 @@ public:
NS_IMETHOD SetView(nsIPresContext* aPresContext, nsIView* aView);
NS_IMETHOD GetParentWithView(nsIPresContext* aPresContext, nsIFrame** aParent) const;
NS_IMETHOD GetOffsetFromView(nsIPresContext* aPresContext, nsPoint& aOffset, nsIView** aView) const;
NS_IMETHOD GetOriginToViewOffset(nsIPresContext *aPresContext, nsPoint& aOffset, nsIView **aView) const;
NS_IMETHOD GetWindow(nsIPresContext* aPresContext, nsIWidget**) const;
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;

View File

@ -5880,13 +5880,27 @@ PresShell::HandleEvent(nsIView *aView,
}
}
else {
// This is because we want to give the point in the same
// coordinates as the frame's own Rect, so mRect.Contains(aPoint)
// works. However, this point is relative to the frame's rect, so
// we need to add on the origin of the rect.
// aEvent->point is relative to aView's upper left corner. We need
// a point that is in the same coordinate system as frame's rect
// so that the frame->mRect.Contains(aPoint) calls in
// GetFrameForPoint() work. The assumption here is that frame->GetView()
// will return aView, and frame's parent view is aView's parent.
nsPoint eventPoint;
frame->GetOrigin(eventPoint);
eventPoint += aEvent->point;
nsPoint originOffset;
nsIView *view = nsnull;
frame->GetOriginToViewOffset(mPresContext, originOffset, &view);
#ifdef DEBUG_kin
NS_ASSERTION(view == aView, "view != aView");
#endif // DEBUG_kin
if (view == aView)
eventPoint -= originOffset;
rv = frame->GetFrameForPoint(mPresContext, eventPoint, NS_FRAME_PAINT_LAYER_FOREGROUND, &mCurrentEventFrame);
if (rv != NS_OK) {
rv = frame->GetFrameForPoint(mPresContext, eventPoint, NS_FRAME_PAINT_LAYER_FLOATERS, &mCurrentEventFrame);

View File

@ -1977,7 +1977,8 @@ nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext,
return NS_ERROR_FAILURE;
nsIView* view = nsnull;
GetView(aPresContext, &view);
nsPoint originOffset;
GetOriginToViewOffset(aPresContext, originOffset, &view);
// get the debug frame.
if (view || (mState & NS_STATE_IS_ROOT))
@ -2002,6 +2003,10 @@ nsBoxFrame::GetFrameForPoint(nsIPresContext* aPresContext,
FirstChild(aPresContext, nsnull, &kid);
*aFrame = nsnull;
tmp.MoveTo(aPoint.x - mRect.x, aPoint.y - mRect.y);
if (view)
tmp += originOffset;
while (nsnull != kid) {
// have we hit a child before
PRBool haveKid = (hit != nsnull);