зеркало из https://github.com/mozilla/gecko-dev.git
Bug 415707 - multiple text selection improvement doesn't work with double-click "word-by-word" or triple-click "paragraph" modes. r+sr=roc.
This commit is contained in:
Родитель
f6621ba654
Коммит
269b19b637
|
@ -1959,7 +1959,11 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
#ifdef XP_MACOSX
|
||||
if (me->isControl)
|
||||
return NS_OK;//short ciruit. hard coded for mac due to time restraints.
|
||||
PRBool control = me->isMeta;
|
||||
#else
|
||||
PRBool control = me->isControl;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsFrameSelection> fc = const_cast<nsFrameSelection*>(frameselection);
|
||||
if (me->clickCount >1 )
|
||||
{
|
||||
|
@ -1967,7 +1971,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
// so no need for nsWeakFrame.
|
||||
fc->SetMouseDownState(PR_TRUE);
|
||||
fc->SetMouseDoubleDown(PR_TRUE);
|
||||
return HandleMultiplePress(aPresContext, aEvent, aEventStatus);
|
||||
return HandleMultiplePress(aPresContext, aEvent, aEventStatus, control);
|
||||
}
|
||||
|
||||
if (!offsets.content)
|
||||
|
@ -2036,12 +2040,6 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
|
||||
fc->SetMouseDownState(PR_TRUE);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
PRBool control = me->isMeta;
|
||||
#else
|
||||
PRBool control = me->isControl;
|
||||
#endif
|
||||
|
||||
// Do not touch any nsFrame members after this point without adding
|
||||
// weakFrame checks.
|
||||
rv = fc->HandleClick(offsets.content, offsets.StartOffset(),
|
||||
|
@ -2074,8 +2072,9 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
*/
|
||||
NS_IMETHODIMP
|
||||
nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus)
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus,
|
||||
PRBool aControlHeld)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventStatus);
|
||||
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
|
||||
|
@ -2130,7 +2129,8 @@ nsFrame::HandleMultiplePress(nsPresContext* aPresContext,
|
|||
|
||||
return frame->PeekBackwardAndForward(beginAmount, endAmount,
|
||||
offsets.offset, aPresContext,
|
||||
beginAmount != eSelectWord);
|
||||
beginAmount != eSelectWord,
|
||||
aControlHeld);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2138,23 +2138,13 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
|||
nsSelectionAmount aAmountForward,
|
||||
PRInt32 aStartPos,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool aJumpLines)
|
||||
PRBool aJumpLines,
|
||||
PRBool aMultipleSelection)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selcon;
|
||||
nsresult rv = GetSelectionController(aPresContext, getter_AddRefs(selcon));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!selcon)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// Use peek offset one way then the other:
|
||||
nsCOMPtr<nsIContent> startContent;
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
nsCOMPtr<nsIContent> endContent;
|
||||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
|
||||
nsIFrame* baseFrame = this;
|
||||
PRInt32 baseOffset = aStartPos;
|
||||
nsresult rv;
|
||||
|
||||
if (aAmountBack == eSelectWord) {
|
||||
// To avoid selecting the previous word when at start of word,
|
||||
// first move one character forward.
|
||||
|
@ -2173,6 +2163,8 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
|||
baseOffset = pos.mContentOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Use peek offset one way then the other:
|
||||
nsPeekOffsetStruct startpos;
|
||||
startpos.SetData(aAmountBack,
|
||||
eDirPrevious,
|
||||
|
@ -2199,26 +2191,22 @@ nsFrame::PeekBackwardAndForward(nsSelectionAmount aAmountBack,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
endNode = do_QueryInterface(endpos.mResultContent, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
startNode = do_QueryInterface(startpos.mResultContent, &rv);
|
||||
// Keep frameSelection alive.
|
||||
nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
|
||||
|
||||
rv = frameSelection->HandleClick(startpos.mResultContent,
|
||||
startpos.mContentOffset, startpos.mContentOffset,
|
||||
PR_FALSE, aMultipleSelection,
|
||||
nsFrameSelection::HINTRIGHT);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Keep frameSelection alive.
|
||||
nsRefPtr<nsFrameSelection> frameSelection = GetFrameSelection();
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
if (NS_SUCCEEDED(selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(selection)))){
|
||||
rv = selection->Collapse(startNode,startpos.mContentOffset);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = selection->Extend(endNode,endpos.mContentOffset);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
//no release
|
||||
rv = frameSelection->HandleClick(endpos.mResultContent,
|
||||
endpos.mContentOffset, endpos.mContentOffset,
|
||||
PR_TRUE, PR_FALSE,
|
||||
nsFrameSelection::HINTLEFT);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// maintain selection
|
||||
return frameSelection->MaintainSelection(aAmountBack);
|
||||
|
|
|
@ -345,7 +345,8 @@ public:
|
|||
|
||||
NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
|
||||
nsGUIEvent * aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
nsEventStatus* aEventStatus,
|
||||
PRBool aControlHeld);
|
||||
|
||||
NS_IMETHOD HandleDrag(nsPresContext* aPresContext,
|
||||
nsGUIEvent * aEvent,
|
||||
|
@ -359,7 +360,8 @@ public:
|
|||
nsSelectionAmount aAmountForward,
|
||||
PRInt32 aStartPos,
|
||||
nsPresContext* aPresContext,
|
||||
PRBool aJumpLines);
|
||||
PRBool aJumpLines,
|
||||
PRBool aMultipleSelection);
|
||||
|
||||
|
||||
// Helper for GetContentAndOffsetsFromPoint; calculation of content offsets
|
||||
|
|
|
@ -219,6 +219,7 @@ public:
|
|||
PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE);
|
||||
nsresult AddItem(nsIDOMRange *aRange, PRInt32* aOutIndex = nsnull);
|
||||
nsresult RemoveItem(nsIDOMRange *aRange);
|
||||
nsresult RemoveCollapsedRanges();
|
||||
nsresult Clear(nsPresContext* aPresContext);
|
||||
|
||||
// methods for convenience. Note, these don't addref
|
||||
|
@ -236,7 +237,7 @@ public:
|
|||
nsDirection GetDirection(){return mDirection;}
|
||||
void SetDirection(nsDirection aDir){mDirection = aDir;}
|
||||
NS_IMETHOD CopyRangeToAnchorFocus(nsIDOMRange *aRange);
|
||||
|
||||
void ReplaceAnchorFocusRange(nsIDOMRange *aRange);
|
||||
|
||||
// NS_IMETHOD GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, PRInt32 aOffset, PRBool aIsEndNode, nsIFrame **aResultFrame);
|
||||
NS_IMETHOD GetPrimaryFrameForAnchorNode(nsIFrame **aResultFrame);
|
||||
|
@ -1628,12 +1629,6 @@ nsresult
|
|||
nsFrameSelection::MaintainSelection(nsSelectionAmount aAmount)
|
||||
{
|
||||
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult rv = mDomSelections[index]->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!range)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mMaintainedAmount = aAmount;
|
||||
|
||||
|
@ -1641,10 +1636,15 @@ nsFrameSelection::MaintainSelection(nsSelectionAmount aAmount)
|
|||
nsCOMPtr<nsIDOMNode> endNode;
|
||||
PRInt32 startOffset;
|
||||
PRInt32 endOffset;
|
||||
range->GetStartContainer(getter_AddRefs(startNode));
|
||||
range->GetEndContainer(getter_AddRefs(endNode));
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsresult rv;
|
||||
rv = mDomSelections[index]->GetAnchorNode(getter_AddRefs(startNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDomSelections[index]->GetFocusNode(getter_AddRefs(endNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDomSelections[index]->GetAnchorOffset(&startOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDomSelections[index]->GetFocusOffset(&endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mMaintainRange = nsnull;
|
||||
NS_NewRange(getter_AddRefs(mMaintainRange));
|
||||
|
@ -1731,55 +1731,44 @@ PRBool
|
|||
nsFrameSelection::AdjustForMaintainedSelection(nsIContent *aContent,
|
||||
PRInt32 aOffset)
|
||||
{
|
||||
// Is the desired content and offset currently in selection?
|
||||
// If the double click flag is set then don't continue selection if the
|
||||
// desired content and offset are currently inside a selection.
|
||||
// This will stop double click then mouse-drag from undoing the desired
|
||||
// selecting of a word.
|
||||
if (!mMaintainRange)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> rangenode;
|
||||
PRInt32 rangeOffset;
|
||||
mMaintainRange->GetStartContainer(getter_AddRefs(rangenode));
|
||||
mMaintainRange->GetStartOffset(&rangeOffset);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aContent);
|
||||
if (domNode)
|
||||
{
|
||||
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange = do_QueryInterface(mMaintainRange);
|
||||
if (nsrange)
|
||||
{
|
||||
PRBool insideSelection = PR_FALSE;
|
||||
nsrange->IsPointInRange(domNode, aOffset, &insideSelection);
|
||||
if (!domNode)
|
||||
return PR_FALSE;
|
||||
|
||||
PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
|
||||
|
||||
// Done when we find a range that we are in
|
||||
if (insideSelection)
|
||||
{
|
||||
mDomSelections[index]->Collapse(rangenode, rangeOffset);
|
||||
mMaintainRange->GetEndContainer(getter_AddRefs(rangenode));
|
||||
mMaintainRange->GetEndOffset(&rangeOffset);
|
||||
mDomSelections[index]->Extend(rangenode,rangeOffset);
|
||||
return PR_TRUE; // dragging in selection aborted
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> rangeStartNode, rangeEndNode;
|
||||
PRInt32 rangeStartOffset, rangeEndOffset;
|
||||
mMaintainRange->GetStartContainer(getter_AddRefs(rangeStartNode));
|
||||
mMaintainRange->GetEndContainer(getter_AddRefs(rangeEndNode));
|
||||
mMaintainRange->GetStartOffset(&rangeStartOffset);
|
||||
mMaintainRange->GetEndOffset(&rangeEndOffset);
|
||||
|
||||
PRInt32 relativePosition = CompareDOMPoints(rangenode, rangeOffset,
|
||||
domNode, aOffset);
|
||||
// if == 0 or -1 do nothing if < 0 then we need to swap direction
|
||||
if (relativePosition > 0
|
||||
&& (mDomSelections[index]->GetDirection() == eDirNext))
|
||||
{
|
||||
mMaintainRange->GetEndContainer(getter_AddRefs(rangenode));
|
||||
mMaintainRange->GetEndOffset(&rangeOffset);
|
||||
mDomSelections[index]->Collapse(rangenode, rangeOffset);
|
||||
PRInt32 relToStart = CompareDOMPoints(rangeStartNode, rangeStartOffset,
|
||||
domNode, aOffset);
|
||||
PRInt32 relToEnd = CompareDOMPoints(rangeEndNode, rangeEndOffset,
|
||||
domNode, aOffset);
|
||||
|
||||
// If aContent/aOffset is inside the maintained selection, or if it is on the
|
||||
// "anchor" side of the maintained selection, we need to do something.
|
||||
if (relToStart < 0 && relToEnd > 0 ||
|
||||
(relToStart > 0 &&
|
||||
mDomSelections[index]->GetDirection() == eDirNext) ||
|
||||
(relToEnd < 0 &&
|
||||
mDomSelections[index]->GetDirection() == eDirPrevious)) {
|
||||
// Set the current range to the maintained range.
|
||||
mDomSelections[index]->ReplaceAnchorFocusRange(mMaintainRange);
|
||||
if (relToStart < 0 && relToEnd > 0) {
|
||||
// We're inside the maintained selection, just keep it selected.
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if (relativePosition < 0
|
||||
&& (mDomSelections[index]->GetDirection() == eDirPrevious))
|
||||
mDomSelections[index]->Collapse(rangenode, rangeOffset);
|
||||
// Reverse the direction of the selection so that the anchor will be on the
|
||||
// far side of the maintained selection, relative to aContent/aOffset.
|
||||
mDomSelections[index]->SetDirection(relToStart > 0 ? eDirPrevious : eDirNext);
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1937,7 +1926,11 @@ nsFrameSelection::TakeFocus(nsIContent *aNewFocus,
|
|||
PRBool changes = mChangesDuringBatching;
|
||||
mBatching = 1;
|
||||
|
||||
if (aMultipleSelection){
|
||||
if (aMultipleSelection) {
|
||||
// Remove existing collapsed ranges as there's no point in having
|
||||
// non-anchor/focus collapsed ranges.
|
||||
mDomSelections[index]->RemoveCollapsedRanges();
|
||||
|
||||
nsCOMPtr<nsIDOMRange> newRange;
|
||||
NS_NewRange(getter_AddRefs(newRange));
|
||||
|
||||
|
@ -4066,6 +4059,24 @@ nsTypedSelection::RemoveItem(nsIDOMRange *aItem)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::RemoveCollapsedRanges()
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 i = 0;
|
||||
while (i < mRanges.Length()) {
|
||||
PRBool isCollapsed;
|
||||
rv = mRanges[i].mRange->GetCollapsed(&isCollapsed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isCollapsed) {
|
||||
rv = RemoveItem(mRanges[i].mRange);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::Clear(nsPresContext* aPresContext)
|
||||
|
@ -5637,6 +5648,18 @@ nsTypedSelection::CopyRangeToAnchorFocus(nsIDOMRange *aRange)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTypedSelection::ReplaceAnchorFocusRange(nsIDOMRange *aRange)
|
||||
{
|
||||
nsCOMPtr<nsPresContext> presContext;
|
||||
GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext) {
|
||||
selectFrames(presContext, mAnchorFocusRange, PR_FALSE);
|
||||
CopyRangeToAnchorFocus(aRange);
|
||||
selectFrames(presContext, mAnchorFocusRange, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Notes which might come in handy for extend:
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче