зеркало из https://github.com/mozilla/gecko-dev.git
Bug 555642 part.1 nsCaret should have a way to override the caret visible state for hiding caret temporarily and nsEditor should hide caret if composition string doesn't have caret information r=roc
This commit is contained in:
Родитель
ed11d345e0
Коммит
3645c1dbaf
|
@ -223,7 +223,12 @@ IMETextTxn::SetIMESelection(nsEditor& aEditor,
|
|||
static_cast<uint32_t>(caretOffset) <= maxOffset);
|
||||
rv = selection->Collapse(aTextNode, caretOffset);
|
||||
setCaret = setCaret || NS_SUCCEEDED(rv);
|
||||
NS_ASSERTION(setCaret, "Failed to collapse normal selection");
|
||||
if (NS_WARN_IF(!setCaret)) {
|
||||
continue;
|
||||
}
|
||||
// If caret range is specified explicitly, we should show the caret if
|
||||
// it should be so.
|
||||
aEditor.HideCaret(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -292,6 +297,8 @@ IMETextTxn::SetIMESelection(nsEditor& aEditor,
|
|||
rv = selection->Collapse(aTextNode, caretOffset);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to set caret at the end of composition string");
|
||||
// If caret range isn't specified explicitly, we should hide the caret.
|
||||
aEditor.HideCaret(true);
|
||||
}
|
||||
|
||||
rv = selection->EndBatchChanges();
|
||||
|
|
|
@ -147,6 +147,7 @@ nsEditor::nsEditor()
|
|||
, mDidPostCreate(false)
|
||||
, mDispatchInputEvent(true)
|
||||
, mIsInEditAction(false)
|
||||
, mHidingCaret(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -158,6 +159,8 @@ nsEditor::~nsEditor()
|
|||
mComposition->OnEditorDestroyed();
|
||||
mComposition = nullptr;
|
||||
}
|
||||
// If this editor is still hiding the caret, we need to restore it.
|
||||
HideCaret(false);
|
||||
mTxnMgr = nullptr;
|
||||
|
||||
delete mPhonetic;
|
||||
|
@ -464,6 +467,8 @@ nsEditor::PreDestroy(bool aDestroyingFrames)
|
|||
|
||||
// Unregister event listeners
|
||||
RemoveEventListeners();
|
||||
// If this editor is still hiding the caret, we need to restore it.
|
||||
HideCaret(false);
|
||||
mActionListeners.Clear();
|
||||
mEditorObservers.Clear();
|
||||
mDocStateListeners.Clear();
|
||||
|
@ -2065,6 +2070,10 @@ nsEditor::EndIMEComposition()
|
|||
}
|
||||
}
|
||||
|
||||
// Composition string may have hidden the caret. Therefore, we need to
|
||||
// cancel it here.
|
||||
HideCaret(false);
|
||||
|
||||
/* reset the data we need to construct a transaction */
|
||||
mIMETextNode = nullptr;
|
||||
mIMETextOffset = 0;
|
||||
|
@ -5258,3 +5267,23 @@ nsEditor::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
|
|||
}
|
||||
return minOffset < INT32_MAX ? minOffset : -1;
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::HideCaret(bool aHide)
|
||||
{
|
||||
if (mHidingCaret == aHide) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
NS_ENSURE_TRUE_VOID(presShell);
|
||||
nsRefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
NS_ENSURE_TRUE_VOID(caret);
|
||||
|
||||
mHidingCaret = aHide;
|
||||
if (aHide) {
|
||||
caret->AddForceHide();
|
||||
} else {
|
||||
caret->RemoveForceHide();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -824,6 +824,13 @@ public:
|
|||
void FindBetterInsertionPoint(nsCOMPtr<nsINode>& aNode,
|
||||
int32_t& aOffset);
|
||||
|
||||
/**
|
||||
* HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
|
||||
* with nsCaret::RemoveForceHide(). This does NOT set visibility of
|
||||
* nsCaret. Therefore, this is stateless.
|
||||
*/
|
||||
void HideCaret(bool aHide);
|
||||
|
||||
protected:
|
||||
enum Tristate {
|
||||
eTriUnset,
|
||||
|
@ -883,6 +890,7 @@ protected:
|
|||
bool mDidPostCreate; // whether PostCreate has been called
|
||||
bool mDispatchInputEvent;
|
||||
bool mIsInEditAction; // true while the instance is handling an edit action
|
||||
bool mHidingCaret; // whether caret is hidden forcibly.
|
||||
|
||||
friend bool NSCanUnload(nsISupports* serviceMgr);
|
||||
friend class nsAutoTxnsConserveSelection;
|
||||
|
|
|
@ -127,8 +127,9 @@ IsKeyboardRTL()
|
|||
|
||||
nsCaret::nsCaret()
|
||||
: mOverrideOffset(0)
|
||||
, mIsBlinkOn(false)
|
||||
, mBlinkCount(-1)
|
||||
, mHideCount(0)
|
||||
, mIsBlinkOn(false)
|
||||
, mVisible(false)
|
||||
, mReadOnly(false)
|
||||
, mShowDuringSelection(false)
|
||||
|
@ -266,7 +267,7 @@ void nsCaret::SetVisible(bool inMakeVisible)
|
|||
|
||||
bool nsCaret::IsVisible()
|
||||
{
|
||||
if (!mVisible) {
|
||||
if (!mVisible || mHideCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -303,6 +304,25 @@ bool nsCaret::IsVisible()
|
|||
return true;
|
||||
}
|
||||
|
||||
void nsCaret::AddForceHide()
|
||||
{
|
||||
MOZ_ASSERT(mHideCount < UINT32_MAX);
|
||||
if (++mHideCount > 1) {
|
||||
return;
|
||||
}
|
||||
ResetBlinking();
|
||||
SchedulePaint();
|
||||
}
|
||||
|
||||
void nsCaret::RemoveForceHide()
|
||||
{
|
||||
if (!mHideCount || --mHideCount) {
|
||||
return;
|
||||
}
|
||||
ResetBlinking();
|
||||
SchedulePaint();
|
||||
}
|
||||
|
||||
void nsCaret::SetCaretReadOnly(bool inMakeReadonly)
|
||||
{
|
||||
mReadOnly = inMakeReadonly;
|
||||
|
@ -622,7 +642,7 @@ void nsCaret::ResetBlinking()
|
|||
{
|
||||
mIsBlinkOn = true;
|
||||
|
||||
if (mReadOnly || !mVisible) {
|
||||
if (mReadOnly || !mVisible || mHideCount) {
|
||||
StopBlinking();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,21 @@ class nsCaret final : public nsISelectionListener
|
|||
* because we're in non-editable/disabled content.
|
||||
*/
|
||||
bool IsVisible();
|
||||
/**
|
||||
* AddForceHide() increases mHideCount and hide the caret even if
|
||||
* SetVisible(true) has been or will be called. This is useful when the
|
||||
* caller wants to hide caret temporarily and it needs to cancel later.
|
||||
* Especially, in the latter case, it's too difficult to decide if the
|
||||
* caret should be actually visible or not because caret visible state
|
||||
* is set from a lot of event handlers. So, it's very stateful.
|
||||
*/
|
||||
void AddForceHide();
|
||||
/**
|
||||
* RemoveForceHide() decreases mHideCount if it's over 0.
|
||||
* If the value becomes 0, this may show the caret if SetVisible(true)
|
||||
* has been called.
|
||||
*/
|
||||
void RemoveForceHide();
|
||||
/** SetCaretReadOnly set the appearance of the caret
|
||||
* @param inMakeReadonly true to show the caret in a 'read only' state,
|
||||
* false to show the caret in normal, editing state
|
||||
|
@ -201,17 +216,22 @@ protected:
|
|||
* Ignored if mOverrideContent is null.
|
||||
*/
|
||||
int32_t mOverrideOffset;
|
||||
|
||||
/**
|
||||
* mIsBlinkOn is true when we're in a blink cycle where the caret is on.
|
||||
*/
|
||||
bool mIsBlinkOn;
|
||||
/**
|
||||
* mBlinkCount is used to control the number of times to blink the caret
|
||||
* before stopping the blink. This is reset each time we reset the
|
||||
* blinking.
|
||||
*/
|
||||
int32_t mBlinkCount;
|
||||
/**
|
||||
* mHideCount is not 0, it means that somebody doesn't want the caret
|
||||
* to be visible. See AddForceHide() and RemoveForceHide().
|
||||
*/
|
||||
uint32_t mHideCount;
|
||||
|
||||
/**
|
||||
* mIsBlinkOn is true when we're in a blink cycle where the caret is on.
|
||||
*/
|
||||
bool mIsBlinkOn;
|
||||
/**
|
||||
* mIsVisible is true when SetVisible was last called with 'true'.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче