Bug 1216096: restore previous RTL caret behaviour by backout of bug 1164963, bug 1177505, and bug 1180417. r=jfkthame

This commit is contained in:
Simon Montagu 2015-11-10 04:42:23 -08:00
parent c7090ef533
commit 3457b582d2
8 changed files with 38 additions and 74 deletions

View File

@ -734,42 +734,31 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame,
#endif #endif
#endif #endif
nsIFrame* frame0 = frameCount > 0 ? aBpd->FrameAt(0) : nullptr; if (runCount == 1 && frameCount == 1 &&
// Non-bidi frames
if (runCount == 1 &&
aBpd->mParagraphDepth == 0 && aBpd->GetDirection() == NSBIDI_LTR && aBpd->mParagraphDepth == 0 && aBpd->GetDirection() == NSBIDI_LTR &&
aBpd->GetParaLevel() == 0 && aBpd->GetParaLevel() == 0) {
frame0 && frame0 != NS_BIDI_CONTROL_FRAME && // We have a single left-to-right frame in a left-to-right paragraph,
!frame0->Properties().Get(nsIFrame::EmbeddingLevelProperty()) &&
!frame0->Properties().Get(nsIFrame::BaseLevelProperty())) {
// We have a left-to-right frame in a left-to-right paragraph,
// without bidi isolation from the surrounding text. // without bidi isolation from the surrounding text.
// The embedding level and base level frame properties aren't // Make sure that the embedding level and base level frame properties aren't
// set (because if they are this frame used to have some other direction, // set (because if they are this frame used to have some other direction,
// so we can't do this optimization) // so we can't do this optimization), and we're done.
nsIFrame* frame = aBpd->FrameAt(0);
// Make all continuations fluid within this run if (frame != NS_BIDI_CONTROL_FRAME &&
for (int i = 0; i < frameCount; ++i) { !frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()) &&
nsIFrame* frame = aBpd->FrameAt(i); !frame->Properties().Get(nsIFrame::BaseLevelProperty())) {
if (frame && frame != NS_BIDI_CONTROL_FRAME) {
JoinInlineAncestors(frame);
}
}
#ifdef DEBUG #ifdef DEBUG
#ifdef NOISY_BIDI #ifdef NOISY_BIDI
printf("early return for single direction frame %p\n", (void*)frame); printf("early return for single direction frame %p\n", (void*)frame);
#endif #endif
#endif #endif
frame->AddStateBits(NS_FRAME_IS_BIDI);
return NS_OK; return NS_OK;
}
} }
nsIFrame* firstFrame = nullptr; nsIFrame* firstFrame = nullptr;
nsIFrame* lastFrame = nullptr; nsIFrame* lastFrame = nullptr;
// Bidi frames
for (; ;) { for (; ;) {
if (fragmentLength <= 0) { if (fragmentLength <= 0) {
// Get the next frame from mLogicalFrames // Get the next frame from mLogicalFrames

View File

@ -115,14 +115,9 @@ AdjustCaretFrameForLineEnd(nsIFrame** aFrame, int32_t* aOffset)
} }
static bool static bool
IsKeyboardRTL() IsBidiUI()
{ {
bool isKeyboardRTL = false; return Preferences::GetBool("bidi.browser.ui");
nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
if (bidiKeyboard) {
bidiKeyboard->IsLangRTL(&isKeyboardRTL);
}
return isKeyboardRTL;
} }
nsCaret::nsCaret() nsCaret::nsCaret()
@ -503,21 +498,6 @@ nsCaret::SetCaretPosition(nsIDOMNode* aNode, int32_t aOffset)
SchedulePaint(); SchedulePaint();
} }
bool
nsCaret::IsBidiUI()
{
nsIFrame* frame = nullptr;
if(Selection* selection = GetSelectionInternal()) {
int32_t contentOffset;
frame = GetFrameAndOffset(selection, mOverrideContent, mOverrideOffset,
&contentOffset);
}
return (frame && frame->GetStateBits() & NS_FRAME_IS_BIDI) ||
Preferences::GetBool("bidi.browser.ui");
}
void void
nsCaret::CheckSelectionLanguageChange() nsCaret::CheckSelectionLanguageChange()
{ {
@ -525,8 +505,11 @@ nsCaret::CheckSelectionLanguageChange()
return; return;
} }
bool isKeyboardRTL = IsKeyboardRTL(); bool isKeyboardRTL = false;
nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
if (bidiKeyboard) {
bidiKeyboard->IsLangRTL(&isKeyboardRTL);
}
// Call SelectionLanguageChange on every paint. Mostly it will be a noop // Call SelectionLanguageChange on every paint. Mostly it will be a noop
// but it should be fast anyway. This guarantees we never paint the caret // but it should be fast anyway. This guarantees we never paint the caret
// at the wrong place. // at the wrong place.
@ -715,9 +698,8 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection,
if (theFrame->PresContext()->BidiEnabled()) if (theFrame->PresContext()->BidiEnabled())
{ {
// If there has been a reflow, take the caret Bidi level to be the level of the current frame // If there has been a reflow, take the caret Bidi level to be the level of the current frame
if (aBidiLevel & BIDI_LEVEL_UNDEFINED) { if (aBidiLevel & BIDI_LEVEL_UNDEFINED)
aBidiLevel = NS_GET_EMBEDDING_LEVEL(theFrame); aBidiLevel = NS_GET_EMBEDDING_LEVEL(theFrame);
}
int32_t start; int32_t start;
int32_t end; int32_t end;
@ -941,22 +923,21 @@ nsCaret::ComputeCaretRects(nsIFrame* aFrame, int32_t aFrameOffset,
} }
} }
// Simon -- make a hook to draw to the left or right of the caret to show keyboard language direction
aHookRect->SetEmpty(); aHookRect->SetEmpty();
if (!IsBidiUI()) {
Selection* selection = GetSelectionInternal();
if (!selection || !selection->GetFrameSelection()) {
return; return;
} }
if (IsBidiUI() || IsKeyboardRTL()) { bool isCaretRTL;
// If caret level is RTL, draw the hook on the left; if LTR, to the right nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
// if bidiKeyboard->IsLangRTL() fails, there is no way to tell the
// keyboard direction, or the user has no right-to-left keyboard
// installed, so we never draw the hook.
if (bidiKeyboard && NS_SUCCEEDED(bidiKeyboard->IsLangRTL(&isCaretRTL))) {
// If keyboard language is RTL, draw the hook on the left; if LTR, to the right
// The height of the hook rectangle is the same as the width of the caret // The height of the hook rectangle is the same as the width of the caret
// rectangle. // rectangle.
int caretBidiLevel = selection->GetFrameSelection()->GetCaretBidiLevel();
if (caretBidiLevel & BIDI_LEVEL_UNDEFINED) {
caretBidiLevel = NS_GET_EMBEDDING_LEVEL(aFrame);
}
bool isCaretRTL = caretBidiLevel % 2;
if (isVertical) { if (isVertical) {
bool isSidewaysLR = wm.IsVerticalLR() && !wm.IsLineInverted(); bool isSidewaysLR = wm.IsVerticalLR() && !wm.IsLineInverted();
if (isSidewaysLR) { if (isSidewaysLR) {

View File

@ -183,7 +183,6 @@ class nsCaret final : public nsISelectionListener
protected: protected:
static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure); static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure);
bool IsBidiUI();
void CheckSelectionLanguageChange(); void CheckSelectionLanguageChange();
void ResetBlinking(); void ResetBlinking();

View File

@ -3,14 +3,13 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head> </head>
<body onload="start()"> <body onload="start()">
<textarea onfocus="done()" style="-moz-appearance: none">س&lrm;</textarea> <textarea onfocus="done()" style="-moz-appearance: none">س</textarea>
<script> <script>
var textarea = document.querySelector("textarea"); var textarea = document.querySelector("textarea");
function start() { function start() {
textarea.focus(); textarea.focus();
} }
function done() { function done() {
textarea.selectionStart = textarea.selectionEnd = 2;
document.documentElement.removeAttribute("class"); document.documentElement.removeAttribute("class");
} }
</script> </script>

View File

@ -1,13 +1,12 @@
<html class="reftest-wait"> <html class="reftest-wait">
<body onload="start()"> <body onload="start()">
<textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s&rlm;</textarea> <textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s</textarea>
<script> <script>
var textarea = document.querySelector("textarea"); var textarea = document.querySelector("textarea");
function start() { function start() {
textarea.focus(); textarea.focus();
} }
function done() { function done() {
textarea.selectionStart = textarea.selectionEnd = 2;
document.documentElement.removeAttribute("class"); document.documentElement.removeAttribute("class");
} }
</script> </script>

View File

@ -621,9 +621,7 @@ private:
uint32_t aContentOffset, uint32_t aContentOffset,
nsSelectionAmount aAmount, nsSelectionAmount aAmount,
CaretAssociateHint aHint); CaretAssociateHint aHint);
void BidiLevelFromClick(nsIContent *aNewFocus, void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset);
uint32_t aContentOffset,
CaretAssociateHint aHint);
nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode, nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
uint32_t aContentOffset, uint32_t aContentOffset,
CaretAssociateHint aHint, CaretAssociateHint aHint,

View File

@ -1460,13 +1460,12 @@ void nsFrameSelection::BidiLevelFromMove(nsIPresShell* aPresShell,
* @param aContentOffset is the new caret position, as an offset into aNode * @param aContentOffset is the new caret position, as an offset into aNode
*/ */
void nsFrameSelection::BidiLevelFromClick(nsIContent *aNode, void nsFrameSelection::BidiLevelFromClick(nsIContent *aNode,
uint32_t aContentOffset, uint32_t aContentOffset)
CaretAssociateHint aHint)
{ {
nsIFrame* clickInFrame=nullptr; nsIFrame* clickInFrame=nullptr;
int32_t OffsetNotUsed; int32_t OffsetNotUsed;
clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, aHint, &OffsetNotUsed); clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, mHint, &OffsetNotUsed);
if (!clickInFrame) if (!clickInFrame)
return; return;
@ -1545,7 +1544,7 @@ nsFrameSelection::HandleClick(nsIContent* aNewFocus,
// Don't take focus when dragging off of a table // Don't take focus when dragging off of a table
if (!mDragSelectingCells) if (!mDragSelectingCells)
{ {
BidiLevelFromClick(aNewFocus, aContentOffset, aHint); BidiLevelFromClick(aNewFocus, aContentOffset);
PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON); PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON);
if (aContinueSelection && if (aContinueSelection &&
AdjustForMaintainedSelection(aNewFocus, aContentOffset)) AdjustForMaintainedSelection(aNewFocus, aContentOffset))

View File

@ -627,7 +627,7 @@ struct FlowLengthProperty {
}; };
int32_t nsTextFrame::GetInFlowContentLength() { int32_t nsTextFrame::GetInFlowContentLength() {
if (!PresContext()->BidiEnabled()) { if (!(mState & NS_FRAME_IS_BIDI)) {
return mContent->TextLength() - mContentOffset; return mContent->TextLength() - mContentOffset;
} }