Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef nsTextControlFrame_h___
7 : #define nsTextControlFrame_h___
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "nsContainerFrame.h"
11 : #include "nsIAnonymousContentCreator.h"
12 : #include "nsIContent.h"
13 : #include "nsITextControlFrame.h"
14 : #include "nsITextControlElement.h"
15 : #include "nsIStatefulFrame.h"
16 :
17 : class nsISelectionController;
18 : class EditorInitializerEntryTracker;
19 : class nsTextEditorState;
20 : namespace mozilla {
21 : class TextEditor;
22 : enum class CSSPseudoElementType : uint8_t;
23 : namespace dom {
24 : class Element;
25 : } // namespace dom
26 : } // namespace mozilla
27 :
28 : class nsTextControlFrame final : public nsContainerFrame,
29 : public nsIAnonymousContentCreator,
30 : public nsITextControlFrame,
31 : public nsIStatefulFrame
32 : {
33 : public:
34 151 : NS_DECL_FRAMEARENA_HELPERS(nsTextControlFrame)
35 :
36 4 : NS_DECLARE_FRAME_PROPERTY_DELETABLE(ContentScrollPos, nsPoint)
37 :
38 : explicit nsTextControlFrame(nsStyleContext* aContext);
39 : virtual ~nsTextControlFrame();
40 :
41 : virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
42 :
43 0 : virtual nsIScrollableFrame* GetScrollTargetFrame() override {
44 0 : return do_QueryFrame(PrincipalChildList().FirstChild());
45 : }
46 :
47 : virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
48 : virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
49 :
50 : virtual mozilla::LogicalSize
51 : ComputeAutoSize(gfxContext* aRenderingContext,
52 : mozilla::WritingMode aWM,
53 : const mozilla::LogicalSize& aCBSize,
54 : nscoord aAvailableISize,
55 : const mozilla::LogicalSize& aMargin,
56 : const mozilla::LogicalSize& aBorder,
57 : const mozilla::LogicalSize& aPadding,
58 : ComputeSizeFlags aFlags) override;
59 :
60 : virtual void Reflow(nsPresContext* aPresContext,
61 : ReflowOutput& aDesiredSize,
62 : const ReflowInput& aReflowInput,
63 : nsReflowStatus& aStatus) override;
64 :
65 0 : bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
66 : nscoord* aBaseline) const override
67 : {
68 0 : return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eFirst, aBaseline);
69 : }
70 :
71 0 : bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
72 : BaselineSharingGroup aBaselineGroup,
73 : nscoord* aBaseline) const override
74 : {
75 0 : if (!IsSingleLineTextControl()) {
76 0 : return false;
77 : }
78 0 : NS_ASSERTION(mFirstBaseline != NS_INTRINSIC_WIDTH_UNKNOWN,
79 : "please call Reflow before asking for the baseline");
80 0 : if (aBaselineGroup == BaselineSharingGroup::eFirst) {
81 0 : *aBaseline = mFirstBaseline;
82 : } else {
83 0 : *aBaseline = BSize(aWM) - mFirstBaseline;
84 : }
85 0 : return true;
86 : }
87 :
88 : virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
89 : virtual bool IsXULCollapsed() override;
90 :
91 : #ifdef ACCESSIBILITY
92 : virtual mozilla::a11y::AccType AccessibleType() override;
93 : #endif
94 :
95 : #ifdef DEBUG_FRAME_DUMP
96 0 : virtual nsresult GetFrameName(nsAString& aResult) const override
97 : {
98 0 : aResult.AssignLiteral("nsTextControlFrame");
99 0 : return NS_OK;
100 : }
101 : #endif
102 :
103 316 : virtual bool IsFrameOfType(uint32_t aFlags) const override
104 : {
105 : // nsStackFrame is already both of these, but that's somewhat bogus,
106 : // and we really mean it.
107 316 : return nsContainerFrame::IsFrameOfType(aFlags &
108 316 : ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
109 : }
110 :
111 : #ifdef DEBUG
112 0 : void MarkIntrinsicISizesDirty() override
113 : {
114 : // Need another Reflow to have a correct baseline value again.
115 0 : mFirstBaseline = NS_INTRINSIC_WIDTH_UNKNOWN;
116 0 : }
117 : #endif
118 :
119 : // nsIAnonymousContentCreator
120 : virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
121 : virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
122 : uint32_t aFilter) override;
123 :
124 : virtual void SetInitialChildList(ChildListID aListID,
125 : nsFrameList& aChildList) override;
126 :
127 : virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
128 : const nsRect& aDirtyRect,
129 : const nsDisplayListSet& aLists) override;
130 :
131 : virtual mozilla::dom::Element*
132 : GetPseudoElement(mozilla::CSSPseudoElementType aType) override;
133 :
134 : //==== BEGIN NSIFORMCONTROLFRAME
135 : virtual void SetFocus(bool aOn , bool aRepaint) override;
136 : virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
137 :
138 : //==== END NSIFORMCONTROLFRAME
139 :
140 : //==== NSITEXTCONTROLFRAME
141 :
142 : NS_IMETHOD_(already_AddRefed<mozilla::TextEditor>) GetTextEditor() override;
143 : NS_IMETHOD SetSelectionRange(uint32_t aSelectionStart,
144 : uint32_t aSelectionEnd,
145 : SelectionDirection aDirection = eNone) override;
146 : NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) override;
147 : virtual nsFrameSelection* GetOwnedFrameSelection() override;
148 :
149 : /**
150 : * Ensure mEditor is initialized with the proper flags and the default value.
151 : * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
152 : * @throws various and sundry other things
153 : */
154 : virtual nsresult EnsureEditorInitialized() override;
155 :
156 : //==== END NSITEXTCONTROLFRAME
157 :
158 : //==== NSISTATEFULFRAME
159 :
160 : NS_IMETHOD SaveState(nsPresState** aState) override;
161 : NS_IMETHOD RestoreState(nsPresState* aState) override;
162 :
163 : //=== END NSISTATEFULFRAME
164 :
165 : //==== OVERLOAD of nsIFrame
166 :
167 : /** handler for attribute changes to mContent */
168 : virtual nsresult AttributeChanged(int32_t aNameSpaceID,
169 : nsIAtom* aAttribute,
170 : int32_t aModType) override;
171 :
172 : nsresult GetText(nsString& aText);
173 :
174 : virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos) override;
175 :
176 : NS_DECL_QUERYFRAME
177 :
178 : protected:
179 : /**
180 : * Launch the reflow on the child frames - see nsTextControlFrame::Reflow()
181 : */
182 : void ReflowTextControlChild(nsIFrame* aFrame,
183 : nsPresContext* aPresContext,
184 : const ReflowInput& aReflowInput,
185 : nsReflowStatus& aStatus,
186 : ReflowOutput& aParentDesiredSize);
187 :
188 : public: //for methods who access nsTextControlFrame directly
189 : void SetValueChanged(bool aValueChanged);
190 :
191 : // called by the focus listener
192 : nsresult MaybeBeginSecureKeyboardInput();
193 : void MaybeEndSecureKeyboardInput();
194 :
195 : #define DEFINE_TEXTCTRL_FORWARDER(type, name) \
196 : type name() { \
197 : nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \
198 : NS_ASSERTION(txtCtrl, "Content not a text control element"); \
199 : return txtCtrl->name(); \
200 : }
201 : #define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name) \
202 : type name() const { \
203 : nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \
204 : NS_ASSERTION(txtCtrl, "Content not a text control element"); \
205 : return txtCtrl->name(); \
206 : }
207 :
208 37 : DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl)
209 20 : DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea)
210 : DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPlainTextControl)
211 0 : DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl)
212 20 : DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetCols)
213 : DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetWrapCols)
214 20 : DEFINE_TEXTCTRL_CONST_FORWARDER(int32_t, GetRows)
215 :
216 : #undef DEFINE_TEXTCTRL_CONST_FORWARDER
217 : #undef DEFINE_TEXTCTRL_FORWARDER
218 :
219 : protected:
220 : class EditorInitializer;
221 : friend class EditorInitializer;
222 : friend class nsTextEditorState; // needs access to UpdateValueDisplay
223 :
224 : // Temp reference to scriptrunner
225 2 : NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(TextControlInitializer,
226 : EditorInitializer,
227 : nsTextControlFrame::RevokeInitializer)
228 :
229 : static void
230 0 : RevokeInitializer(EditorInitializer* aInitializer) {
231 0 : aInitializer->Revoke();
232 0 : };
233 :
234 0 : class EditorInitializer : public mozilla::Runnable {
235 : public:
236 0 : explicit EditorInitializer(nsTextControlFrame* aFrame)
237 0 : : mozilla::Runnable("nsTextControlFrame::EditorInitializer")
238 0 : , mFrame(aFrame)
239 : {
240 0 : }
241 :
242 : NS_IMETHOD Run() override;
243 :
244 : // avoids use of AutoWeakFrame
245 0 : void Revoke() {
246 0 : mFrame = nullptr;
247 0 : }
248 :
249 : private:
250 : nsTextControlFrame* mFrame;
251 : };
252 :
253 : class ScrollOnFocusEvent;
254 : friend class ScrollOnFocusEvent;
255 :
256 0 : class ScrollOnFocusEvent : public mozilla::Runnable {
257 : public:
258 0 : explicit ScrollOnFocusEvent(nsTextControlFrame* aFrame)
259 0 : : mozilla::Runnable("nsTextControlFrame::ScrollOnFocusEvent")
260 0 : , mFrame(aFrame)
261 : {
262 0 : }
263 :
264 : NS_DECL_NSIRUNNABLE
265 :
266 0 : void Revoke() {
267 0 : mFrame = nullptr;
268 0 : }
269 :
270 : private:
271 : nsTextControlFrame* mFrame;
272 : };
273 :
274 : nsresult OffsetToDOMPoint(uint32_t aOffset, nsIDOMNode** aResult, uint32_t* aPosition);
275 :
276 : /**
277 : * Update the textnode under our anonymous div to show the new
278 : * value. This should only be called when we have no editor yet.
279 : * @throws NS_ERROR_UNEXPECTED if the div has no text content
280 : */
281 : nsresult UpdateValueDisplay(bool aNotify,
282 : bool aBeforeEditorInit = false,
283 : const nsAString *aValue = nullptr);
284 :
285 : /**
286 : * Get the maxlength attribute
287 : * @param aMaxLength the value of the max length attr
288 : * @returns false if attr not defined
289 : */
290 : bool GetMaxLength(int32_t* aMaxLength);
291 :
292 : /**
293 : * Find out whether an attribute exists on the content or not.
294 : * @param aAtt the attribute to determine the existence of
295 : * @returns false if it does not exist
296 : */
297 0 : bool AttributeExists(nsIAtom *aAtt) const
298 0 : { return mContent && mContent->HasAttr(kNameSpaceID_None, aAtt); }
299 :
300 : /**
301 : * We call this when we are being destroyed or removed from the PFM.
302 : * @param aPresContext the current pres context
303 : */
304 : void PreDestroy();
305 :
306 : // Compute our intrinsic size. This does not include any borders, paddings,
307 : // etc. Just the size of our actual area for the text (and the scrollbars,
308 : // for <textarea>).
309 : mozilla::LogicalSize CalcIntrinsicSize(gfxContext* aRenderingContext,
310 : mozilla::WritingMode aWM,
311 : float aFontSizeInflation) const;
312 :
313 : nsresult ScrollSelectionIntoView() override;
314 :
315 : private:
316 : //helper methods
317 : nsresult SetSelectionInternal(nsIDOMNode *aStartNode, uint32_t aStartOffset,
318 : nsIDOMNode *aEndNode, uint32_t aEndOffset,
319 : SelectionDirection aDirection = eNone);
320 : nsresult SelectAllOrCollapseToEndOfText(bool aSelect);
321 : nsresult SetSelectionEndPoints(uint32_t aSelStart, uint32_t aSelEnd,
322 : SelectionDirection aDirection = eNone);
323 :
324 : /**
325 : * Return the root DOM element, and implicitly initialize the editor if
326 : * needed.
327 : *
328 : * XXXbz This function is slow. Very slow. Consider using
329 : * EnsureEditorInitialized() if you need that, and
330 : * nsITextControlElement::GetRootEditorNode on our content if you need that.
331 : */
332 : nsresult GetRootNodeAndInitializeEditor(nsIDOMElement **aRootElement);
333 :
334 0 : void FinishedInitializer() {
335 0 : DeleteProperty(TextControlInitializer());
336 0 : }
337 :
338 : private:
339 : // Our first baseline, or NS_INTRINSIC_WIDTH_UNKNOWN if we have a pending
340 : // Reflow.
341 : nscoord mFirstBaseline;
342 :
343 : // these packed bools could instead use the high order bits on mState, saving 4 bytes
344 : bool mEditorHasBeenInitialized;
345 : bool mIsProcessing;
346 : // Keep track if we have asked a placeholder node creation.
347 : bool mUsePlaceholder;
348 : // Similarly for preview node creation.
349 : bool mUsePreview;
350 :
351 : #ifdef DEBUG
352 : bool mInEditorInitialization;
353 : friend class EditorInitializerEntryTracker;
354 : #endif
355 :
356 : nsRevocableEventPtr<ScrollOnFocusEvent> mScrollEvent;
357 : };
358 :
359 : #endif
360 :
361 :
|