First pass implementation of selection auto scrolling.
layout/base/public/nsIFrame.h
- Added GetContentAndOffsetsFromPoint() method. This
method will eventually replace GetPosition().
layout/base/public/nsIFrameSelection.h
- Added HandleDrag() and Start/StopAutoScrollTimer() methods.
layout/base/src/nsRangeList.cpp
- Added implementation for HandleDrag() and
Start/StopAutoScrollTimer() methods.
layout/html/base/src/nsBRFrame.cpp
- Added implementation for GetContentAndOffsetsFromPoint().
layout/html/base/src/nsFrame.cpp
layout/html/base/src/nsFrame.h
- Added implementation for GetContentAndOffsetsFromPoint().
- Added GetClosestViewForFrame() utility method.
- Modified HandleEvent() to call HandleRelease() which now
stops the auto scrolling timers.
- Modified HandleDrag() to call nsIFrameSelection's HandleDrag()
and Start/StopAutoScrollTimer() methods.
layout/html/base/src/nsTextFrame.cpp
- Added implementation for GetContentAndOffsetsFromPoint().
git-svn-id: svn://10.0.0.236/trunk@49313 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
cf2257de2a
commit
1806b9519b
@ -136,6 +136,27 @@ public:
|
||||
NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset ,
|
||||
PRBool aContinueSelection, PRBool aMultipleSelection) = 0;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
NS_IMETHOD HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint) = 0;
|
||||
|
||||
/** StartAutoScrollTimer is responsible for scrolling the view so that aPoint is always
|
||||
* visible, and for selecting any frame that contains aPoint. The timer will also reset
|
||||
* itself to fire again if the view has not scrolled to the end of the document.
|
||||
* @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 aDelay is the timer's interval.
|
||||
*/
|
||||
NS_IMETHOD StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay) = 0;
|
||||
|
||||
/** StopAutoScrollTimer stops any active auto scroll timer.
|
||||
*/
|
||||
NS_IMETHOD StopAutoScrollTimer() = 0;
|
||||
|
||||
/** EnableFrameNotification
|
||||
* mutch like start batching, except all dirty calls are ignored. no notifications will go
|
||||
* out until enableNotifications with a PR_TRUE is called
|
||||
|
||||
@ -457,6 +457,12 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd) = 0;
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Get the cursor for a given frame.
|
||||
|
||||
@ -136,6 +136,27 @@ public:
|
||||
NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset ,
|
||||
PRBool aContinueSelection, PRBool aMultipleSelection) = 0;
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
NS_IMETHOD HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint) = 0;
|
||||
|
||||
/** StartAutoScrollTimer is responsible for scrolling the view so that aPoint is always
|
||||
* visible, and for selecting any frame that contains aPoint. The timer will also reset
|
||||
* itself to fire again if the view has not scrolled to the end of the document.
|
||||
* @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 aDelay is the timer's interval.
|
||||
*/
|
||||
NS_IMETHOD StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay) = 0;
|
||||
|
||||
/** StopAutoScrollTimer stops any active auto scroll timer.
|
||||
*/
|
||||
NS_IMETHOD StopAutoScrollTimer() = 0;
|
||||
|
||||
/** EnableFrameNotification
|
||||
* mutch like start batching, except all dirty calls are ignored. no notifications will go
|
||||
* out until enableNotifications with a PR_TRUE is called
|
||||
|
||||
@ -51,6 +51,8 @@
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsITimerCallback.h"
|
||||
|
||||
#define STATUS_CHECK_RETURN_MACRO() {if (!mTracker) return NS_ERROR_FAILURE;}
|
||||
|
||||
@ -79,6 +81,7 @@ static void printRange(nsIDOMRange *aDomRange);
|
||||
|
||||
class nsRangeListIterator;
|
||||
class nsRangeList;
|
||||
class nsAutoScrollTimer;
|
||||
|
||||
class nsDOMSelection : public nsIDOMSelection , public nsIScriptObjectOwner
|
||||
{
|
||||
@ -159,6 +162,10 @@ public:
|
||||
SelectionDetails **aReturnDetails, SelectionType aType);
|
||||
NS_IMETHOD Repaint();
|
||||
|
||||
nsresult StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay);
|
||||
nsresult StopAutoScrollTimer();
|
||||
nsresult DoAutoScroll(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint);
|
||||
|
||||
private:
|
||||
friend class nsRangeListIterator;
|
||||
|
||||
@ -182,6 +189,8 @@ private:
|
||||
|
||||
// for nsIScriptContextOwner
|
||||
void* mScriptObject;
|
||||
|
||||
nsAutoScrollTimer *mAutoScrollTimer; // timer for autoscrolling.
|
||||
};
|
||||
|
||||
|
||||
@ -200,6 +209,9 @@ public:
|
||||
NS_IMETHOD HandleKeyEvent(nsGUIEvent *aGuiEvent);
|
||||
NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset,
|
||||
PRBool aContinueSelection, PRBool aMultipleSelection);
|
||||
NS_IMETHOD HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint);
|
||||
NS_IMETHOD StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay);
|
||||
NS_IMETHOD StopAutoScrollTimer();
|
||||
NS_IMETHOD EnableFrameNotification(PRBool aEnable){mNotifyFrames = aEnable; return NS_OK;}
|
||||
NS_IMETHOD LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength,
|
||||
SelectionDetails **aReturnDetails);
|
||||
@ -295,8 +307,108 @@ private:
|
||||
SelectionType mType;
|
||||
};
|
||||
|
||||
class nsAutoScrollTimer : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsAutoScrollTimer()
|
||||
: mSelection(0), mTimer(0), mFrame(0), mPresContext(0), mPoint(0,0), mDelay(30)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
~nsAutoScrollTimer()
|
||||
{
|
||||
if (mTimer)
|
||||
{
|
||||
mTimer->Cancel();
|
||||
NS_RELEASE(mTimer);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Start(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint)
|
||||
{
|
||||
mFrame = aFrame;
|
||||
mPresContext = aPresContext;
|
||||
mPoint = aPoint;
|
||||
|
||||
if (!mTimer)
|
||||
{
|
||||
nsresult result = NS_NewTimer(&mTimer);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
|
||||
return mTimer->Init(this, mDelay);
|
||||
}
|
||||
|
||||
nsresult Stop()
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
if (mTimer)
|
||||
{
|
||||
mTimer->Cancel();
|
||||
NS_RELEASE(mTimer);
|
||||
mTimer = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult Init(nsRangeList *aRangeList, nsDOMSelection *aSelection)
|
||||
{
|
||||
mRangeList = aRangeList;
|
||||
mSelection = aSelection;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult SetDelay(PRUint32 aDelay)
|
||||
{
|
||||
mDelay = aDelay;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void Notify(nsITimer *timer)
|
||||
{
|
||||
if (mSelection && mPresContext && mFrame)
|
||||
{
|
||||
mRangeList->HandleDrag(mPresContext, mFrame, mPoint);
|
||||
mSelection->DoAutoScroll(mPresContext, mFrame, mPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRangeList *mRangeList;
|
||||
nsDOMSelection *mSelection;
|
||||
nsITimer *mTimer;
|
||||
nsIFrame *mFrame;
|
||||
nsIPresContext *mPresContext;
|
||||
nsPoint mPoint;
|
||||
PRUint32 mDelay;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(nsAutoScrollTimer)
|
||||
NS_IMPL_RELEASE(nsAutoScrollTimer)
|
||||
NS_IMPL_QUERY_INTERFACE1(nsAutoScrollTimer, nsITimerCallback)
|
||||
|
||||
nsresult NS_NewAutoScrollTimer(nsAutoScrollTimer **aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aResult = (nsAutoScrollTimer*) new nsAutoScrollTimer;
|
||||
|
||||
if (!aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_NewRangeList(nsIFrameSelection **aRangeList);
|
||||
|
||||
@ -914,6 +1026,44 @@ nsRangeList::HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset,
|
||||
return TakeFocus(aNewFocus, aContentOffset, aContentEndOffset, aContinueSelection, aMultipleSelection);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRangeList::HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint)
|
||||
{
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
|
||||
result = aFrame->GetContentAndOffsetsFromPoint(*aPresContext, aPoint,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
result = HandleClick(newContent, startPos, contentOffsetEnd , PR_TRUE, PR_FALSE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRangeList::StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay)
|
||||
{
|
||||
return mDomSelections[SELECTION_NORMAL]->StartAutoScrollTimer(aPresContext, aFrame, aPoint, aDelay);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsRangeList::StopAutoScrollTimer()
|
||||
{
|
||||
return mDomSelections[SELECTION_NORMAL]->StopAutoScrollTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
hard to go from nodes to frames, easy the other way!
|
||||
*/
|
||||
@ -1266,6 +1416,7 @@ nsDOMSelection::nsDOMSelection(nsRangeList *aList)
|
||||
mDirection = eDirNext;
|
||||
NS_NewISupportsArray(getter_AddRefs(mRangeArray));
|
||||
mScriptObject = nsnull;
|
||||
mAutoScrollTimer = nsnull;
|
||||
NS_INIT_REFCNT();
|
||||
}
|
||||
|
||||
@ -1282,6 +1433,8 @@ nsDOMSelection::~nsDOMSelection()
|
||||
mRangeArray->RemoveElementAt(0);
|
||||
}
|
||||
setAnchorFocusRange(-1);
|
||||
|
||||
NS_IF_RELEASE(mAutoScrollTimer);
|
||||
}
|
||||
|
||||
|
||||
@ -1953,6 +2106,243 @@ nsDOMSelection::Repaint()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSelection::StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay)
|
||||
{
|
||||
nsresult result;
|
||||
|
||||
if (!mAutoScrollTimer)
|
||||
{
|
||||
result = NS_NewAutoScrollTimer(&mAutoScrollTimer);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (!mAutoScrollTimer)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
result = mAutoScrollTimer->Init(mRangeList, this);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mAutoScrollTimer->SetDelay(aDelay);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
return DoAutoScroll(aPresContext, aFrame, aPoint);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSelection::StopAutoScrollTimer()
|
||||
{
|
||||
if (mAutoScrollTimer)
|
||||
return mAutoScrollTimer->Stop();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMSelection::DoAutoScroll(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint)
|
||||
{
|
||||
nsresult result;
|
||||
|
||||
if (!aPresContext || !aFrame)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mAutoScrollTimer)
|
||||
result = mAutoScrollTimer->Stop();
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext->GetShell(getter_AddRefs(presShell));
|
||||
|
||||
//
|
||||
// Get a hold of the root scrollable view for presShell.
|
||||
//
|
||||
|
||||
nsCOMPtr<nsIViewManager> viewManager;
|
||||
|
||||
result = presShell->GetViewManager(getter_AddRefs(viewManager));
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (!viewManager)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsIScrollableView *scrollableView = 0;
|
||||
|
||||
result = viewManager->GetRootScrollableView(&scrollableView);
|
||||
|
||||
if (NS_SUCCEEDED(result) && scrollableView)
|
||||
{
|
||||
//
|
||||
// Get a hold of the scrollable view's clip view.
|
||||
//
|
||||
|
||||
const nsIView *cView = 0;
|
||||
|
||||
result = scrollableView->GetClipView(&cView);
|
||||
|
||||
if (NS_SUCCEEDED(result) && cView)
|
||||
{
|
||||
//
|
||||
// Find out if this frame's view is in the parent hierarchy of the clip view.
|
||||
// If it is, then we know the drag is happening outside of the clip view,
|
||||
// so we may need to auto scroll.
|
||||
//
|
||||
|
||||
// Get the frame's parent view.
|
||||
|
||||
nsPoint viewOffset(0,0);
|
||||
|
||||
nsIView *frameView = 0;
|
||||
|
||||
nsIFrame *parentFrame = aFrame;
|
||||
|
||||
while (NS_SUCCEEDED(result) && parentFrame && !frameView)
|
||||
{
|
||||
result = parentFrame->GetView(&frameView);
|
||||
if (NS_SUCCEEDED(result) && !frameView)
|
||||
result = parentFrame->GetParent(&parentFrame);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result) && frameView)
|
||||
{
|
||||
//
|
||||
// Now make sure that the frame's view is in the
|
||||
// scrollable view's parent hierarchy.
|
||||
//
|
||||
|
||||
nsIView *view = (nsIView*)cView;
|
||||
nscoord x, y;
|
||||
|
||||
while (view && view != frameView)
|
||||
{
|
||||
result = view->GetParent(view);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
view = 0;
|
||||
else if (view)
|
||||
{
|
||||
result = view->GetPosition(&x, &y);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
view = 0;
|
||||
else
|
||||
{
|
||||
//
|
||||
// Keep track of the view offsets so we can
|
||||
// translate aPoint into the scrollable view's
|
||||
// coordinate system.
|
||||
//
|
||||
|
||||
viewOffset.x += x;
|
||||
viewOffset.y += y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (view)
|
||||
{
|
||||
//
|
||||
// See if aPoint is outside the clip view's boundaries.
|
||||
// If it is, scroll the view till it is inside the visible area!
|
||||
//
|
||||
|
||||
nsRect bounds;
|
||||
|
||||
result = cView->GetBounds(bounds);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
//
|
||||
// Calculate the amount we would have to scroll in
|
||||
// the vertical and horizontal directions to get the point
|
||||
// within the clip area.
|
||||
//
|
||||
|
||||
nscoord dx = 0, dy = 0;
|
||||
nsPoint ePoint = aPoint;
|
||||
|
||||
ePoint.x -= viewOffset.x;
|
||||
ePoint.y -= viewOffset.y;
|
||||
|
||||
nscoord x1 = bounds.x;
|
||||
nscoord x2 = bounds.x + bounds.width;
|
||||
nscoord y1 = bounds.y;
|
||||
nscoord y2 = bounds.y + bounds.height;
|
||||
|
||||
if (ePoint.x < x1)
|
||||
dx = ePoint.x - x1;
|
||||
else if (ePoint.x > x2)
|
||||
dx = ePoint.x - x2;
|
||||
|
||||
if (ePoint.y < y1)
|
||||
dy = ePoint.y - y1;
|
||||
else if (ePoint.y > y2)
|
||||
dy = ePoint.y - y2;
|
||||
|
||||
//
|
||||
// Now clip the scroll amounts so that we don't scroll
|
||||
// beyond the ends of the document.
|
||||
//
|
||||
|
||||
nscoord scrollX = 0, scrollY = 0;
|
||||
nscoord docWidth = 0, docHeight = 0;
|
||||
|
||||
result = scrollableView->GetScrollPosition(scrollX, scrollY);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
result = scrollableView->GetContainerSize(&docWidth, &docHeight);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (dx < 0 && scrollX == 0)
|
||||
dx = 0;
|
||||
else if (dx > 0)
|
||||
{
|
||||
x1 = scrollX + dx + bounds.width;
|
||||
|
||||
if (x1 > docWidth)
|
||||
dx -= x1 - docWidth;
|
||||
}
|
||||
|
||||
|
||||
if (dy < 0 && scrollY == 0)
|
||||
dy = 0;
|
||||
else if (dy > 0)
|
||||
{
|
||||
y1 = scrollY + dy + bounds.height;
|
||||
|
||||
if (y1 > docHeight)
|
||||
dy -= y1 - docHeight;
|
||||
}
|
||||
|
||||
//
|
||||
// Now scroll the view if neccessary.
|
||||
//
|
||||
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
result = scrollableView->ScrollTo(scrollX + dx, scrollY + dy, NS_VMREFRESH_NO_SYNC);
|
||||
|
||||
if (mAutoScrollTimer)
|
||||
result = mAutoScrollTimer->Start(aPresContext, aFrame, aPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMSelection::GetEnumerator(nsIEnumerator **aIterator)
|
||||
{
|
||||
@ -2965,7 +3355,6 @@ nsDOMSelection::Extend(nsIDOMNode* aParentNode, PRInt32 aOffset)
|
||||
else if (NS_FAILED(mAnchorFocusRange->SetEnd(endNode,endOffset)))
|
||||
return NS_ERROR_FAILURE;//???
|
||||
/*end hack*/
|
||||
ScrollIntoView();
|
||||
#ifdef DEBUG_SELECTION
|
||||
if (aParentNode)
|
||||
{
|
||||
|
||||
@ -45,6 +45,11 @@ public:
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
protected:
|
||||
virtual ~BRFrame();
|
||||
@ -170,3 +175,20 @@ NS_IMETHODIMP BRFrame::GetPosition(nsIPresContext& aCX,
|
||||
aOffsetEnd = aOffsetBegin;//BRFrames should return a collapsed selection before itself
|
||||
return returnval;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP BRFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aContent,
|
||||
PRInt32& aOffsetBegin,
|
||||
PRInt32& aOffsetEnd)
|
||||
{
|
||||
nsresult result = nsFrame::GetContentAndOffsetsFromPoint(aCX,aPoint,aContent,aOffsetBegin,aOffsetEnd);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// BRFrames should return a collapsed selection before itself
|
||||
aOffsetEnd = aOffsetBegin;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -793,6 +793,9 @@ nsFrame::HandleEvent(nsIPresContext& aPresContext,
|
||||
frameselection->SetMouseDownState(PR_TRUE);//not important if it fails here
|
||||
HandlePress(aPresContext, aEvent, aEventStatus);
|
||||
}break;
|
||||
case NS_MOUSE_LEFT_BUTTON_UP:
|
||||
HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
@ -822,7 +825,7 @@ nsFrame::HandlePress(nsIPresContext& aPresContext,
|
||||
// PRUint32 contentOffset = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
if (NS_SUCCEEDED(GetContentAndOffsetsFromPoint(aPresContext, aEvent->point,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))){
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
@ -866,7 +869,7 @@ nsFrame::HandleMultiplePress(nsIPresContext& aPresContext,
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
if (NS_SUCCEEDED(GetContentAndOffsetsFromPoint(aPresContext, aEvent->point,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))) {
|
||||
// find which word needs to be selected! use peek offset one
|
||||
@ -929,23 +932,26 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext,
|
||||
if (!DisplaySelection(aPresContext)) {
|
||||
return NS_OK;
|
||||
}
|
||||
// printf("handledrag %x\n",this);
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsresult rv = aPresContext.GetShell(getter_AddRefs(shell));
|
||||
if (NS_SUCCEEDED(rv) && shell) {
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))) {
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
if (NS_SUCCEEDED(shell->GetFrameSelection(getter_AddRefs(frameselection))) && frameselection){
|
||||
frameselection->HandleClick(newContent, startPos, contentOffsetEnd , PR_TRUE, PR_FALSE); //TRUE IS THE DIFFERENCE for continue selection
|
||||
}
|
||||
//no release
|
||||
}
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
|
||||
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
||||
|
||||
if (NS_SUCCEEDED(result) && frameselection)
|
||||
{
|
||||
frameselection->StopAutoScrollTimer();
|
||||
frameselection->HandleDrag(&aPresContext, this, aEvent->point);
|
||||
frameselection->StartAutoScrollTimer(&aPresContext, this, aEvent->point, 30);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -953,9 +959,153 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsIPresContext& aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus& aEventStatus)
|
||||
{
|
||||
if (!DisplaySelection(aPresContext))
|
||||
return NS_OK;
|
||||
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
|
||||
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
||||
|
||||
if (NS_SUCCEEDED(result) && frameselection)
|
||||
frameselection->StopAutoScrollTimer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
|
||||
if (!aNewContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Traverse through children and look for the best one to give this
|
||||
// to if it fails the getposition call, make it yourself also only
|
||||
// look at primary list
|
||||
nsIView *view = nsnull;
|
||||
nsIFrame *kid = nsnull;
|
||||
nsIFrame *closestFrame = nsnull;
|
||||
|
||||
result = GetClosestViewForFrame(this, &view);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
result = FirstChild(nsnull, &kid);
|
||||
|
||||
if (NS_SUCCEEDED(result) && nsnull != kid) {
|
||||
|
||||
#define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison
|
||||
|
||||
PRInt32 closestXDistance = HUGE_DISTANCE;
|
||||
PRInt32 closestYDistance = HUGE_DISTANCE;
|
||||
|
||||
while (nsnull != kid) {
|
||||
nsRect rect;
|
||||
nsPoint offsetPoint(0,0);
|
||||
nsIView * kidView = nsnull;
|
||||
|
||||
kid->GetRect(rect);
|
||||
kid->GetOffsetFromView(offsetPoint, &kidView);
|
||||
|
||||
rect.x = offsetPoint.x;
|
||||
rect.y = offsetPoint.y;
|
||||
|
||||
nscoord y1 = rect.y;
|
||||
nscoord y2 = rect.y + rect.height;
|
||||
|
||||
PRInt32 yDistance = PR_MIN(abs(y1 - aPoint.y),abs(y2 - aPoint.y));
|
||||
|
||||
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
|
||||
{
|
||||
if (yDistance < closestYDistance)
|
||||
closestXDistance = HUGE_DISTANCE;
|
||||
|
||||
nscoord x1 = rect.x;
|
||||
nscoord x2 = rect.x + rect.width;
|
||||
|
||||
if (x1 <= aPoint.x && x2 >= aPoint.x && y1 <= aPoint.y && y2 >= aPoint.y)
|
||||
{
|
||||
closestFrame = kid;
|
||||
break;
|
||||
}
|
||||
|
||||
PRInt32 xDistance = PR_MIN(abs(x1 - aPoint.x),abs(x2 - aPoint.x));
|
||||
|
||||
if (xDistance < closestXDistance)
|
||||
{
|
||||
closestXDistance = xDistance;
|
||||
closestYDistance = yDistance;
|
||||
closestFrame = kid;
|
||||
}
|
||||
// else if (xDistance > closestXDistance)
|
||||
// break;//done
|
||||
}
|
||||
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
if (closestFrame) {
|
||||
|
||||
// If we cross a view boundary, we need to adjust
|
||||
// the coordinates because GetPosition() expects
|
||||
// them to be relative to the closest view.
|
||||
|
||||
nsPoint newPoint = aPoint;
|
||||
nsIView *closestView = nsnull;
|
||||
|
||||
result = GetClosestViewForFrame(closestFrame, &closestView);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (closestView && view != closestView)
|
||||
{
|
||||
nscoord vX = 0, vY = 0;
|
||||
result = closestView->GetPosition(&vX, &vY);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
newPoint.x -= vX;
|
||||
newPoint.y -= vY;
|
||||
}
|
||||
}
|
||||
|
||||
// printf(" 0x%.8x 0x%.8x %4d %4d\n",
|
||||
// closestFrame, closestView, closestXDistance, closestYDistance);
|
||||
|
||||
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent,
|
||||
aContentOffset, aContentOffsetEnd);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
result = mContent->GetParent(*aNewContent);
|
||||
if (*aNewContent){
|
||||
result = (*aNewContent)->IndexOf(mContent, aContentOffset);
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
aContentOffsetEnd = aContentOffset +1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- GetPosition
|
||||
//--------------------------------------------------------------------------
|
||||
@ -2310,6 +2460,36 @@ nsFrame::PeekOffset(nsPeekOffsetStruct *aPos)
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsFrame::GetClosestViewForFrame(nsIFrame *aFrame, nsIView **aView)
|
||||
{
|
||||
if (!aView)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
*aView = 0;
|
||||
|
||||
nsIFrame *parent = aFrame;
|
||||
|
||||
while (parent && !*aView)
|
||||
{
|
||||
result = parent->GetView(aView);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (!*aView)
|
||||
{
|
||||
result = parent->GetParent(&parent);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@ -274,6 +274,13 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Additional methods
|
||||
|
||||
@ -303,6 +310,8 @@ public:
|
||||
PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aMetrics);
|
||||
|
||||
virtual nsresult GetClosestViewForFrame(nsIFrame *aFrame, nsIView **aView);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
/**
|
||||
* Tracing method that writes a method enter/exit routine to the
|
||||
|
||||
@ -457,6 +457,12 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd) = 0;
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Get the cursor for a given frame.
|
||||
|
||||
@ -348,6 +348,12 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetPositionSlowly(nsIPresContext& aCX,
|
||||
nsIRenderingContext * aRendContext,
|
||||
nscoord aXCoord,
|
||||
@ -1829,6 +1835,16 @@ nsTextFrame::GetPosition(nsIPresContext& aCX,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
return GetPosition(aCX, (aPoint.x < 0) ? 0 : aPoint.x, aNewContent, aContentOffset, aContentOffsetEnd);
|
||||
}
|
||||
|
||||
|
||||
// [HACK] Foward Declarations
|
||||
void ForceDrawFrame(nsFrame * aFrame);
|
||||
|
||||
@ -45,6 +45,11 @@ public:
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
protected:
|
||||
virtual ~BRFrame();
|
||||
@ -170,3 +175,20 @@ NS_IMETHODIMP BRFrame::GetPosition(nsIPresContext& aCX,
|
||||
aOffsetEnd = aOffsetBegin;//BRFrames should return a collapsed selection before itself
|
||||
return returnval;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP BRFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aContent,
|
||||
PRInt32& aOffsetBegin,
|
||||
PRInt32& aOffsetEnd)
|
||||
{
|
||||
nsresult result = nsFrame::GetContentAndOffsetsFromPoint(aCX,aPoint,aContent,aOffsetBegin,aOffsetEnd);
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// BRFrames should return a collapsed selection before itself
|
||||
aOffsetEnd = aOffsetBegin;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -793,6 +793,9 @@ nsFrame::HandleEvent(nsIPresContext& aPresContext,
|
||||
frameselection->SetMouseDownState(PR_TRUE);//not important if it fails here
|
||||
HandlePress(aPresContext, aEvent, aEventStatus);
|
||||
}break;
|
||||
case NS_MOUSE_LEFT_BUTTON_UP:
|
||||
HandleRelease(aPresContext, aEvent, aEventStatus);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
@ -822,7 +825,7 @@ nsFrame::HandlePress(nsIPresContext& aPresContext,
|
||||
// PRUint32 contentOffset = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
if (NS_SUCCEEDED(GetContentAndOffsetsFromPoint(aPresContext, aEvent->point,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))){
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
@ -866,7 +869,7 @@ nsFrame::HandleMultiplePress(nsIPresContext& aPresContext,
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
if (NS_SUCCEEDED(GetContentAndOffsetsFromPoint(aPresContext, aEvent->point,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))) {
|
||||
// find which word needs to be selected! use peek offset one
|
||||
@ -929,23 +932,26 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext,
|
||||
if (!DisplaySelection(aPresContext)) {
|
||||
return NS_OK;
|
||||
}
|
||||
// printf("handledrag %x\n",this);
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
nsresult rv = aPresContext.GetShell(getter_AddRefs(shell));
|
||||
if (NS_SUCCEEDED(rv) && shell) {
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
if (NS_SUCCEEDED(GetPosition(aPresContext, aEvent->point.x,
|
||||
getter_AddRefs(newContent),
|
||||
startPos, contentOffsetEnd))) {
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
if (NS_SUCCEEDED(shell->GetFrameSelection(getter_AddRefs(frameselection))) && frameselection){
|
||||
frameselection->HandleClick(newContent, startPos, contentOffsetEnd , PR_TRUE, PR_FALSE); //TRUE IS THE DIFFERENCE for continue selection
|
||||
}
|
||||
//no release
|
||||
}
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
|
||||
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
||||
|
||||
if (NS_SUCCEEDED(result) && frameselection)
|
||||
{
|
||||
frameselection->StopAutoScrollTimer();
|
||||
frameselection->HandleDrag(&aPresContext, this, aEvent->point);
|
||||
frameselection->StartAutoScrollTimer(&aPresContext, this, aEvent->point, 30);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -953,9 +959,153 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsIPresContext& aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus& aEventStatus)
|
||||
{
|
||||
if (!DisplaySelection(aPresContext))
|
||||
return NS_OK;
|
||||
|
||||
nsresult result;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
|
||||
result = aPresContext.GetShell(getter_AddRefs(presShell));
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIFrameSelection> frameselection;
|
||||
|
||||
result = presShell->GetFrameSelection(getter_AddRefs(frameselection));
|
||||
|
||||
if (NS_SUCCEEDED(result) && frameselection)
|
||||
frameselection->StopAutoScrollTimer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
nsresult result = NS_ERROR_FAILURE;
|
||||
|
||||
if (!aNewContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Traverse through children and look for the best one to give this
|
||||
// to if it fails the getposition call, make it yourself also only
|
||||
// look at primary list
|
||||
nsIView *view = nsnull;
|
||||
nsIFrame *kid = nsnull;
|
||||
nsIFrame *closestFrame = nsnull;
|
||||
|
||||
result = GetClosestViewForFrame(this, &view);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
result = FirstChild(nsnull, &kid);
|
||||
|
||||
if (NS_SUCCEEDED(result) && nsnull != kid) {
|
||||
|
||||
#define HUGE_DISTANCE 999999 //some HUGE number that will always fail first comparison
|
||||
|
||||
PRInt32 closestXDistance = HUGE_DISTANCE;
|
||||
PRInt32 closestYDistance = HUGE_DISTANCE;
|
||||
|
||||
while (nsnull != kid) {
|
||||
nsRect rect;
|
||||
nsPoint offsetPoint(0,0);
|
||||
nsIView * kidView = nsnull;
|
||||
|
||||
kid->GetRect(rect);
|
||||
kid->GetOffsetFromView(offsetPoint, &kidView);
|
||||
|
||||
rect.x = offsetPoint.x;
|
||||
rect.y = offsetPoint.y;
|
||||
|
||||
nscoord y1 = rect.y;
|
||||
nscoord y2 = rect.y + rect.height;
|
||||
|
||||
PRInt32 yDistance = PR_MIN(abs(y1 - aPoint.y),abs(y2 - aPoint.y));
|
||||
|
||||
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
|
||||
{
|
||||
if (yDistance < closestYDistance)
|
||||
closestXDistance = HUGE_DISTANCE;
|
||||
|
||||
nscoord x1 = rect.x;
|
||||
nscoord x2 = rect.x + rect.width;
|
||||
|
||||
if (x1 <= aPoint.x && x2 >= aPoint.x && y1 <= aPoint.y && y2 >= aPoint.y)
|
||||
{
|
||||
closestFrame = kid;
|
||||
break;
|
||||
}
|
||||
|
||||
PRInt32 xDistance = PR_MIN(abs(x1 - aPoint.x),abs(x2 - aPoint.x));
|
||||
|
||||
if (xDistance < closestXDistance)
|
||||
{
|
||||
closestXDistance = xDistance;
|
||||
closestYDistance = yDistance;
|
||||
closestFrame = kid;
|
||||
}
|
||||
// else if (xDistance > closestXDistance)
|
||||
// break;//done
|
||||
}
|
||||
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
if (closestFrame) {
|
||||
|
||||
// If we cross a view boundary, we need to adjust
|
||||
// the coordinates because GetPosition() expects
|
||||
// them to be relative to the closest view.
|
||||
|
||||
nsPoint newPoint = aPoint;
|
||||
nsIView *closestView = nsnull;
|
||||
|
||||
result = GetClosestViewForFrame(closestFrame, &closestView);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (closestView && view != closestView)
|
||||
{
|
||||
nscoord vX = 0, vY = 0;
|
||||
result = closestView->GetPosition(&vX, &vY);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
newPoint.x -= vX;
|
||||
newPoint.y -= vY;
|
||||
}
|
||||
}
|
||||
|
||||
// printf(" 0x%.8x 0x%.8x %4d %4d\n",
|
||||
// closestFrame, closestView, closestXDistance, closestYDistance);
|
||||
|
||||
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint, aNewContent,
|
||||
aContentOffset, aContentOffsetEnd);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
result = mContent->GetParent(*aNewContent);
|
||||
if (*aNewContent){
|
||||
result = (*aNewContent)->IndexOf(mContent, aContentOffset);
|
||||
if (NS_FAILED(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
aContentOffsetEnd = aContentOffset +1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- GetPosition
|
||||
//--------------------------------------------------------------------------
|
||||
@ -2310,6 +2460,36 @@ nsFrame::PeekOffset(nsPeekOffsetStruct *aPos)
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsFrame::GetClosestViewForFrame(nsIFrame *aFrame, nsIView **aView)
|
||||
{
|
||||
if (!aView)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
*aView = 0;
|
||||
|
||||
nsIFrame *parent = aFrame;
|
||||
|
||||
while (parent && !*aView)
|
||||
{
|
||||
result = parent->GetView(aView);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (!*aView)
|
||||
{
|
||||
result = parent->GetParent(&parent);
|
||||
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
@ -274,6 +274,13 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Additional methods
|
||||
|
||||
@ -303,6 +310,8 @@ public:
|
||||
PRBool IsFrameTreeTooDeep(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aMetrics);
|
||||
|
||||
virtual nsresult GetClosestViewForFrame(nsIFrame *aFrame, nsIView **aView);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
/**
|
||||
* Tracing method that writes a method enter/exit routine to the
|
||||
|
||||
@ -348,6 +348,12 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetPositionSlowly(nsIPresContext& aCX,
|
||||
nsIRenderingContext * aRendContext,
|
||||
nscoord aXCoord,
|
||||
@ -1829,6 +1835,16 @@ nsTextFrame::GetPosition(nsIPresContext& aCX,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::GetContentAndOffsetsFromPoint(nsIPresContext& aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
return GetPosition(aCX, (aPoint.x < 0) ? 0 : aPoint.x, aNewContent, aContentOffset, aContentOffsetEnd);
|
||||
}
|
||||
|
||||
|
||||
// [HACK] Foward Declarations
|
||||
void ForceDrawFrame(nsFrame * aFrame);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user