зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1164693 - Part 1: Directional caret should point in caret direction in bidi paragraphs. r=smontagu
This commit is contained in:
Родитель
f0737417db
Коммит
b1d966b6e0
|
@ -115,9 +115,14 @@ AdjustCaretFrameForLineEnd(nsIFrame** aFrame, int32_t* aOffset)
|
|||
}
|
||||
|
||||
static bool
|
||||
IsBidiUI()
|
||||
IsKeyboardRTL()
|
||||
{
|
||||
return Preferences::GetBool("bidi.browser.ui");
|
||||
bool isKeyboardRTL = false;
|
||||
nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
|
||||
if (bidiKeyboard) {
|
||||
bidiKeyboard->IsLangRTL(&isKeyboardRTL);
|
||||
}
|
||||
return isKeyboardRTL;
|
||||
}
|
||||
|
||||
nsCaret::nsCaret()
|
||||
|
@ -478,6 +483,21 @@ 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()
|
||||
{
|
||||
|
@ -485,11 +505,8 @@ nsCaret::CheckSelectionLanguageChange()
|
|||
return;
|
||||
}
|
||||
|
||||
bool isKeyboardRTL = false;
|
||||
nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard();
|
||||
if (bidiKeyboard) {
|
||||
bidiKeyboard->IsLangRTL(&isKeyboardRTL);
|
||||
}
|
||||
bool isKeyboardRTL = 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.
|
||||
|
@ -678,8 +695,9 @@ 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;
|
||||
|
@ -902,21 +920,22 @@ 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();
|
||||
if (!IsBidiUI()) {
|
||||
|
||||
Selection* selection = GetSelectionInternal();
|
||||
if (!selection || !selection->GetFrameSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
if (IsBidiUI() || IsKeyboardRTL()) {
|
||||
// If caret level 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) {
|
||||
aHookRect->SetRect(aCaretRect->XMost() - bidiIndicatorSize,
|
||||
aCaretRect->y + (isCaretRTL ? bidiIndicatorSize * -1 :
|
||||
|
|
|
@ -158,6 +158,7 @@ class nsCaret final : public nsISelectionListener
|
|||
protected:
|
||||
static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
bool IsBidiUI();
|
||||
void CheckSelectionLanguageChange();
|
||||
|
||||
void ResetBlinking();
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
</head>
|
||||
<body onload="start()">
|
||||
<textarea onfocus="done()" style="-moz-appearance: none">س</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>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<html class="reftest-wait">
|
||||
<body onload="start()">
|
||||
<textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s</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>
|
||||
|
|
|
@ -621,7 +621,9 @@ private:
|
|||
uint32_t aContentOffset,
|
||||
nsSelectionAmount aAmount,
|
||||
CaretAssociateHint aHint);
|
||||
void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset);
|
||||
void BidiLevelFromClick(nsIContent *aNewFocus,
|
||||
uint32_t aContentOffset,
|
||||
CaretAssociateHint aHint);
|
||||
nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
|
||||
uint32_t aContentOffset,
|
||||
CaretAssociateHint aHint,
|
||||
|
|
|
@ -1431,12 +1431,13 @@ 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)
|
||||
uint32_t aContentOffset,
|
||||
CaretAssociateHint aHint)
|
||||
{
|
||||
nsIFrame* clickInFrame=nullptr;
|
||||
int32_t OffsetNotUsed;
|
||||
|
||||
clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, mHint, &OffsetNotUsed);
|
||||
clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, aHint, &OffsetNotUsed);
|
||||
if (!clickInFrame)
|
||||
return;
|
||||
|
||||
|
@ -1515,7 +1516,7 @@ nsFrameSelection::HandleClick(nsIContent* aNewFocus,
|
|||
// Don't take focus when dragging off of a table
|
||||
if (!mDragSelectingCells)
|
||||
{
|
||||
BidiLevelFromClick(aNewFocus, aContentOffset);
|
||||
BidiLevelFromClick(aNewFocus, aContentOffset, aHint);
|
||||
PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON);
|
||||
if (aContinueSelection &&
|
||||
AdjustForMaintainedSelection(aNewFocus, aContentOffset))
|
||||
|
|
Загрузка…
Ссылка в новой задаче