mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 18:47:53 +00:00
Bug 316281. Rework GetContentAndOffsetsFromPoint. r=uriber,sr=roc,patch by Eli Friedman
This commit is contained in:
parent
5473753429
commit
a710fcd15d
@ -56,9 +56,8 @@ class nsIPresShell;
|
||||
|
||||
// IID for the nsIFrameSelection interface
|
||||
#define NS_IFRAMESELECTION_IID \
|
||||
{ 0x18477ed4, 0x01ff, 0x4319, \
|
||||
{ 0x95, 0xc0, 0x63, 0x9e, 0xe4, 0x33, 0xbe, 0x92 } }
|
||||
|
||||
{ 0xe5d9fe4f, 0xf430, 0x41ab, \
|
||||
{ 0x95, 0xab, 0x1e, 0x7c, 0x86, 0x80, 0x2d, 0xd7 } }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@ -289,18 +288,6 @@ public:
|
||||
*/
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset)=0;
|
||||
|
||||
/** AdjustOffsetsFromStyle. Called after detecting that a click or drag will
|
||||
* select the frame, this function looks for user-select style on that frame or a parent
|
||||
* frame, and adjust the content and offsets accordingly.
|
||||
* @param aFrame the frame that was clicked
|
||||
* @param outContent content node to be selected
|
||||
* @param outStartOffset selection start offset
|
||||
* @param outEndOffset selection end offset
|
||||
*/
|
||||
NS_IMETHOD AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection,
|
||||
nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset)=0;
|
||||
|
||||
|
||||
NS_IMETHOD GetHint(HINT *aHint)=0;
|
||||
NS_IMETHOD SetHint(HINT aHint)=0;
|
||||
|
||||
|
@ -597,8 +597,6 @@ public:
|
||||
NS_IMETHOD GetLimiter(nsIContent **aLimiterContent);
|
||||
NS_IMETHOD GetTableCellSelection(PRBool *aState);
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset);
|
||||
NS_IMETHOD AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection,
|
||||
nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset);
|
||||
NS_IMETHOD GetHint(nsIFrameSelection::HINT *aHint);
|
||||
NS_IMETHOD SetHint(nsIFrameSelection::HINT aHint);
|
||||
NS_IMETHOD SetScrollableView(nsIScrollableView *aScrollableView);
|
||||
@ -1148,13 +1146,6 @@ nsTextInputSelectionImpl::GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffs
|
||||
return mFrameSelection->GetFrameForNodeOffset(aNode, aOffset, aHint,aReturnFrame,aReturnOffset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextInputSelectionImpl::AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection,
|
||||
nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset)
|
||||
{
|
||||
return mFrameSelection->AdjustOffsetsFromStyle(aFrame, changeSelection, outContent, outStartOffset, outEndOffset);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTextInputSelectionImpl::GetHint(nsIFrameSelection::HINT *aHint)
|
||||
{
|
||||
return mFrameSelection->GetHint(aHint);
|
||||
|
@ -61,12 +61,11 @@ public:
|
||||
nsFramePaintLayer aWhichLayer,
|
||||
PRUint32 aFlags = 0);
|
||||
#endif
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd,
|
||||
PRBool& aBeginFrameContent);
|
||||
NS_IMETHOD GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD PeekOffset(nsPresContext* aPresContext,
|
||||
nsPeekOffsetStruct *aPos);
|
||||
|
||||
@ -210,22 +209,21 @@ BRFrame::GetType() const
|
||||
return nsLayoutAtoms::brFrame;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP BRFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aContent,
|
||||
PRInt32& aOffsetBegin,
|
||||
PRInt32& aOffsetEnd,
|
||||
PRBool& aBeginFrameContent)
|
||||
NS_IMETHODIMP BRFrame::GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
if (!mContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_IF_ADDREF(*aContent = mContent->GetParent());
|
||||
NS_IF_ADDREF(*aNewContent = mContent->GetParent());
|
||||
|
||||
if (*aContent)
|
||||
aOffsetBegin = (*aContent)->IndexOf(mContent);
|
||||
aOffsetEnd = aOffsetBegin;
|
||||
aBeginFrameContent = PR_TRUE;
|
||||
return NS_OK;
|
||||
if (*aNewContent) {
|
||||
aContentOffset = (*aNewContent)->IndexOf(mContent);
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP BRFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
||||
|
@ -6484,203 +6484,6 @@ nsBlockFrame::PaintChildren(nsPresContext* aPresContext,
|
||||
#endif
|
||||
}
|
||||
|
||||
// XXXldb Does this handle all overlap cases correctly? (How?)
|
||||
nsresult
|
||||
nsBlockFrame::GetClosestLine(nsILineIterator *aLI,
|
||||
const nsPoint &aPoint,
|
||||
PRInt32 &aClosestLine)
|
||||
{
|
||||
if (!aLI)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsRect rect;
|
||||
PRInt32 numLines;
|
||||
PRInt32 lineFrameCount;
|
||||
nsIFrame *firstFrame;
|
||||
PRUint32 flags;
|
||||
|
||||
nsresult result = aLI->GetNumLines(&numLines);
|
||||
|
||||
if (NS_FAILED(result) || numLines < 0)
|
||||
return NS_OK;//do not handle
|
||||
|
||||
PRInt32 shifted = numLines;
|
||||
PRInt32 start = 0, midpoint = 0;
|
||||
PRInt32 y = 0;
|
||||
|
||||
while(shifted > 0)
|
||||
{
|
||||
// Cut the number of lines to look at in half and
|
||||
// calculate the midpoint of the region we are looking at.
|
||||
|
||||
shifted >>= 1; //divide by 2
|
||||
midpoint = start + shifted;
|
||||
|
||||
// Get the dimensions of the line that is at the half
|
||||
// point of the region we are looking at.
|
||||
|
||||
result = aLI->GetLine(midpoint, &firstFrame, &lineFrameCount,rect,&flags);
|
||||
if (NS_FAILED(result))
|
||||
break;//do not handle
|
||||
|
||||
// Check to see if our point lies with the line's Y bounds.
|
||||
|
||||
y = aPoint.y - rect.y;
|
||||
if (y >=0 && (aPoint.y < (rect.y+rect.height)))
|
||||
{
|
||||
aClosestLine = midpoint; //spot on!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (y > 0)
|
||||
{
|
||||
// If we get here, no match was found above, so aPoint.y must
|
||||
// be greater than the Y bounds of the current line rect. Move
|
||||
// our starting point just beyond the midpoint of the current region.
|
||||
|
||||
start = midpoint;
|
||||
|
||||
if (numLines > 1 && start < (numLines - 1))
|
||||
++start;
|
||||
else
|
||||
shifted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we don't go off the edge in either direction!
|
||||
|
||||
NS_ASSERTION(start >=0 && start <= numLines, "Invalid start calculated.");
|
||||
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
else if (start >= numLines)
|
||||
start = numLines - 1;
|
||||
|
||||
aClosestLine = start; //close as we could come
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBlockFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
|
||||
nsresult result;
|
||||
nsIPresShell *shell = nsnull;
|
||||
if (aEvent->message == NS_MOUSE_MOVE) {
|
||||
shell = aPresContext->GetPresShell();
|
||||
if (!shell)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIFrameSelection> frameSelection;
|
||||
PRBool mouseDown = PR_FALSE;
|
||||
//check to see if we need to ask the selection controller..
|
||||
if (mState & NS_FRAME_INDEPENDENT_SELECTION)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
||||
if (NS_FAILED(result) || !selCon)
|
||||
return result?result:NS_ERROR_FAILURE;
|
||||
frameSelection = do_QueryInterface(selCon);
|
||||
}
|
||||
else
|
||||
frameSelection = shell->FrameSelection();
|
||||
if (!frameSelection || NS_FAILED(frameSelection->GetMouseDownState(&mouseDown)) || !mouseDown)
|
||||
return NS_OK;//do not handle
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN || aEvent->message == NS_MOUSE_MOVE ||
|
||||
aEvent->message == NS_MOUSE_LEFT_DOUBLECLICK ) {
|
||||
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
|
||||
nsIFrame *resultFrame = nsnull;//this will be passed the handle event when we
|
||||
//can tell who to pass it to
|
||||
nsIFrame *mainframe = this;
|
||||
shell = aPresContext->GetPresShell();
|
||||
if (!shell)
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsILineIterator> it( do_QueryInterface(mainframe, &result) );
|
||||
nsPeekOffsetStruct pos;
|
||||
|
||||
while(NS_OK == result)
|
||||
{ //we are starting aloop to allow us to "drill down to the one we want"
|
||||
PRInt32 closestLine;
|
||||
nsPoint pt =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, mainframe);
|
||||
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 + offset.x;
|
||||
pos.mScrollViewStop = PR_FALSE;
|
||||
pos.mIsKeyboardSelect = PR_FALSE;
|
||||
result = nsFrame::GetNextPrevLineFromeBlockFrame(aPresContext,
|
||||
&pos,
|
||||
mainframe,
|
||||
closestLine-1,
|
||||
0
|
||||
);
|
||||
|
||||
if (NS_SUCCEEDED(result) && pos.mResultFrame){
|
||||
if (result == NS_OK)
|
||||
it = do_QueryInterface(pos.mResultFrame, &result);//if this fails that's ok
|
||||
resultFrame = pos.mResultFrame;
|
||||
mainframe = resultFrame;
|
||||
}
|
||||
else
|
||||
break;//time to go nothing was found
|
||||
}
|
||||
//end while loop. if nssucceeded resutl then keep going that means
|
||||
//we have successfully hit another block frame and we should keep going.
|
||||
|
||||
|
||||
if (resultFrame)
|
||||
{
|
||||
if (NS_POSITION_BEFORE_TABLE == result)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon;
|
||||
result = GetSelectionController(aPresContext, getter_AddRefs(selCon));
|
||||
//get the selection controller
|
||||
if (NS_SUCCEEDED(result) && selCon)
|
||||
{
|
||||
PRInt16 displayresult;
|
||||
selCon->GetDisplaySelection(&displayresult);
|
||||
if (displayresult == nsISelectionController::SELECTION_OFF)
|
||||
return NS_OK;//nothing to do we cannot affect selection from here
|
||||
}
|
||||
PRBool mouseDown = aEvent->message == NS_MOUSE_MOVE;
|
||||
result = shell->FrameSelection()->HandleClick(pos.mResultContent,
|
||||
pos.mContentOffset,
|
||||
pos.mContentOffsetEnd,
|
||||
mouseDown || me->isShift,
|
||||
PR_FALSE,
|
||||
pos.mPreferLeft);
|
||||
}
|
||||
else
|
||||
result = resultFrame->HandleEvent(aPresContext, aEvent, aEventStatus);//else let the frame/container do what it needs
|
||||
/* Note that the above call to HandleEvent may capture the
|
||||
mouse. If so, don't try to capture again. */
|
||||
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN && !IsMouseCaptured(aPresContext))
|
||||
CaptureMouse(aPresContext, PR_TRUE);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NS_OK; //just stop it
|
||||
}
|
||||
}
|
||||
return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHODIMP nsBlockFrame::GetAccessible(nsIAccessible** aAccessible)
|
||||
{
|
||||
|
@ -206,9 +206,6 @@ public:
|
||||
PRBool aConsiderSelf);
|
||||
virtual nsIFrame* GetFrameForPoint(const nsPoint& aPoint,
|
||||
nsFramePaintLayer aWhichLayer);
|
||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
|
||||
|
||||
NS_IMETHOD IsVisibleForPainting(nsPresContext * aPresContext,
|
||||
@ -229,21 +226,6 @@ public:
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
#ifdef DO_SELECTION
|
||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
|
||||
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
|
||||
nsIFrame * FindHitFrame(nsBlockFrame * aBlockFrame,
|
||||
const nscoord aX, const nscoord aY,
|
||||
const nsPoint & aPoint);
|
||||
|
||||
#endif
|
||||
|
||||
virtual void DeleteNextInFlowChild(nsPresContext* aPresContext,
|
||||
nsIFrame* aNextInFlow);
|
||||
|
||||
@ -312,16 +294,6 @@ protected:
|
||||
nscoord aAscent,
|
||||
nscoord aSize);
|
||||
|
||||
/**
|
||||
* GetClosestLine will return the line that VERTICALLY owns the point closest to aPoint.y
|
||||
* aPoint is the point to search for, relative to the origin of the frame that aLI
|
||||
* iterates over.
|
||||
* aClosestLine is the result.
|
||||
*/
|
||||
nsresult GetClosestLine(nsILineIterator *aLI,
|
||||
const nsPoint &aPoint,
|
||||
PRInt32 &aClosestLine);
|
||||
|
||||
void TryAllLines(nsLineList::iterator* aIterator,
|
||||
nsLineList::iterator* aEndIterator,
|
||||
PRBool* aInOverflowLines);
|
||||
|
@ -23,6 +23,7 @@
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Uri Bernstein <uriber@gmail.com>
|
||||
* Eli Friedman <sharparrow1@yahoo.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -1112,28 +1113,6 @@ nsFrame::GetDataForTableSelection(nsIFrameSelection *aFrameSelection,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
NS_IMETHODIMP
|
||||
nsFrame::FrameOrParentHasSpecialSelectionStyle(PRUint8 aSelectionStyle, nsIFrame* *foundFrame)
|
||||
{
|
||||
nsIFrame* thisFrame = this;
|
||||
|
||||
while (thisFrame)
|
||||
{
|
||||
if (thisFrame->GetStyleUserInterface()->mUserSelect == aSelectionStyle)
|
||||
{
|
||||
*foundFrame = thisFrame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
thisFrame = thisFrame->GetParent();
|
||||
}
|
||||
|
||||
*foundFrame = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
|
||||
{
|
||||
@ -1199,58 +1178,6 @@ nsFrame::IsSelectable(PRBool* aSelectable, PRUint8* aSelectStyle) const
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
ContentContainsPoint(nsPresContext *aPresContext,
|
||||
nsIContent *aContent,
|
||||
const nsPoint &aPoint,
|
||||
nsIView *aRelativeView)
|
||||
{
|
||||
nsIPresShell *presShell = aPresContext->GetPresShell();
|
||||
|
||||
if (!presShell) return PR_FALSE;
|
||||
|
||||
nsIFrame *frame = presShell->GetPrimaryFrameFor(aContent);
|
||||
|
||||
if (!frame) return PR_FALSE;
|
||||
|
||||
nsIView *frameView = nsnull;
|
||||
nsPoint offsetPoint;
|
||||
|
||||
// Get the view that contains the content's frame.
|
||||
|
||||
nsresult rv = frame->GetOffsetFromView(offsetPoint, &frameView);
|
||||
|
||||
if (NS_FAILED(rv) || !frameView) return PR_FALSE;
|
||||
|
||||
// aPoint is relative to aRelativeView's upper left corner! Make sure
|
||||
// that our point is in the same view space our content frame's
|
||||
// rects are in.
|
||||
|
||||
nsPoint point = aPoint + aRelativeView->GetOffsetTo(frameView);
|
||||
|
||||
// Now check to see if the point is within the bounds of the
|
||||
// content's primary frame, or any of it's continuation frames.
|
||||
|
||||
while (frame) {
|
||||
// Get the frame's rect and make it relative to the
|
||||
// upper left corner of its parent view.
|
||||
|
||||
nsRect frameRect = frame->GetRect();
|
||||
frameRect.x = offsetPoint.x;
|
||||
frameRect.y = offsetPoint.y;
|
||||
|
||||
if (frameRect.Contains(point)) {
|
||||
// point is within this frame's rect!
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
frame = frame->GetNextInFlow();
|
||||
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the Mouse Press Event for the frame
|
||||
*/
|
||||
@ -1366,19 +1293,6 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||
rv = GetContentAndOffsetsFromPoint(aPresContext, pt, getter_AddRefs(content),
|
||||
startOffset, endOffset,
|
||||
beginFrameContent);
|
||||
// do we have CSS that changes selection behaviour?
|
||||
PRBool changeSelection = PR_FALSE;
|
||||
{
|
||||
nsCOMPtr<nsIContent> selectContent;
|
||||
PRInt32 newStart, newEnd;
|
||||
if (NS_SUCCEEDED(frameselection->AdjustOffsetsFromStyle(this, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
|
||||
&& changeSelection)
|
||||
{
|
||||
content = selectContent;
|
||||
startOffset = newStart;
|
||||
endOffset = newEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -1475,83 +1389,16 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
||||
if (isEditor && !me->isShift && (endOffset - startOffset) == 1)
|
||||
{
|
||||
// A single node is selected and we aren't extending an existing
|
||||
// selection, which means the user clicked directly on an object.
|
||||
// Check if the user clicked in a -moz-user-select:all subtree,
|
||||
// image, or hr. If so, we want to give the drag and drop
|
||||
// code a chance to execute so we need to turn off selection extension
|
||||
// when processing mouse move/drag events that follow this mouse
|
||||
// down event.
|
||||
|
||||
PRBool disableDragSelect = PR_FALSE;
|
||||
|
||||
if (changeSelection)
|
||||
{
|
||||
// The click hilited a -moz-user-select:all subtree.
|
||||
//
|
||||
// XXX: We really should be able to just do a:
|
||||
//
|
||||
// disableDragSelect = PR_TRUE;
|
||||
//
|
||||
// but we are working around the fact that in some cases,
|
||||
// selection selects a -moz-user-select:all subtree even
|
||||
// when the click was outside of the subtree. An example of
|
||||
// this case would be when the subtree is at the end of a
|
||||
// line and the user clicks to the right of it. In this case
|
||||
// I would expect the caret to be placed next to the root of
|
||||
// the subtree, but right now the whole subtree gets selected.
|
||||
// This means that we have to do geometric frame containment
|
||||
// checks on the point to see if the user truly clicked
|
||||
// inside the subtree.
|
||||
|
||||
nsIView *view = nsnull;
|
||||
nsPoint dummyPoint;
|
||||
|
||||
// aEvent->point is relative to the upper left corner of the
|
||||
// frame's parent view. Unfortunately, the only way to get
|
||||
// the parent view is to call GetOffsetFromView().
|
||||
|
||||
nsPoint pt = nsLayoutUtils::
|
||||
GetEventCoordinatesForNearestView(aEvent, this, &view);
|
||||
|
||||
GetOffsetFromView(dummyPoint, &view);
|
||||
|
||||
// Now check to see if the point is truly within the bounds
|
||||
// of any of the frames that make up the -moz-user-select:all subtree:
|
||||
|
||||
if (view)
|
||||
disableDragSelect = ContentContainsPoint(aPresContext, content,
|
||||
pt, view);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if click was in an image.
|
||||
|
||||
nsIContent* frameContent = GetContent();
|
||||
nsCOMPtr<nsIDOMHTMLImageElement> img(do_QueryInterface(frameContent));
|
||||
|
||||
disableDragSelect = img != nsnull;
|
||||
|
||||
if (!img)
|
||||
{
|
||||
// Check if click was in an hr.
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLHRElement> hr(do_QueryInterface(frameContent));
|
||||
disableDragSelect = hr != nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
if (disableDragSelect)
|
||||
{
|
||||
// Click was in one of our draggable objects, so disable
|
||||
// selection extension during mouse moves.
|
||||
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
}
|
||||
// selection, which means the user clicked directly on an object (either
|
||||
// -moz-user-select: all or a non-text node without children).
|
||||
// Therefore, disable selection extension during mouse moves.
|
||||
// XXX This is a bit hacky; shouldn't editor be able to deal with this?
|
||||
rv = frameselection->SetMouseDownState( PR_FALSE );
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiple Mouse Press -- line or paragraph selection -- for the frame.
|
||||
* Wouldn't it be nice if this didn't have to be hardwired into Frame code?
|
||||
@ -1575,28 +1422,31 @@ nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||
// If browser.triple_click_selects_paragraph is true, triple-click selects paragraph.
|
||||
// Otherwise, triple-click selects line, and quadruple-click selects paragraph
|
||||
// (on platforms that support quadruple-click).
|
||||
PRBool selectPara = PR_FALSE;
|
||||
nsSelectionAmount beginAmount, endAmount;
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
if (!me) return NS_OK;
|
||||
|
||||
if (me->clickCount == 4)
|
||||
selectPara = PR_TRUE;
|
||||
else if (me->clickCount == 3)
|
||||
{
|
||||
selectPara =
|
||||
nsContentUtils::GetBoolPref("browser.triple_click_selects_paragraph");
|
||||
}
|
||||
else
|
||||
if (me->clickCount == 4) {
|
||||
beginAmount = endAmount = eSelectParagraph;
|
||||
} else if (me->clickCount == 3) {
|
||||
if (nsContentUtils::GetBoolPref("browser.triple_click_selects_paragraph")) {
|
||||
beginAmount = endAmount = eSelectParagraph;
|
||||
} else {
|
||||
beginAmount = eSelectBeginLine;
|
||||
endAmount = eSelectEndLine;
|
||||
}
|
||||
} else if (me->clickCount == 2) {
|
||||
// We only want inline frames; PeekBackwardAndForward dislikes blocks
|
||||
beginAmount = endAmount = eSelectWord;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Line or paragraph selection:
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
PRBool beginContent = PR_FALSE;
|
||||
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
||||
|
||||
rv = GetContentAndOffsetsFromPoint(aPresContext,
|
||||
pt,
|
||||
getter_AddRefs(newContent),
|
||||
@ -1604,13 +1454,19 @@ nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||
contentOffsetEnd,
|
||||
beginContent);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
return PeekBackwardAndForward(selectPara ? eSelectParagraph
|
||||
: eSelectBeginLine,
|
||||
selectPara ? eSelectParagraph
|
||||
: eSelectEndLine,
|
||||
startPos, aPresContext, PR_TRUE);
|
||||
|
||||
nsIFrame* result;
|
||||
PRInt32 offset;
|
||||
// Maybe make this a static helper?
|
||||
rv = GetPresContext()->GetPresShell()->FrameSelection()->
|
||||
GetFrameForNodeOffset(newContent, startPos,
|
||||
nsIFrameSelection::HINT(beginContent),
|
||||
&result, &offset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsFrame* frame = NS_STATIC_CAST(nsFrame*, result);
|
||||
|
||||
return frame->PeekBackwardAndForward(beginAmount, endAmount,
|
||||
startPos, aPresContext, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1711,6 +1567,9 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPresContext* aPresContext,
|
||||
PRBool selectable;
|
||||
PRUint8 selectStyle;
|
||||
IsSelectable(&selectable, &selectStyle);
|
||||
// XXX Do we really need to exclude non-selectable content here?
|
||||
// GetContentAndOffsetsFromPoint can handle it just fine, although some
|
||||
// other stuff might not like it.
|
||||
if (!selectable)
|
||||
return NS_OK;
|
||||
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
||||
@ -1851,20 +1710,6 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
beginFrameContent);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// do we have CSS that changes selection behaviour?
|
||||
{
|
||||
PRBool changeSelection;
|
||||
nsCOMPtr<nsIContent> selectContent;
|
||||
PRInt32 newStart, newEnd;
|
||||
if (NS_SUCCEEDED(frameselection->AdjustOffsetsFromStyle(this, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
|
||||
&& changeSelection)
|
||||
{
|
||||
content = selectContent;
|
||||
startOffset = newStart;
|
||||
endOffset = newEnd;
|
||||
}
|
||||
}
|
||||
|
||||
result = frameselection->HandleClick(content, startOffset , endOffset, me->isShift, PR_FALSE, beginFrameContent);
|
||||
if (NS_FAILED(result)) return result;
|
||||
}
|
||||
@ -1897,139 +1742,431 @@ NS_IMETHODIMP nsFrame::HandleRelease(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct ContentOffsets {
|
||||
ContentOffsets(nsIContent* aContent, PRInt32 aStart, PRInt32 aEnd) :
|
||||
content(aContent), start(aStart), end(aEnd) { }
|
||||
nsCOMPtr<nsIContent> content;
|
||||
PRInt32 start;
|
||||
PRInt32 end;
|
||||
};
|
||||
|
||||
// Retrieve the content offsets of a frame
|
||||
static ContentOffsets GetOffsetsOfFrame(nsIFrame* aFrame) {
|
||||
nsCOMPtr<nsIContent> content, parent;
|
||||
NS_ASSERTION(aFrame->GetContent(), "No content?!");
|
||||
content = aFrame->GetContent();
|
||||
if (aFrame->GetType() == nsLayoutAtoms::textFrame) {
|
||||
PRInt32 offset, offsetEnd;
|
||||
aFrame->GetOffsets(offset, offsetEnd);
|
||||
return ContentOffsets(content, offset, offsetEnd);
|
||||
}
|
||||
// Loop to deal with anonymous content, which has no index; this loop
|
||||
// probably won't run more than twice under normal conditions
|
||||
do {
|
||||
parent = content->GetParent();
|
||||
if (parent) {
|
||||
PRInt32 beginOffset = parent->IndexOf(content);
|
||||
if (beginOffset >= 0)
|
||||
return ContentOffsets(parent, beginOffset, beginOffset + 1);
|
||||
content = parent;
|
||||
}
|
||||
} while (parent);
|
||||
|
||||
// The root content node must act differently
|
||||
return ContentOffsets(content, 0, content->GetChildCount());
|
||||
}
|
||||
|
||||
// The FrameTarget represents the closest frame to a point that can be selected
|
||||
// The frame is the frame represented, frameEdge says whether one end of the
|
||||
// frame is the result (in which case different handling is needed), and
|
||||
// afterFrame says which end is repersented if frameEdge is true
|
||||
struct FrameTarget {
|
||||
FrameTarget(nsIFrame* aFrame, PRBool aFrameEdge, PRBool aAfterFrame) :
|
||||
frame(aFrame), frameEdge(aFrameEdge), afterFrame(aAfterFrame) { }
|
||||
static FrameTarget Null() {
|
||||
return FrameTarget(nsnull, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
PRBool IsNull() {
|
||||
return !frame;
|
||||
}
|
||||
nsIFrame* frame;
|
||||
PRPackedBool frameEdge;
|
||||
PRPackedBool afterFrame;
|
||||
};
|
||||
|
||||
// See function implementation for information
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint);
|
||||
|
||||
static PRBool SelfIsSelectable(nsIFrame* aFrame)
|
||||
{
|
||||
return !(aFrame->IsGeneratedContentFrame() ||
|
||||
aFrame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE);
|
||||
}
|
||||
|
||||
static PRBool SelectionDescendToKids(nsIFrame* aFrame) {
|
||||
PRUint8 style = aFrame->GetStyleUIReset()->mUserSelect;
|
||||
nsIFrame* parent = aFrame->GetParent();
|
||||
// If we are only near (not directly over) then don't traverse
|
||||
// frames with independent selection (e.g. text and list controls)
|
||||
// unless we're already inside such a frame (see bug 268497). Note that this
|
||||
// prevents any of the users of this method from entering form controls.
|
||||
// XXX We might want some way to allow using the up-arrow to go into a form
|
||||
// control, but the focus didn't work right anyway; it'd probably be enough
|
||||
// if the left and right arrows could enter textboxes (which I don't believe
|
||||
// they can at the moment)
|
||||
return !aFrame->IsGeneratedContentFrame() &&
|
||||
style != NS_STYLE_USER_SELECT_ALL &&
|
||||
style != NS_STYLE_USER_SELECT_NONE &&
|
||||
((parent->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) ||
|
||||
!(aFrame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION));
|
||||
}
|
||||
|
||||
static FrameTarget GetSelectionClosestFrameForChild(nsIFrame* aChild,
|
||||
nsPoint aPoint)
|
||||
{
|
||||
nsIFrame* parent = aChild->GetParent();
|
||||
if (SelectionDescendToKids(aChild)) {
|
||||
nsPoint pt = aPoint - aChild->GetOffsetTo(parent);
|
||||
return GetSelectionClosestFrame(aChild, pt);
|
||||
}
|
||||
return FrameTarget(aChild, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
// When the cursor needs to be at the beginning of a block, it shouldn't be
|
||||
// before the first child. A click on a block whose first child is a block
|
||||
// should put the cursor in the child. The cursor shouldn't be between the
|
||||
// blocks, because that's not where it's expected.
|
||||
// Note that this method is guaranteed to succeed.
|
||||
static FrameTarget DrillDownToSelectionFrame(nsIFrame* aFrame,
|
||||
PRBool aEndFrame) {
|
||||
if (SelectionDescendToKids(aFrame)) {
|
||||
nsIFrame* result = nsnull;
|
||||
nsIFrame *frame = aFrame->GetFirstChild(nsnull);
|
||||
if (!aEndFrame) {
|
||||
while (frame && (!SelfIsSelectable(frame) ||
|
||||
frame->IsEmpty()))
|
||||
frame = frame->GetNextSibling();
|
||||
if (frame)
|
||||
result = frame;
|
||||
} else {
|
||||
// Because the frame tree is singly linked, to find the last frame,
|
||||
// we have to iterate through all the frames
|
||||
// XXX I have a feeling this could be slow for long blocks, although
|
||||
// I can't find any slowdowns
|
||||
while (frame) {
|
||||
if (!frame->IsEmpty() && SelfIsSelectable(frame))
|
||||
result = frame;
|
||||
frame = frame->GetNextSibling();
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
return DrillDownToSelectionFrame(result, aEndFrame);
|
||||
}
|
||||
// If the current frame has no targetable children, target the current frame
|
||||
return FrameTarget(aFrame, PR_TRUE, aEndFrame);
|
||||
}
|
||||
|
||||
// This method finds the closest valid FrameTarget on a given line; if there is
|
||||
// no valid FrameTarget on the line, it returns a null FrameTarget
|
||||
static FrameTarget GetSelectionClosestFrameForLine(
|
||||
nsBlockFrame* aParent,
|
||||
nsBlockFrame::line_iterator aLine,
|
||||
nsPoint aPoint)
|
||||
{
|
||||
nsIFrame *frame = aLine->mFirstChild;
|
||||
// Account for end of lines (any iterator from the block is valid)
|
||||
if (aLine == aParent->end_lines())
|
||||
return DrillDownToSelectionFrame(aParent, PR_TRUE);
|
||||
nsIFrame *closestFromLeft = nsnull, *closestFromRight = nsnull;
|
||||
nsRect rect = aLine->mBounds;
|
||||
nscoord closestLeft = rect.x, closestRight = rect.XMost();
|
||||
for (PRInt32 n = aLine->GetChildCount(); n;
|
||||
--n, frame = frame->GetNextSibling()) {
|
||||
if (!SelfIsSelectable(frame) || frame->IsEmpty())
|
||||
continue;
|
||||
nsRect frameRect = frame->GetRect();
|
||||
if (aPoint.x >= frameRect.x) {
|
||||
if (aPoint.x < frameRect.XMost()) {
|
||||
return GetSelectionClosestFrameForChild(frame, aPoint);
|
||||
}
|
||||
if (frameRect.XMost() >= closestLeft) {
|
||||
closestFromLeft = frame;
|
||||
closestLeft = frameRect.XMost();
|
||||
}
|
||||
} else {
|
||||
if (frameRect.x <= closestRight) {
|
||||
closestFromRight = frame;
|
||||
closestRight = frameRect.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!closestFromLeft && !closestFromRight) {
|
||||
// We should only get here if there are no selectable frames on a line
|
||||
// XXX Do we need more elaborate handling here?
|
||||
return FrameTarget::Null();
|
||||
}
|
||||
if (closestFromLeft &&
|
||||
(!closestFromRight ||
|
||||
(abs(aPoint.x - closestLeft) <= abs(aPoint.x - closestRight)))) {
|
||||
return GetSelectionClosestFrameForChild(closestFromLeft, aPoint);
|
||||
}
|
||||
return GetSelectionClosestFrameForChild(closestFromRight, aPoint);
|
||||
}
|
||||
|
||||
// This method is for the special handling we do for block frames; they're
|
||||
// special because they represent paragraphs and because they are organized
|
||||
// into lines, which have bounds that are not stored elsewhere in the
|
||||
// frame tree. Returns a null FrameTarget for frames which are not
|
||||
// blocks or blocks with no lines.
|
||||
static FrameTarget GetSelectionClosestFrameForBlock(nsIFrame* aFrame,
|
||||
nsPoint aPoint)
|
||||
{
|
||||
nsresult rv;
|
||||
nsBlockFrame* bf; // used only for QI
|
||||
rv = aFrame->QueryInterface(kBlockFrameCID, (void**)&bf);
|
||||
if (NS_FAILED(rv))
|
||||
return FrameTarget::Null();
|
||||
|
||||
// This code searches for the correct line
|
||||
nsBlockFrame::line_iterator firstLine = bf->begin_lines();
|
||||
nsBlockFrame::line_iterator end = bf->end_lines();
|
||||
if (firstLine == end)
|
||||
return FrameTarget::Null();
|
||||
nsBlockFrame::line_iterator curLine = firstLine;
|
||||
nsBlockFrame::line_iterator closestLine = end;
|
||||
while (curLine != end) {
|
||||
// Check to see if our point lies with the line's Y bounds
|
||||
nscoord y = aPoint.y - curLine->mBounds.y;
|
||||
nscoord height = curLine->mBounds.height;
|
||||
if (y >= 0 && y < height) {
|
||||
closestLine = curLine;
|
||||
break; // We found the line; stop looking
|
||||
}
|
||||
if (y < 0)
|
||||
break;
|
||||
++curLine;
|
||||
}
|
||||
|
||||
if (closestLine == end) {
|
||||
nsBlockFrame::line_iterator prevLine = curLine.prev();
|
||||
nsBlockFrame::line_iterator nextLine = curLine;
|
||||
// Avoid empty lines
|
||||
while (nextLine != end && nextLine->IsEmpty())
|
||||
++nextLine;
|
||||
while (prevLine != end && prevLine->IsEmpty())
|
||||
--prevLine;
|
||||
|
||||
// This hidden pref dictates whether a point above or below all lines comes
|
||||
// up with a line or the beginning or end of the frame; 0 on Windows,
|
||||
// 1 on other platforms by default at the writing of this code
|
||||
PRInt32 dragOutOfFrame =
|
||||
nsContentUtils::GetIntPref("browser.drag_out_of_frame_style");
|
||||
|
||||
if (prevLine == end) {
|
||||
if (dragOutOfFrame == 1 || nextLine == end)
|
||||
return DrillDownToSelectionFrame(aFrame, PR_FALSE);
|
||||
closestLine = nextLine;
|
||||
} else if (nextLine == end) {
|
||||
if (dragOutOfFrame == 1)
|
||||
return DrillDownToSelectionFrame(aFrame, PR_TRUE);
|
||||
closestLine = prevLine;
|
||||
} else { // Figure out which line is closer
|
||||
if (aPoint.y - prevLine->mBounds.YMost() < nextLine->mBounds.y - aPoint.y)
|
||||
closestLine = prevLine;
|
||||
else
|
||||
closestLine = nextLine;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
FrameTarget target = GetSelectionClosestFrameForLine(bf, closestLine,
|
||||
aPoint);
|
||||
if (!target.IsNull())
|
||||
return target;
|
||||
++closestLine;
|
||||
} while (closestLine != end);
|
||||
// Fall back to just targeting the last targetable place
|
||||
return DrillDownToSelectionFrame(aFrame, PR_TRUE);
|
||||
}
|
||||
|
||||
// GetSelectionClosestFrame is the helper function that calculates the closest
|
||||
// frame to the given point.
|
||||
// It doesn't completely account for offset styles, so needs to be used in
|
||||
// restricted environments.
|
||||
// Cannot handle overlapping frames correctly, so it should recieve the output
|
||||
// of GetFrameForPoint
|
||||
// Guaranteed to return a valid FrameTarget
|
||||
static FrameTarget GetSelectionClosestFrame(nsIFrame* aFrame, nsPoint aPoint)
|
||||
{
|
||||
{
|
||||
// Handle blocks; if the frame isn't a block, the method fails
|
||||
FrameTarget target = GetSelectionClosestFrameForBlock(aFrame, aPoint);
|
||||
if (!target.IsNull())
|
||||
return target;
|
||||
}
|
||||
|
||||
nsIFrame *kid = aFrame->GetFirstChild(nsnull);
|
||||
|
||||
if (kid) {
|
||||
// Go through all the child frames to find the closest one
|
||||
|
||||
// Large number to force the comparison to succeed
|
||||
const nscoord HUGE_DISTANCE = nscoord_MAX;
|
||||
nscoord closestXDistance = HUGE_DISTANCE;
|
||||
nscoord closestYDistance = HUGE_DISTANCE;
|
||||
nsIFrame *closestFrame = nsnull;
|
||||
|
||||
do {
|
||||
if (!SelfIsSelectable(kid) || kid->IsEmpty())
|
||||
continue;
|
||||
|
||||
nsRect rect = kid->GetRect();
|
||||
|
||||
nscoord fromLeft = aPoint.x - rect.x;
|
||||
nscoord fromRight = aPoint.x - rect.XMost();
|
||||
|
||||
nscoord xDistance;
|
||||
if (fromLeft >= 0 && fromRight <= 0) {
|
||||
xDistance = 0;
|
||||
} else {
|
||||
xDistance = PR_MIN(abs(fromLeft), abs(fromRight));
|
||||
}
|
||||
|
||||
if (xDistance <= closestXDistance)
|
||||
{
|
||||
if (xDistance < closestXDistance)
|
||||
closestYDistance = HUGE_DISTANCE;
|
||||
|
||||
nscoord fromTop = aPoint.y - rect.y;
|
||||
nscoord fromBottom = aPoint.y - rect.YMost();
|
||||
|
||||
nscoord yDistance;
|
||||
if (fromTop >= 0 && fromBottom <= 0)
|
||||
yDistance = 0;
|
||||
else
|
||||
yDistance = PR_MIN(abs(fromTop), abs(fromBottom));
|
||||
|
||||
if (yDistance < closestYDistance)
|
||||
{
|
||||
closestXDistance = xDistance;
|
||||
closestYDistance = yDistance;
|
||||
closestFrame = kid;
|
||||
}
|
||||
}
|
||||
} while (kid = kid->GetNextSibling());
|
||||
if (closestFrame);
|
||||
return GetSelectionClosestFrameForChild(closestFrame, aPoint);
|
||||
}
|
||||
return FrameTarget(aFrame, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult nsFrame::GetContentAndOffsetsFromPoint(nsPresContext* aCX,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd,
|
||||
PRBool& aBeginFrameContent)
|
||||
PRBool& aKeepWithAbove)
|
||||
{
|
||||
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
|
||||
nsIFrame *closestFrame = nsnull;
|
||||
nsIFrame *kid = GetFirstChild(nsnull);
|
||||
// This section of code deals with special selection styles. Note that
|
||||
// -moz-none and -moz-all exist, even though they don't need to be explicitly
|
||||
// handled.
|
||||
// The offset is forced not to end up in generated content; content offsets
|
||||
// cannot represent content outside of the document's content tree.
|
||||
|
||||
if (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) {
|
||||
|
||||
// Skip over generated content kid frames, or frames
|
||||
// that don't have a proper parent-child relationship!
|
||||
|
||||
PRBool skipThisKid = (kid->GetStateBits() & NS_FRAME_GENERATED_CONTENT) != 0;
|
||||
|
||||
if (skipThisKid) {
|
||||
kid = kid->GetNextSibling();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Kid frame has content that has a proper parent-child
|
||||
// relationship. Now see if the aPoint inside it's bounding
|
||||
// rect or close by.
|
||||
|
||||
nsRect rect = kid->GetRect();
|
||||
|
||||
nscoord fromTop = aPoint.y - rect.y;
|
||||
nscoord fromBottom = aPoint.y - rect.y - rect.height;
|
||||
|
||||
PRInt32 yDistance;
|
||||
if (fromTop > 0 && fromBottom < 0)
|
||||
yDistance = 0;
|
||||
else
|
||||
yDistance = PR_MIN(abs(fromTop), abs(fromBottom));
|
||||
|
||||
if (yDistance <= closestYDistance && rect.width > 0 && rect.height > 0)
|
||||
{
|
||||
if (yDistance < closestYDistance)
|
||||
closestXDistance = HUGE_DISTANCE;
|
||||
|
||||
nscoord fromLeft = aPoint.x - rect.x;
|
||||
nscoord fromRight = aPoint.x - rect.x - rect.width;
|
||||
|
||||
PRInt32 xDistance;
|
||||
if (fromLeft > 0 && fromRight < 0)
|
||||
xDistance = 0;
|
||||
else
|
||||
xDistance = PR_MIN(abs(fromLeft), abs(fromRight));
|
||||
|
||||
if (xDistance == 0 && yDistance == 0)
|
||||
{
|
||||
closestFrame = kid;
|
||||
break;
|
||||
}
|
||||
|
||||
if (xDistance < closestXDistance || (xDistance == closestXDistance && rect.x <= aPoint.x))
|
||||
{
|
||||
// If we are only near (not directly over) then don't traverse a frame with independent
|
||||
// selection (e.g. text and list controls) unless we're already inside such a frame,
|
||||
// except in "browsewithcaret" mode, bug 268497.
|
||||
if (!(kid->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) ||
|
||||
(GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) ||
|
||||
nsContentUtils::GetBoolPref("accessibility.browsewithcaret")) {
|
||||
closestXDistance = xDistance;
|
||||
closestYDistance = yDistance;
|
||||
closestFrame = kid;
|
||||
}
|
||||
}
|
||||
// else if (xDistance > closestXDistance)
|
||||
// break;//done
|
||||
}
|
||||
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
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 - closestFrame->GetOffsetTo(this);
|
||||
return closestFrame->GetContentAndOffsetsFromPoint(aCX, newPoint,
|
||||
aNewContent,
|
||||
aContentOffset,
|
||||
aContentOffsetEnd,
|
||||
aBeginFrameContent);
|
||||
nsIFrame* adjustedFrame = this;
|
||||
PRBool frameAdjusted = PR_FALSE;
|
||||
for (nsIFrame* frame = this; frame; frame = frame->GetParent())
|
||||
{
|
||||
// These are the conditions that make all children not able to handle
|
||||
// a cursor.
|
||||
if (frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_NONE ||
|
||||
frame->GetStyleUIReset()->mUserSelect == NS_STYLE_USER_SELECT_ALL ||
|
||||
frame->IsGeneratedContentFrame()) {
|
||||
adjustedFrame = frame;
|
||||
frameAdjusted = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
// -moz-user-select: all needs special handling, because clicking on it
|
||||
// should lead to the whole frame being selected
|
||||
if (adjustedFrame->GetStyleUIReset()->mUserSelect ==
|
||||
NS_STYLE_USER_SELECT_ALL) {
|
||||
ContentOffsets selectOffset = GetOffsetsOfFrame(adjustedFrame);
|
||||
|
||||
NS_IF_ADDREF(*aNewContent = mContent->GetParent());
|
||||
if (*aNewContent){
|
||||
|
||||
PRInt32 contentOffset(aContentOffset); //temp to hold old value in case of failure
|
||||
|
||||
contentOffset = (*aNewContent)->IndexOf(mContent);
|
||||
if (contentOffset < 0)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
NS_IF_ADDREF(*aNewContent = selectOffset.content);
|
||||
aContentOffset = selectOffset.start;
|
||||
aContentOffsetEnd = selectOffset.end;
|
||||
aKeepWithAbove = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
// For other cases, try to find a closest frame starting from the parent of
|
||||
// the unselectable frame
|
||||
if (frameAdjusted)
|
||||
adjustedFrame = adjustedFrame->GetParent();
|
||||
|
||||
nsPoint adjustedPoint = aPoint + this->GetOffsetTo(adjustedFrame);
|
||||
FrameTarget closest = GetSelectionClosestFrame(adjustedFrame, adjustedPoint);
|
||||
|
||||
ContentOffsets offset = GetOffsetsOfFrame(closest.frame);
|
||||
// If the correct offset is at one end of a frame, use offset-based
|
||||
// calculation method
|
||||
if (closest.frameEdge) {
|
||||
NS_ADDREF(*aNewContent = offset.content);
|
||||
if (closest.afterFrame) {
|
||||
aContentOffset = offset.end;
|
||||
aKeepWithAbove = PR_FALSE;
|
||||
} else {
|
||||
aContentOffset = offset.start;
|
||||
aKeepWithAbove = PR_TRUE;
|
||||
}
|
||||
aContentOffset = contentOffset; //its clear save the result
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
nsPoint pt = aPoint - closest.frame->GetOffsetTo(this);
|
||||
nsresult rv = closest.frame->GetPositionHelper(pt, aNewContent,
|
||||
aContentOffset,
|
||||
aContentOffsetEnd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
aBeginFrameContent = PR_TRUE;
|
||||
nsRect thisRect(nsPoint(0, 0), GetSize());
|
||||
if (thisRect.Contains(aPoint))
|
||||
aContentOffsetEnd = aContentOffset +1;
|
||||
else
|
||||
{
|
||||
//if we are a collapsed frame then dont check to see if we need to skip past this content
|
||||
//see bug http://bugzilla.mozilla.org/show_bug.cgi?id=103888
|
||||
if (thisRect.width && thisRect.height && ((thisRect.x + thisRect.width) < aPoint.x || thisRect.y > aPoint.y))
|
||||
{
|
||||
aBeginFrameContent = PR_FALSE;
|
||||
aContentOffset++;
|
||||
}
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
// XXX should I add some kind of offset standardization?
|
||||
// consider <b>xxxxx</b><i>zzzzz</i>; should any click between the last
|
||||
// x and first z put the cursor in the same logical position in addition
|
||||
// to the same visual position?
|
||||
|
||||
NS_ASSERTION(*aNewContent == offset.content,
|
||||
"There should only be one possible content base");
|
||||
aKeepWithAbove = (aContentOffset == offset.start);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFrame::GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
{
|
||||
ContentOffsets offset = GetOffsetsOfFrame(this);
|
||||
|
||||
NS_IF_ADDREF(*aNewContent = offset.content);
|
||||
// Figure out whether the offsets should be over, after, or before the frame
|
||||
nsRect rect(nsPoint(0, 0), GetSize());
|
||||
|
||||
if (rect.Contains(aPoint)) {
|
||||
aContentOffset = offset.start;
|
||||
aContentOffsetEnd = offset.end;
|
||||
} else {
|
||||
PRBool isBlock = (GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE);
|
||||
PRBool isRtl = (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL);
|
||||
if ((isBlock && rect.y < aPoint.y) ||
|
||||
(!isBlock && ((isRtl && rect.x + rect.width < aPoint.x) ||
|
||||
(!isRtl && rect.x < aPoint.x)))) {
|
||||
aContentOffset = offset.end;
|
||||
aContentOffsetEnd = offset.end;
|
||||
} else {
|
||||
aContentOffset = offset.start;
|
||||
aContentOffsetEnd = offset.start;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -321,6 +321,11 @@ public:
|
||||
PRBool aJumpLines);
|
||||
|
||||
|
||||
// Helper for GetContentAndOffsetsFromPoint
|
||||
NS_IMETHOD GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
// Box layout methods
|
||||
NS_IMETHOD GetPrefSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
|
||||
NS_IMETHOD GetMinSize(nsBoxLayoutState& aBoxLayoutState, nsSize& aSize);
|
||||
|
@ -760,6 +760,11 @@ public:
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd,
|
||||
PRBool& aBeginFrameContent) = 0;
|
||||
// Helper for GetContentAndOffsetsFromPoint
|
||||
NS_IMETHOD GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd) = 0;
|
||||
|
||||
/**
|
||||
* This structure holds information about a cursor. mContainer represents a
|
||||
|
@ -340,9 +340,6 @@ public:
|
||||
NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset);
|
||||
NS_IMETHOD CommonPageMove(PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel);
|
||||
|
||||
NS_IMETHOD AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection,
|
||||
nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset);
|
||||
|
||||
NS_IMETHOD SetHint(HINT aHintRight);
|
||||
NS_IMETHOD GetHint(HINT *aHintRight);
|
||||
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
|
||||
@ -462,9 +459,6 @@ private:
|
||||
|
||||
nsresult NotifySelectionListeners(SelectionType aType); // add parameters to say collapsed etc?
|
||||
|
||||
// utility method to lookup frame style
|
||||
nsresult FrameOrParentHasSpecialSelectionStyle(nsIFrame* aFrame, PRUint8 aSelectionStyle, nsIFrame* *foundFrame);
|
||||
|
||||
nsTypedSelection *mDomSelections[nsISelectionController::NUM_SELECTIONTYPES];
|
||||
|
||||
// Table selection support.
|
||||
@ -2468,21 +2462,6 @@ nsSelection::HandleDrag(nsPresContext *aPresContext, nsIFrame *aFrame, nsPoint&
|
||||
AdjustForMaintainedSelection(newContent, startPos))
|
||||
return NS_OK;
|
||||
|
||||
// do we have CSS that changes selection behaviour?
|
||||
{
|
||||
//add scope for nsCOMPtr
|
||||
PRBool changeSelection;
|
||||
nsCOMPtr<nsIContent> selectContent;
|
||||
PRInt32 newStart, newEnd;
|
||||
if (NS_SUCCEEDED(AdjustOffsetsFromStyle(newFrame, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
|
||||
&& changeSelection)
|
||||
{
|
||||
newContent = selectContent;
|
||||
startPos = newStart;
|
||||
contentOffsetEnd = newEnd;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
#ifdef VISUALSELECTION
|
||||
@ -3056,27 +3035,6 @@ nsSelection::NotifySelectionListeners(SelectionType aType)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSelection::FrameOrParentHasSpecialSelectionStyle(nsIFrame* aFrame, PRUint8 aSelectionStyle, nsIFrame* *foundFrame)
|
||||
{
|
||||
nsIFrame* thisFrame = aFrame;
|
||||
|
||||
while (thisFrame)
|
||||
{
|
||||
if (thisFrame->GetStyleUIReset()->mUserSelect == aSelectionStyle)
|
||||
{
|
||||
*foundFrame = thisFrame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
thisFrame = thisFrame->GetParent();
|
||||
}
|
||||
|
||||
*foundFrame = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Start of Table Selection methods
|
||||
|
||||
static PRBool IsCell(nsIContent *aContent)
|
||||
@ -4093,59 +4051,6 @@ nsSelection::CreateAndAddRange(nsIDOMNode *aParentNode, PRInt32 aOffset)
|
||||
|
||||
// End of Table Selection
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::AdjustOffsetsFromStyle(nsIFrame *aFrame, PRBool *changeSelection,
|
||||
nsIContent** outContent, PRInt32* outStartOffset, PRInt32* outEndOffset)
|
||||
{
|
||||
|
||||
*changeSelection = PR_FALSE;
|
||||
*outContent = nsnull;
|
||||
|
||||
nsresult rv;
|
||||
nsIFrame* selectAllFrame;
|
||||
rv = FrameOrParentHasSpecialSelectionStyle(aFrame, NS_STYLE_USER_SELECT_ALL, &selectAllFrame);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!selectAllFrame)
|
||||
return NS_OK;
|
||||
|
||||
nsIContent* selectAllContent = selectAllFrame->GetContent();
|
||||
if (selectAllContent)
|
||||
{
|
||||
nsCOMPtr<nsIContent> parentContent = selectAllContent->GetParent();
|
||||
if (parentContent)
|
||||
{
|
||||
PRInt32 startOffset = parentContent->IndexOf(selectAllContent);
|
||||
|
||||
if (startOffset < 0)
|
||||
{
|
||||
// hrmm, this is probably anonymous content. Let's go up another level
|
||||
// do we need to do this if we get the right frameSelection to start with?
|
||||
nsCOMPtr<nsIContent> superParent = parentContent->GetParent();
|
||||
if (superParent)
|
||||
{
|
||||
PRInt32 superStartOffset = superParent->IndexOf(parentContent);
|
||||
if (superStartOffset < 0)
|
||||
return NS_ERROR_FAILURE; // give up
|
||||
|
||||
parentContent = superParent;
|
||||
startOffset = superStartOffset;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*outContent = parentContent);
|
||||
|
||||
*outStartOffset = startOffset;
|
||||
*outEndOffset = startOffset + 1;
|
||||
|
||||
*changeSelection = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelection::SetHint(HINT aHintRight)
|
||||
{
|
||||
|
@ -294,21 +294,12 @@ public:
|
||||
NS_IMETHOD_(nsFrameState) GetDebugStateBits() const ;
|
||||
#endif
|
||||
|
||||
NS_IMETHOD GetPosition(nsPresContext* aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
NS_IMETHOD GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd);
|
||||
|
||||
NS_IMETHOD GetContentAndOffsetsFromPoint(nsPresContext* aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd,
|
||||
PRBool& aBeginFrameContent);
|
||||
|
||||
NS_IMETHOD GetPositionSlowly(nsPresContext* aPresContext,
|
||||
nsIRenderingContext * aRendContext,
|
||||
NS_IMETHOD GetPositionSlowly(nsIRenderingContext * aRendContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aOffset);
|
||||
@ -322,10 +313,6 @@ public:
|
||||
NS_IMETHOD PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos);
|
||||
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
|
||||
nsGUIEvent * aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
|
||||
NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const;
|
||||
|
||||
virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end);
|
||||
@ -3065,22 +3052,21 @@ nsTextFrame::PaintUnicodeText(nsPresContext* aPresContext,
|
||||
|
||||
//measure Spaced Textvoid
|
||||
nsresult
|
||||
nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
|
||||
nsIRenderingContext* aRendContext,
|
||||
nsTextFrame::GetPositionSlowly(nsIRenderingContext* aRendContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent** aNewContent,
|
||||
PRInt32& aOffset)
|
||||
|
||||
{
|
||||
// pre-condition tests
|
||||
NS_PRECONDITION(aPresContext && aRendContext && aNewContent, "null arg");
|
||||
if (!aPresContext || !aRendContext || !aNewContent) {
|
||||
NS_PRECONDITION(aRendContext && aNewContent, "null arg");
|
||||
if (!aRendContext || !aNewContent) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
// initialize out param
|
||||
*aNewContent = nsnull;
|
||||
|
||||
nsTextStyle ts(aPresContext, *aRendContext, mStyleContext);
|
||||
nsTextStyle ts(GetPresContext(), *aRendContext, mStyleContext);
|
||||
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing && !ts.mJustifying) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
@ -3119,7 +3105,7 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Transform text from content into renderable form
|
||||
nsTextTransformer tx(aPresContext);
|
||||
nsTextTransformer tx(GetPresContext());
|
||||
PRInt32 textLength;
|
||||
PRIntn numJustifiableCharacter;
|
||||
|
||||
@ -3148,29 +3134,6 @@ nsTextFrame::GetPositionSlowly(nsPresContext* aPresContext,
|
||||
#endif // IBMBIDI
|
||||
|
||||
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numJustifiableCharacter);
|
||||
|
||||
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||
PRInt32 prefInt =
|
||||
nsContentUtils::GetIntPref("browser.drag_out_of_frame_style");
|
||||
|
||||
PRBool outofstylehandled = PR_FALSE;
|
||||
|
||||
if (prefInt)
|
||||
{
|
||||
if (aPoint.y < 0)//above rectangle
|
||||
{
|
||||
aOffset = mContentOffset;
|
||||
outofstylehandled = PR_TRUE;
|
||||
}
|
||||
else if (aPoint.y > mRect.height)
|
||||
{
|
||||
aOffset = mContentOffset + mContentLength;
|
||||
outofstylehandled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!outofstylehandled) //then we drag to closest X point and dont worry about the 'Y'
|
||||
//END STYLE RULE
|
||||
{
|
||||
//the following will first get the index into the PAINTBUFFER then the actual content
|
||||
nscoord adjustedX = PR_MAX(0,aPoint.x);
|
||||
@ -4033,16 +3996,15 @@ nsTextFrame::PaintAsciiText(nsPresContext* aPresContext,
|
||||
// display of selection is based on the compressed text.
|
||||
//---------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
nsTextFrame::GetPositionHelper(const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd)
|
||||
|
||||
{
|
||||
// pre-condition tests
|
||||
NS_PRECONDITION(aPresContext && aNewContent, "null arg");
|
||||
if (!aPresContext || !aNewContent) {
|
||||
NS_PRECONDITION(aNewContent, "null arg");
|
||||
if (!aNewContent) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
// initialize out param
|
||||
@ -4052,14 +4014,14 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
||||
if (mState & NS_FRAME_IS_DIRTY)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||
nsIPresShell *shell = GetPresContext()->GetPresShell();
|
||||
if (shell) {
|
||||
nsCOMPtr<nsIRenderingContext> rendContext;
|
||||
nsresult rv = shell->CreateRenderingContext(this, getter_AddRefs(rendContext));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsTextStyle ts(aPresContext, *rendContext, mStyleContext);
|
||||
nsTextStyle ts(GetPresContext(), *rendContext, mStyleContext);
|
||||
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing || ts.mJustifying) {
|
||||
nsresult result = GetPositionSlowly(aPresContext, rendContext, aPoint, aNewContent,
|
||||
nsresult result = GetPositionSlowly(rendContext, aPoint, aNewContent,
|
||||
aContentOffset);
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
return result;
|
||||
@ -4077,39 +4039,17 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
||||
SetFontFromStyle(rendContext, mStyleContext);
|
||||
|
||||
// Get the renderable form of the text
|
||||
nsTextTransformer tx(aPresContext);
|
||||
nsTextTransformer tx(GetPresContext());
|
||||
PRInt32 textLength;
|
||||
// no need to worry about justification, that's always on the slow path
|
||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||
|
||||
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||
PRInt32 prefInt =
|
||||
nsContentUtils::GetIntPref("browser.drag_out_of_frame_style");
|
||||
PRBool outofstylehandled = PR_FALSE;
|
||||
|
||||
if (prefInt)
|
||||
{
|
||||
if (aPoint.y < 0)//above rectangle
|
||||
{
|
||||
aContentOffset = mContentOffset;
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
outofstylehandled = PR_TRUE;
|
||||
}
|
||||
else if (aPoint.y > mRect.height)
|
||||
{
|
||||
aContentOffset = mContentOffset + mContentLength;
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
outofstylehandled = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (textLength <= 0) {
|
||||
aContentOffset = mContentOffset;
|
||||
aContentOffsetEnd = aContentOffset;
|
||||
}
|
||||
else if (!outofstylehandled) //then we need to track based on the X coord only
|
||||
else
|
||||
{
|
||||
//END STYLE IF
|
||||
PRInt32* ip = indexBuffer.mBuffer;
|
||||
|
||||
PRInt32 indx;
|
||||
@ -4196,42 +4136,6 @@ nsTextFrame::GetPosition(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::GetContentAndOffsetsFromPoint(nsPresContext* aPresContext,
|
||||
const nsPoint& aPoint,
|
||||
nsIContent ** aNewContent,
|
||||
PRInt32& aContentOffset,
|
||||
PRInt32& aContentOffsetEnd,
|
||||
PRBool& aBeginFrameContent)
|
||||
{
|
||||
if (!aNewContent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aNewContent = nsnull;//initialize
|
||||
aContentOffset = 0;
|
||||
aContentOffsetEnd = 0;
|
||||
aBeginFrameContent = 0;
|
||||
|
||||
DEBUG_VERIFY_NOT_DIRTY(mState);
|
||||
if (mState & NS_FRAME_IS_DIRTY)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsPoint newPoint;
|
||||
newPoint.y = aPoint.y;
|
||||
if (aPoint.x < 0)
|
||||
newPoint.x = 0;
|
||||
else
|
||||
newPoint.x = aPoint.x;
|
||||
nsresult rv = GetPosition(aPresContext, newPoint, aNewContent, aContentOffset, aContentOffsetEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (aContentOffset == mContentOffset)
|
||||
aBeginFrameContent = PR_TRUE;
|
||||
else
|
||||
aBeginFrameContent = PR_FALSE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// [HACK] Foward Declarations
|
||||
void ForceDrawFrame(nsFrame * aFrame);
|
||||
|
||||
@ -5120,38 +5024,6 @@ nsTextFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
{
|
||||
if (DisplaySelection(aPresContext) == nsISelectionController::SELECTION_OFF) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMouseEvent *me = (nsMouseEvent *)aEvent;
|
||||
if (!me) return NS_OK;
|
||||
|
||||
// Triple- and greater click counts are handled by nsFrame.
|
||||
if (me->clickCount > 2)
|
||||
return nsFrame::HandleMultiplePress(aPresContext, aEvent, aEventStatus);
|
||||
|
||||
// Double-click: word selection, handled here:
|
||||
PRInt32 startPos = 0;
|
||||
PRInt32 contentOffsetEnd = 0;
|
||||
nsCOMPtr<nsIContent> newContent;
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
|
||||
nsresult rv = GetPosition(aPresContext, pt,
|
||||
getter_AddRefs(newContent), startPos,
|
||||
contentOffsetEnd);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return PeekBackwardAndForward(eSelectWord, eSelectWord, startPos,
|
||||
aPresContext, PR_FALSE);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user