зеркало из https://github.com/mozilla/gecko-dev.git
Enable PeekOffset to find the visual beginning/end of a line, and use use it for bidi caret positioning. bug=302051 r=smontagu sr=roc
This commit is contained in:
Родитель
5defba927b
Коммит
cee7609648
|
@ -731,19 +731,15 @@ nsCaret::GetCaretFrameForNodeOffset(nsIContent* aContentNode,
|
|||
// if there is no frameBefore, we must be at the beginning of the line
|
||||
// so we stay with the current frame.
|
||||
// Exception: when the first frame on the line has a different Bidi level from the paragraph level, there is no
|
||||
// real frame for the caret to be in. We have to find the first frame whose level is the same as the
|
||||
// paragraph level, and put the caret at the end of the frame before that.
|
||||
// real frame for the caret to be in. We have to find the visually first frame on the line.
|
||||
PRUint8 baseLevel = NS_GET_BASE_LEVEL(frameAfter);
|
||||
if (baseLevel != levelAfter)
|
||||
{
|
||||
if (NS_SUCCEEDED(frameSelection->GetFrameFromLevel(frameAfter, eDirNext, baseLevel, &theFrame)))
|
||||
{
|
||||
theFrame->GetOffsets(start, end);
|
||||
levelAfter = NS_GET_EMBEDDING_LEVEL(theFrame);
|
||||
if (baseLevel & 1) // RTL paragraph: caret to the right of the rightmost character
|
||||
theFrameOffset = (levelAfter & 1) ? start : end;
|
||||
else // LTR paragraph: caret to the left of the leftmost character
|
||||
theFrameOffset = (levelAfter & 1) ? end : start;
|
||||
nsPeekOffsetStruct pos;
|
||||
pos.SetData(eSelectBeginLine, eDirPrevious, 0, 0, PR_FALSE, PR_TRUE, PR_FALSE, PR_TRUE);
|
||||
if (NS_SUCCEEDED(frameAfter->PeekOffset(presContext, &pos))) {
|
||||
theFrame = pos.mResultFrame;
|
||||
theFrameOffset = pos.mContentOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -766,22 +762,16 @@ nsCaret::GetCaretFrameForNodeOffset(nsIContent* aContentNode,
|
|||
{
|
||||
// if there is no frameAfter, we must be at the end of the line
|
||||
// so we stay with the current frame.
|
||||
//
|
||||
// Exception: when the last frame on the line has a different Bidi level from the paragraph level, there is no
|
||||
// real frame for the caret to be in. We have to find the last frame whose level is the same as the
|
||||
// paragraph level, and put the caret at the end of the frame after that.
|
||||
|
||||
// real frame for the caret to be in. We have to find the visually last frame on the line.
|
||||
PRUint8 baseLevel = NS_GET_BASE_LEVEL(frameBefore);
|
||||
if (baseLevel != levelBefore)
|
||||
{
|
||||
if (NS_SUCCEEDED(frameSelection->GetFrameFromLevel(frameBefore, eDirPrevious, baseLevel, &theFrame)))
|
||||
{
|
||||
theFrame->GetOffsets(start, end);
|
||||
levelBefore = NS_GET_EMBEDDING_LEVEL(theFrame);
|
||||
if (baseLevel & 1) // RTL paragraph: caret to the left of the leftmost character
|
||||
theFrameOffset = (levelBefore & 1) ? end : start;
|
||||
else // RTL paragraph: caret to the right of the rightmost character
|
||||
theFrameOffset = (levelBefore & 1) ? start : end;
|
||||
nsPeekOffsetStruct pos;
|
||||
pos.SetData(eSelectEndLine, eDirNext, 0, 0, PR_FALSE, PR_TRUE, PR_FALSE, PR_TRUE);
|
||||
if (NS_SUCCEEDED(frameBefore->PeekOffset(presContext, &pos))) {
|
||||
theFrame = pos.mResultFrame;
|
||||
theFrameOffset = pos.mContentOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4364,17 +4364,35 @@ nsFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
|||
nsIFrame *firstFrame;
|
||||
nsRect usedRect;
|
||||
PRUint32 lineFlags;
|
||||
it->GetLine(thisLine, &firstFrame, &lineFrameCount, usedRect, &lineFlags);
|
||||
|
||||
PRBool endOfLine = (eSelectEndLine == aPos->mAmount);
|
||||
nsIFrame* baseFrame = nsnull;
|
||||
nsIFrame* frame = firstFrame;
|
||||
for (PRInt32 count = lineFrameCount; count;
|
||||
--count, frame = frame->GetNextSibling()) {
|
||||
if (!frame->IsGeneratedContentFrame()) {
|
||||
baseFrame = frame;
|
||||
if (!endOfLine)
|
||||
break;
|
||||
PRBool endOfLine = (eSelectEndLine == aPos->mAmount);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
if (aPos->mVisual && aPresContext->BidiEnabled()) {
|
||||
PRBool lineIsRTL;
|
||||
it->GetDirection(&lineIsRTL);
|
||||
PRBool isReordered;
|
||||
nsIFrame *lastFrame;
|
||||
result = it->CheckLineOrder(thisLine, &isReordered, &firstFrame, &lastFrame);
|
||||
baseFrame = endOfLine ? lastFrame : firstFrame;
|
||||
nsBidiLevel embeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(baseFrame);
|
||||
// If the direction of the frame on the edge is opposite to that of the line,
|
||||
// we'll need to drill down to its opposite end, so reverse endOfLine.
|
||||
if ((embeddingLevel & 1) == !lineIsRTL)
|
||||
endOfLine = !endOfLine;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
it->GetLine(thisLine, &firstFrame, &lineFrameCount, usedRect, &lineFlags);
|
||||
|
||||
nsIFrame* frame = firstFrame;
|
||||
for (PRInt32 count = lineFrameCount; count;
|
||||
--count, frame = frame->GetNextSibling()) {
|
||||
if (!frame->IsGeneratedContentFrame()) {
|
||||
baseFrame = frame;
|
||||
if (!endOfLine)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!baseFrame)
|
||||
|
@ -4384,6 +4402,7 @@ nsFrame::PeekOffset(nsPresContext* aPresContext, nsPeekOffsetStruct *aPos)
|
|||
FrameContentRange range = GetRangeForFrame(targetFrame.frame);
|
||||
aPos->mResultContent = range.content;
|
||||
aPos->mContentOffset = endOfLine ? range.end : range.start;
|
||||
aPos->mResultFrame = targetFrame.frame;
|
||||
aPos->mAttachForward = (aPos->mContentOffset == range.start);
|
||||
if (!range.content)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -125,7 +125,7 @@ struct nsPeekOffsetStruct
|
|||
PRBool mIsKeyboardSelect;
|
||||
|
||||
// mVisual: Whether bidi caret behavior is visual (PR_TRUE) or logical (PR_FALSE).
|
||||
// Used with: eSelectCharacter, eSelectWord.
|
||||
// Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine.
|
||||
PRBool mVisual;
|
||||
|
||||
// mWordMovementType: An enum that determines whether to prefer the start or end of a word
|
||||
|
|
|
@ -1264,8 +1264,10 @@ nsFrameSelection::MoveCaret(PRUint32 aKeycode,
|
|||
|
||||
PRBool visualMovement =
|
||||
(aKeycode == nsIDOMKeyEvent::DOM_VK_BACK_SPACE ||
|
||||
aKeycode == nsIDOMKeyEvent::DOM_VK_DELETE) ?
|
||||
PR_FALSE : // Delete operations are always logical
|
||||
aKeycode == nsIDOMKeyEvent::DOM_VK_DELETE ||
|
||||
aKeycode == nsIDOMKeyEvent::DOM_VK_HOME ||
|
||||
aKeycode == nsIDOMKeyEvent::DOM_VK_END) ?
|
||||
PR_FALSE : // Delete operations and home/end are always logical
|
||||
mCaretMovementStyle == 1 || (mCaretMovementStyle == 2 && !aContinueSelection);
|
||||
|
||||
//set data using mLimiter to stop on scroll views. If we have a limiter then we stop peeking
|
||||
|
|
Загрузка…
Ссылка в новой задаче