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
nsIFrame* frame0 = frameCount > 0 ? aBpd->FrameAt(0) : nullptr;
// Non-bidi frames
if (runCount == 1 &&
if (runCount == 1 && frameCount == 1 &&
aBpd->mParagraphDepth == 0 && aBpd->GetDirection() == NSBIDI_LTR &&
aBpd->GetParaLevel() == 0 &&
frame0 && frame0 != NS_BIDI_CONTROL_FRAME &&
!frame0->Properties().Get(nsIFrame::EmbeddingLevelProperty()) &&
!frame0->Properties().Get(nsIFrame::BaseLevelProperty())) {
// We have a left-to-right frame in a left-to-right paragraph,
aBpd->GetParaLevel() == 0) {
// We have a single left-to-right frame in a left-to-right paragraph,
// 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,
// so we can't do this optimization)
// Make all continuations fluid within this run
for (int i = 0; i < frameCount; ++i) {
nsIFrame* frame = aBpd->FrameAt(i);
if (frame && frame != NS_BIDI_CONTROL_FRAME) {
JoinInlineAncestors(frame);
}
}
// so we can't do this optimization), and we're done.
nsIFrame* frame = aBpd->FrameAt(0);
if (frame != NS_BIDI_CONTROL_FRAME &&
!frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()) &&
!frame->Properties().Get(nsIFrame::BaseLevelProperty())) {
#ifdef DEBUG
#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
return NS_OK;
frame->AddStateBits(NS_FRAME_IS_BIDI);
return NS_OK;
}
}
nsIFrame* firstFrame = nullptr;
nsIFrame* lastFrame = nullptr;
// Bidi frames
for (; ;) {
if (fragmentLength <= 0) {
// Get the next frame from mLogicalFrames

View File

@ -115,14 +115,9 @@ AdjustCaretFrameForLineEnd(nsIFrame** aFrame, int32_t* aOffset)
}
static bool
IsKeyboardRTL()
IsBidiUI()
{
bool isKeyboardRTL = false;
nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
if (bidiKeyboard) {
bidiKeyboard->IsLangRTL(&isKeyboardRTL);
}
return isKeyboardRTL;
return Preferences::GetBool("bidi.browser.ui");
}
nsCaret::nsCaret()
@ -503,21 +498,6 @@ nsCaret::SetCaretPosition(nsIDOMNode* aNode, int32_t aOffset)
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
nsCaret::CheckSelectionLanguageChange()
{
@ -525,8 +505,11 @@ nsCaret::CheckSelectionLanguageChange()
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
// but it should be fast anyway. This guarantees we never paint the caret
// at the wrong place.
@ -715,9 +698,8 @@ nsCaret::GetCaretFrameForNodeOffset(nsFrameSelection* aFrameSelection,
if (theFrame->PresContext()->BidiEnabled())
{
// 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);
}
int32_t start;
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();
Selection* selection = GetSelectionInternal();
if (!selection || !selection->GetFrameSelection()) {
if (!IsBidiUI()) {
return;
}
if (IsBidiUI() || IsKeyboardRTL()) {
// If caret level is RTL, draw the hook on the left; if LTR, to the right
bool isCaretRTL;
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
// rectangle.
int caretBidiLevel = selection->GetFrameSelection()->GetCaretBidiLevel();
if (caretBidiLevel & BIDI_LEVEL_UNDEFINED) {
caretBidiLevel = NS_GET_EMBEDDING_LEVEL(aFrame);
}
bool isCaretRTL = caretBidiLevel % 2;
if (isVertical) {
bool isSidewaysLR = wm.IsVerticalLR() && !wm.IsLineInverted();
if (isSidewaysLR) {

View File

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

View File

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

View File

@ -1,13 +1,12 @@
<html class="reftest-wait">
<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>
var textarea = document.querySelector("textarea");
function start() {
textarea.focus();
}
function done() {
textarea.selectionStart = textarea.selectionEnd = 2;
document.documentElement.removeAttribute("class");
}
</script>

View File

@ -621,9 +621,7 @@ private:
uint32_t aContentOffset,
nsSelectionAmount aAmount,
CaretAssociateHint aHint);
void BidiLevelFromClick(nsIContent *aNewFocus,
uint32_t aContentOffset,
CaretAssociateHint aHint);
void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset);
nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
uint32_t aContentOffset,
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
*/
void nsFrameSelection::BidiLevelFromClick(nsIContent *aNode,
uint32_t aContentOffset,
CaretAssociateHint aHint)
uint32_t aContentOffset)
{
nsIFrame* clickInFrame=nullptr;
int32_t OffsetNotUsed;
clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, aHint, &OffsetNotUsed);
clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, mHint, &OffsetNotUsed);
if (!clickInFrame)
return;
@ -1545,7 +1544,7 @@ nsFrameSelection::HandleClick(nsIContent* aNewFocus,
// Don't take focus when dragging off of a table
if (!mDragSelectingCells)
{
BidiLevelFromClick(aNewFocus, aContentOffset, aHint);
BidiLevelFromClick(aNewFocus, aContentOffset);
PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON);
if (aContinueSelection &&
AdjustForMaintainedSelection(aNewFocus, aContentOffset))

View File

@ -627,7 +627,7 @@ struct FlowLengthProperty {
};
int32_t nsTextFrame::GetInFlowContentLength() {
if (!PresContext()->BidiEnabled()) {
if (!(mState & NS_FRAME_IS_BIDI)) {
return mContent->TextLength() - mContentOffset;
}
@ -639,7 +639,7 @@ int32_t nsTextFrame::GetInFlowContentLength() {
* mContentOffset but this frame is empty, logically it might be before the
* start of the cached flow.
*/
if (flowLength &&
if (flowLength &&
(flowLength->mStartOffset < mContentOffset ||
(flowLength->mStartOffset == mContentOffset && GetContentEnd() > mContentOffset)) &&
flowLength->mEndFlowOffset > mContentOffset) {