Bug 1867190 - Initialise the PHC allocate delay later r=glandium
[gecko.git] / layout / forms / nsTextControlFrame.h
blob0d52e5849f69746b84f0ac60f0d2b9a29fb3e965
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef nsTextControlFrame_h___
8 #define nsTextControlFrame_h___
10 #include "mozilla/Attributes.h"
11 #include "mozilla/TextControlElement.h"
12 #include "nsContainerFrame.h"
13 #include "nsIAnonymousContentCreator.h"
14 #include "nsIContent.h"
15 #include "nsITextControlFrame.h"
16 #include "nsIStatefulFrame.h"
18 class nsISelectionController;
19 class EditorInitializerEntryTracker;
20 namespace mozilla {
21 class AutoTextControlHandlingState;
22 class TextEditor;
23 class TextControlState;
24 enum class PseudoStyleType : uint8_t;
25 namespace dom {
26 class Element;
27 } // namespace dom
28 } // namespace mozilla
30 class nsTextControlFrame : public nsContainerFrame,
31 public nsIAnonymousContentCreator,
32 public nsITextControlFrame,
33 public nsIStatefulFrame {
34 using Element = mozilla::dom::Element;
36 public:
37 NS_DECL_FRAMEARENA_HELPERS(nsTextControlFrame)
39 NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ContentScrollPos, nsPoint)
41 protected:
42 nsTextControlFrame(ComputedStyle*, nsPresContext*, nsIFrame::ClassID);
44 public:
45 explicit nsTextControlFrame(ComputedStyle* aStyle,
46 nsPresContext* aPresContext)
47 : nsTextControlFrame(aStyle, aPresContext, kClassID) {}
49 virtual ~nsTextControlFrame();
51 /**
52 * Destroy() causes preparing to destroy editor and that may cause running
53 * selection listeners of spellchecker selection and document state listeners.
54 * Not sure whether the former does something or not, but nobody should run
55 * content script. The latter is currently only FinderHighlighter to clean up
56 * its fields at destruction. Thus, the latter won't run content script too.
57 * Therefore, this won't run unsafe script.
59 MOZ_CAN_RUN_SCRIPT_BOUNDARY void Destroy(DestroyContext&) override;
61 nsIScrollableFrame* GetScrollTargetFrame() const override;
63 nscoord GetMinISize(gfxContext* aRenderingContext) override;
64 nscoord GetPrefISize(gfxContext* aRenderingContext) override;
66 mozilla::LogicalSize ComputeAutoSize(
67 gfxContext* aRenderingContext, mozilla::WritingMode aWM,
68 const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
69 const mozilla::LogicalSize& aMargin,
70 const mozilla::LogicalSize& aBorderPadding,
71 const mozilla::StyleSizeOverrides& aSizeOverrides,
72 mozilla::ComputeSizeFlags aFlags) override;
74 void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
75 const ReflowInput& aReflowInput,
76 nsReflowStatus& aStatus) override;
78 Maybe<nscoord> GetNaturalBaselineBOffset(
79 mozilla::WritingMode aWM, BaselineSharingGroup aBaselineGroup,
80 BaselineExportContext aExportContext) const override;
82 BaselineSharingGroup GetDefaultBaselineSharingGroup() const override {
83 return BaselineSharingGroup::Last;
86 static Maybe<nscoord> GetSingleLineTextControlBaseline(
87 const nsIFrame* aFrame, nscoord aFirstBaseline, mozilla::WritingMode aWM,
88 BaselineSharingGroup aBaselineGroup) {
89 if (aFrame->StyleDisplay()->IsContainLayout()) {
90 return Nothing{};
92 NS_ASSERTION(aFirstBaseline != NS_INTRINSIC_ISIZE_UNKNOWN,
93 "please call Reflow before asking for the baseline");
94 return mozilla::Some(aBaselineGroup == BaselineSharingGroup::First
95 ? aFirstBaseline
96 : aFrame->BSize(aWM) - aFirstBaseline);
99 #ifdef ACCESSIBILITY
100 mozilla::a11y::AccType AccessibleType() override;
101 #endif
103 #ifdef DEBUG_FRAME_DUMP
104 nsresult GetFrameName(nsAString& aResult) const override {
105 aResult.AssignLiteral("nsTextControlFrame");
106 return NS_OK;
108 #endif
110 // nsIAnonymousContentCreator
111 nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
112 void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
113 uint32_t aFilter) override;
115 void SetInitialChildList(ChildListID, nsFrameList&&) override;
117 void BuildDisplayList(nsDisplayListBuilder* aBuilder,
118 const nsDisplayListSet& aLists) override;
120 //==== BEGIN NSIFORMCONTROLFRAME
121 MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetFocus(bool aOn, bool aRepaint) override;
122 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
123 SetFormProperty(nsAtom* aName, const nsAString& aValue) override;
125 //==== END NSIFORMCONTROLFRAME
127 //==== NSITEXTCONTROLFRAME
129 MOZ_CAN_RUN_SCRIPT_BOUNDARY already_AddRefed<mozilla::TextEditor>
130 GetTextEditor() override;
131 MOZ_CAN_RUN_SCRIPT NS_IMETHOD
132 SetSelectionRange(uint32_t aSelectionStart, uint32_t aSelectionEnd,
133 SelectionDirection = SelectionDirection::None) override;
134 NS_IMETHOD GetOwnedSelectionController(
135 nsISelectionController** aSelCon) override;
136 nsFrameSelection* GetOwnedFrameSelection() override {
137 return ControlElement()->GetConstFrameSelection();
139 nsISelectionController* GetSelectionController() {
140 return ControlElement()->GetSelectionController();
143 void PlaceholderChanged(const nsAttrValue* aOld, const nsAttrValue* aNew);
146 * Ensure mEditor is initialized with the proper flags and the default value.
147 * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
148 * @throws various and sundry other things
150 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult EnsureEditorInitialized() override;
152 //==== END NSITEXTCONTROLFRAME
154 //==== NSISTATEFULFRAME
156 mozilla::UniquePtr<mozilla::PresState> SaveState() override;
157 NS_IMETHOD RestoreState(mozilla::PresState* aState) override;
159 //=== END NSISTATEFULFRAME
161 //==== OVERLOAD of nsIFrame
163 /** handler for attribute changes to mContent */
164 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult AttributeChanged(
165 int32_t aNameSpaceID, nsAtom* aAttribute, int32_t aModType) override;
166 void ElementStateChanged(mozilla::dom::ElementState aStates) override;
168 nsresult PeekOffset(mozilla::PeekOffsetStruct* aPos) override;
170 NS_DECL_QUERYFRAME
172 // Whether we should scroll only the current selection into view in the inner
173 // scroller, or also ancestors as needed.
174 enum class ScrollAncestors { No, Yes };
175 void ScrollSelectionIntoViewAsync(ScrollAncestors = ScrollAncestors::No);
177 protected:
178 MOZ_CAN_RUN_SCRIPT_BOUNDARY void HandleReadonlyOrDisabledChange();
181 * Launch the reflow on the child frames - see nsTextControlFrame::Reflow()
183 void ReflowTextControlChild(nsIFrame* aFrame, nsPresContext* aPresContext,
184 const ReflowInput& aReflowInput,
185 nsReflowStatus& aStatus,
186 ReflowOutput& aParentDesiredSize,
187 nscoord& aButtonBoxISize);
189 public:
190 static Maybe<nscoord> ComputeBaseline(const nsIFrame*, const ReflowInput&,
191 bool aForSingleLineControl);
193 Element* GetRootNode() const { return mRootNode; }
195 Element* GetPreviewNode() const { return mPreviewDiv; }
197 Element* GetPlaceholderNode() const { return mPlaceholderDiv; }
199 Element* GetRevealButton() const { return mRevealButton; }
201 // called by the focus listener
202 nsresult MaybeBeginSecureKeyboardInput();
203 void MaybeEndSecureKeyboardInput();
205 mozilla::TextControlElement* ControlElement() const {
206 MOZ_ASSERT(mozilla::TextControlElement::FromNode(GetContent()));
207 return static_cast<mozilla::TextControlElement*>(GetContent());
210 #define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name) \
211 type name() const { return ControlElement()->name(); }
213 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl)
214 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea)
215 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl)
216 DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetCols)
217 DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetRows)
219 #undef DEFINE_TEXTCTRL_CONST_FORWARDER
221 protected:
222 class EditorInitializer;
223 friend class EditorInitializer;
224 friend class mozilla::AutoTextControlHandlingState; // needs access to
225 // CacheValue
226 friend class mozilla::TextControlState; // needs access to UpdateValueDisplay
228 // Temp reference to scriptrunner
229 NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(TextControlInitializer, EditorInitializer,
230 nsTextControlFrame::RevokeInitializer)
232 static void RevokeInitializer(EditorInitializer* aInitializer) {
233 aInitializer->Revoke();
236 class EditorInitializer : public mozilla::Runnable {
237 public:
238 explicit EditorInitializer(nsTextControlFrame* aFrame)
239 : mozilla::Runnable("nsTextControlFrame::EditorInitializer"),
240 mFrame(aFrame) {}
242 NS_IMETHOD Run() override;
244 // avoids use of AutoWeakFrame
245 void Revoke() { mFrame = nullptr; }
247 private:
248 nsTextControlFrame* mFrame;
251 nsresult OffsetToDOMPoint(uint32_t aOffset, nsINode** aResult,
252 uint32_t* aPosition);
255 * Update the textnode under our anonymous div to show the new
256 * value. This should only be called when we have no editor yet.
257 * @throws NS_ERROR_UNEXPECTED if the div has no text content
259 nsresult UpdateValueDisplay(bool aNotify, bool aBeforeEditorInit = false,
260 const nsAString* aValue = nullptr);
263 * Find out whether an attribute exists on the content or not.
264 * @param aAtt the attribute to determine the existence of
265 * @returns false if it does not exist
267 bool AttributeExists(nsAtom* aAtt) const {
268 return mContent && mContent->AsElement()->HasAttr(aAtt);
272 * We call this when we are being destroyed or removed from the PFM.
273 * @param aPresContext the current pres context
275 void PreDestroy();
277 // Compute our intrinsic size. This does not include any borders, paddings,
278 // etc. Just the size of our actual area for the text (and the scrollbars,
279 // for <textarea>).
280 mozilla::LogicalSize CalcIntrinsicSize(gfxContext* aRenderingContext,
281 mozilla::WritingMode aWM,
282 float aFontSizeInflation) const;
284 private:
285 // helper methods
286 MOZ_CAN_RUN_SCRIPT nsresult SetSelectionInternal(
287 nsINode* aStartNode, uint32_t aStartOffset, nsINode* aEndNode,
288 uint32_t aEndOffset, SelectionDirection = SelectionDirection::None);
289 MOZ_CAN_RUN_SCRIPT nsresult SelectAllOrCollapseToEndOfText(bool aSelect);
290 MOZ_CAN_RUN_SCRIPT nsresult
291 SetSelectionEndPoints(uint32_t aSelStart, uint32_t aSelEnd,
292 SelectionDirection = SelectionDirection::None);
294 void FinishedInitializer() { RemoveProperty(TextControlInitializer()); }
296 const nsAString& CachedValue() const { return mCachedValue; }
298 void ClearCachedValue() { mCachedValue.SetIsVoid(true); }
300 void CacheValue(const nsAString& aValue) { mCachedValue.Assign(aValue); }
302 [[nodiscard]] bool CacheValue(const nsAString& aValue,
303 const mozilla::fallible_t& aFallible) {
304 if (!mCachedValue.Assign(aValue, aFallible)) {
305 ClearCachedValue();
306 return false;
308 return true;
311 protected:
312 class nsAnonDivObserver;
314 nsresult CreateRootNode();
315 void CreatePlaceholderIfNeeded();
316 void UpdatePlaceholderText(nsString&, bool aNotify);
317 void CreatePreviewIfNeeded();
318 already_AddRefed<Element> MakeAnonElement(
319 mozilla::PseudoStyleType, Element* aParent = nullptr,
320 nsAtom* aTag = nsGkAtoms::div) const;
321 already_AddRefed<Element> MakeAnonDivWithTextNode(
322 mozilla::PseudoStyleType) const;
324 bool ShouldInitializeEagerly() const;
325 void InitializeEagerlyIfNeeded();
327 RefPtr<Element> mRootNode;
328 RefPtr<Element> mPlaceholderDiv;
329 RefPtr<Element> mPreviewDiv;
330 // The Reveal Password button. Only used for type=password, nullptr
331 // otherwise.
332 RefPtr<Element> mRevealButton;
333 RefPtr<nsAnonDivObserver> mMutationObserver;
334 // Cache of the |.value| of <input> or <textarea> element without hard-wrap.
335 // If its IsVoid() returns true, it doesn't cache |.value|.
336 // Otherwise, it's cached when setting specific value or getting value from
337 // TextEditor. Additionally, when contents in the anonymous <div> element
338 // is modified, this is cleared.
340 // FIXME(bug 1402545): Consider using an nsAutoString here.
341 nsString mCachedValue{VoidString()};
343 // Our first baseline, or NS_INTRINSIC_ISIZE_UNKNOWN if we have a pending
344 // Reflow (or if we're contain:layout, which means we have no baseline).
345 nscoord mFirstBaseline = NS_INTRINSIC_ISIZE_UNKNOWN;
347 // these packed bools could instead use the high order bits on mState, saving
348 // 4 bytes
349 bool mEditorHasBeenInitialized = false;
350 bool mIsProcessing = false;
352 #ifdef DEBUG
353 bool mInEditorInitialization = false;
354 friend class EditorInitializerEntryTracker;
355 #endif
358 #endif