зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1045270 - Part 1: Cache the selection state for the native anonymous text box inside number controls on the number control itself; r=smaug
This is needed because the text control and its nsTextEditorState will die together with the text control's frame.
This commit is contained in:
Родитель
7bf01ccf5c
Коммит
bc2e518c00
|
@ -1128,6 +1128,7 @@ HTMLInputElement::HTMLInputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||
, mNumberControlSpinnerIsSpinning(false)
|
||||
, mNumberControlSpinnerSpinsUp(false)
|
||||
, mPickerRunning(false)
|
||||
, mSelectionCached(true)
|
||||
{
|
||||
// We are in a type=text so we now we currenty need a nsTextEditorState.
|
||||
mInputData.mState = new nsTextEditorState(this);
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
#include "nsIContentPrefService2.h"
|
||||
#include "mozilla/Decimal.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsTextEditorState.h"
|
||||
|
||||
class nsDOMFileList;
|
||||
class nsIRadioGroupContainer;
|
||||
class nsIRadioGroupVisitor;
|
||||
class nsIRadioVisitor;
|
||||
class nsTextEditorState;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -250,6 +250,28 @@ public:
|
|||
|
||||
void MaybeLoadImage();
|
||||
|
||||
void SetSelectionProperties(const nsTextEditorState::SelectionProperties& aProps)
|
||||
{
|
||||
MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
|
||||
mSelectionCached = true;
|
||||
mSelectionProperties = aProps;
|
||||
}
|
||||
bool IsSelectionCached() const
|
||||
{
|
||||
MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
|
||||
return mSelectionCached;
|
||||
}
|
||||
void ClearSelectionCached()
|
||||
{
|
||||
MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
|
||||
mSelectionCached = false;
|
||||
}
|
||||
nsTextEditorState::SelectionProperties& GetSelectionProperties()
|
||||
{
|
||||
MOZ_ASSERT(mType == NS_FORM_INPUT_NUMBER);
|
||||
return mSelectionProperties;
|
||||
}
|
||||
|
||||
// nsITimerCallback
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
|
@ -1255,6 +1277,13 @@ protected:
|
|||
*/
|
||||
nsCOMPtr<nsITimer> mProgressTimer;
|
||||
|
||||
/**
|
||||
* The selection properties cache for number controls. This is needed because
|
||||
* the number controls don't recycle their text field, so the normal cache in
|
||||
* nsTextEditorState cannot do its job.
|
||||
*/
|
||||
nsTextEditorState::SelectionProperties mSelectionProperties;
|
||||
|
||||
// Step scale factor values, for input types that have one.
|
||||
static const Decimal kStepScaleFactorDate;
|
||||
static const Decimal kStepScaleFactorNumberRange;
|
||||
|
@ -1295,6 +1324,7 @@ protected:
|
|||
bool mNumberControlSpinnerIsSpinning : 1;
|
||||
bool mNumberControlSpinnerSpinsUp : 1;
|
||||
bool mPickerRunning : 1;
|
||||
bool mSelectionCached : 1;
|
||||
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
|
|
|
@ -8,6 +8,7 @@ EXPORTS += [
|
|||
'HTMLPropertiesCollection.h',
|
||||
'nsGenericHTMLElement.h',
|
||||
'nsHTMLDNSPrefetch.h',
|
||||
'nsTextEditorState.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "nsIController.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "nsNumberControlFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -1423,7 +1425,8 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
newEditor->AddEditorObserver(mTextListener);
|
||||
|
||||
// Restore our selection after being bound to a new frame
|
||||
if (mSelectionCached) {
|
||||
HTMLInputElement* number = GetParentNumberControl(mBoundFrame);
|
||||
if (number ? number->IsSelectionCached() : mSelectionCached) {
|
||||
if (mRestoringSelection) // paranoia
|
||||
mRestoringSelection->Revoke();
|
||||
mRestoringSelection = new RestoreSelectionState(this, mBoundFrame);
|
||||
|
@ -1433,11 +1436,66 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
}
|
||||
|
||||
// The selection cache is no longer going to be valid
|
||||
mSelectionCached = false;
|
||||
if (number) {
|
||||
number->ClearSelectionCached();
|
||||
} else {
|
||||
mSelectionCached = false;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextEditorState::IsSelectionCached() const
|
||||
{
|
||||
if (mBoundFrame) {
|
||||
HTMLInputElement* number = GetParentNumberControl(mBoundFrame);
|
||||
if (number) {
|
||||
return number->IsSelectionCached();
|
||||
}
|
||||
}
|
||||
return mSelectionCached;
|
||||
}
|
||||
|
||||
nsTextEditorState::SelectionProperties&
|
||||
nsTextEditorState::GetSelectionProperties()
|
||||
{
|
||||
if (mBoundFrame) {
|
||||
HTMLInputElement* number = GetParentNumberControl(mBoundFrame);
|
||||
if (number) {
|
||||
return number->GetSelectionProperties();
|
||||
}
|
||||
}
|
||||
return mSelectionProperties;
|
||||
}
|
||||
|
||||
HTMLInputElement*
|
||||
nsTextEditorState::GetParentNumberControl(nsFrame* aFrame) const
|
||||
{
|
||||
MOZ_ASSERT(aFrame);
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
MOZ_ASSERT(content);
|
||||
nsIContent* parent = content->GetParent();
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIContent* parentOfParent = parent->GetParent();
|
||||
if (!parentOfParent) {
|
||||
return nullptr;
|
||||
}
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(parentOfParent);
|
||||
if (input) {
|
||||
// This function might be called during frame reconstruction as a result
|
||||
// of changing the input control's type from number to something else. In
|
||||
// that situation, the type of the control has changed, but its frame has
|
||||
// not been reconstructed yet. So we need to check the type of the input
|
||||
// control in addition to the type of the frame.
|
||||
return (input->GetType() == NS_FORM_INPUT_NUMBER) ? input : nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextEditorState::DestroyEditor()
|
||||
{
|
||||
|
@ -1478,10 +1536,21 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
|||
// GetSelectionRange before calling DestroyEditor, and only if
|
||||
// mEditorInitialized indicates that we actually have an editor available.
|
||||
if (mEditorInitialized) {
|
||||
mBoundFrame->GetSelectionRange(&mSelectionProperties.mStart,
|
||||
&mSelectionProperties.mEnd,
|
||||
&mSelectionProperties.mDirection);
|
||||
mSelectionCached = true;
|
||||
HTMLInputElement* number = GetParentNumberControl(aFrame);
|
||||
if (number) {
|
||||
// If we are inside a number control, cache the selection on the
|
||||
// parent control, because this text editor state will be destroyed
|
||||
// together with the native anonymous text control.
|
||||
SelectionProperties props;
|
||||
mBoundFrame->GetSelectionRange(&props.mStart, &props.mEnd,
|
||||
&props.mDirection);
|
||||
number->SetSelectionProperties(props);
|
||||
} else {
|
||||
mBoundFrame->GetSelectionRange(&mSelectionProperties.mStart,
|
||||
&mSelectionProperties.mEnd,
|
||||
&mSelectionProperties.mDirection);
|
||||
mSelectionCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy our editor
|
||||
|
|
|
@ -23,6 +23,13 @@ class nsISelectionController;
|
|||
class nsFrameSelection;
|
||||
class nsIEditor;
|
||||
class nsITextControlElement;
|
||||
class nsFrame;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class HTMLInputElement;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nsTextEditorState is a class which is responsible for managing the state of
|
||||
|
@ -203,10 +210,8 @@ public:
|
|||
nsITextControlFrame::SelectionDirection mDirection;
|
||||
};
|
||||
|
||||
bool IsSelectionCached() const { return mSelectionCached; }
|
||||
SelectionProperties& GetSelectionProperties() {
|
||||
return mSelectionProperties;
|
||||
}
|
||||
bool IsSelectionCached() const;
|
||||
SelectionProperties& GetSelectionProperties();
|
||||
void WillInitEagerly() { mSelectionRestoreEagerInit = true; }
|
||||
bool HasNeverInitializedBefore() const { return !mEverInited; }
|
||||
|
||||
|
@ -235,6 +240,8 @@ private:
|
|||
|
||||
void FinishedRestoringSelection() { mRestoringSelection = nullptr; }
|
||||
|
||||
mozilla::dom::HTMLInputElement* GetParentNumberControl(nsFrame* aFrame) const;
|
||||
|
||||
class InitializationGuard {
|
||||
public:
|
||||
explicit InitializationGuard(nsTextEditorState& aState) :
|
||||
|
|
Загрузка…
Ссылка в новой задаче