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/. */
6 #ifndef nsTextControlFrame_h___
7 #define nsTextControlFrame_h___
9 #include "nsContainerFrame.h"
10 #include "nsBlockFrame.h"
11 #include "nsIFormControlFrame.h"
12 #include "nsIAnonymousContentCreator.h"
13 #include "nsITextControlFrame.h"
14 #include "nsDisplayList.h"
15 #include "nsIScrollableFrame.h"
16 #include "nsStubMutationObserver.h"
17 #include "nsITextControlElement.h"
18 #include "nsIStatefulFrame.h"
19 #include "nsContentUtils.h" // nsAutoScriptBlocker
20 #include "nsIEditor.h"
22 class nsISelectionController
;
23 class nsIDOMCharacterData
;
27 class EditorInitializerEntryTracker
;
28 class nsTextEditorState
;
35 class nsTextControlFrame
: public nsContainerFrame
,
36 public nsIAnonymousContentCreator
,
37 public nsITextControlFrame
,
38 public nsIStatefulFrame
41 NS_DECL_FRAMEARENA_HELPERS
43 NS_DECLARE_FRAME_PROPERTY(ContentScrollPos
, DestroyPoint
)
45 nsTextControlFrame(nsIPresShell
* aShell
, nsStyleContext
* aContext
);
46 virtual ~nsTextControlFrame();
48 virtual void DestroyFrom(nsIFrame
* aDestructRoot
);
50 virtual nsIScrollableFrame
* GetScrollTargetFrame() {
53 return do_QueryFrame(GetFirstPrincipalChild());
56 virtual nscoord
GetMinWidth(nsRenderingContext
* aRenderingContext
);
57 virtual nscoord
GetPrefWidth(nsRenderingContext
* aRenderingContext
);
59 virtual nsSize
ComputeAutoSize(nsRenderingContext
*aRenderingContext
,
60 nsSize aCBSize
, nscoord aAvailableWidth
,
61 nsSize aMargin
, nsSize aBorder
,
62 nsSize aPadding
, bool aShrinkWrap
);
64 NS_IMETHOD
Reflow(nsPresContext
* aPresContext
,
65 nsHTMLReflowMetrics
& aDesiredSize
,
66 const nsHTMLReflowState
& aReflowState
,
67 nsReflowStatus
& aStatus
);
69 virtual nsSize
GetMinSize(nsBoxLayoutState
& aBoxLayoutState
);
70 virtual bool IsCollapsed();
72 DECL_DO_GLOBAL_REFLOW_COUNT_DSP(nsTextControlFrame
, nsContainerFrame
)
74 virtual bool IsLeaf() const;
77 virtual already_AddRefed
<Accessible
> CreateAccessible();
81 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const
83 aResult
.AssignLiteral("nsTextControlFrame");
88 virtual bool IsFrameOfType(PRUint32 aFlags
) const
90 // nsStackFrame is already both of these, but that's somewhat bogus,
91 // and we really mean it.
92 return nsContainerFrame::IsFrameOfType(aFlags
&
93 ~(nsIFrame::eReplaced
| nsIFrame::eReplacedContainsBlock
));
96 // nsIAnonymousContentCreator
97 virtual nsresult
CreateAnonymousContent(nsTArray
<ContentInfo
>& aElements
);
98 virtual void AppendAnonymousContentTo(nsBaseContentList
& aElements
,
101 // Utility methods to set current widget state
103 NS_IMETHOD
SetInitialChildList(ChildListID aListID
,
104 nsFrameList
& aChildList
);
106 //==== BEGIN NSIFORMCONTROLFRAME
107 virtual void SetFocus(bool aOn
, bool aRepaint
);
108 virtual nsresult
SetFormProperty(nsIAtom
* aName
, const nsAString
& aValue
);
109 virtual nsresult
GetFormProperty(nsIAtom
* aName
, nsAString
& aValue
) const;
112 //==== END NSIFORMCONTROLFRAME
114 //==== NSITEXTCONTROLFRAME
116 NS_IMETHOD
GetEditor(nsIEditor
**aEditor
);
117 NS_IMETHOD
GetTextLength(PRInt32
* aTextLength
);
118 NS_IMETHOD
SetSelectionStart(PRInt32 aSelectionStart
);
119 NS_IMETHOD
SetSelectionEnd(PRInt32 aSelectionEnd
);
120 NS_IMETHOD
SetSelectionRange(PRInt32 aSelectionStart
,
121 PRInt32 aSelectionEnd
,
122 SelectionDirection aDirection
= eNone
);
123 NS_IMETHOD
GetSelectionRange(PRInt32
* aSelectionStart
,
124 PRInt32
* aSelectionEnd
,
125 SelectionDirection
* aDirection
= nullptr);
126 NS_IMETHOD
GetOwnedSelectionController(nsISelectionController
** aSelCon
);
127 virtual nsFrameSelection
* GetOwnedFrameSelection();
129 nsresult
GetPhonetic(nsAString
& aPhonetic
);
132 * Ensure mEditor is initialized with the proper flags and the default value.
133 * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created
134 * @throws various and sundry other things
136 virtual nsresult
EnsureEditorInitialized();
138 //==== END NSITEXTCONTROLFRAME
140 //==== NSISTATEFULFRAME
142 NS_IMETHOD
SaveState(SpecialStateID aStateID
, nsPresState
** aState
);
143 NS_IMETHOD
RestoreState(nsPresState
* aState
);
145 //=== END NSISTATEFULFRAME
147 //==== OVERLOAD of nsIFrame
148 virtual nsIAtom
* GetType() const;
150 /** handler for attribute changes to mContent */
151 NS_IMETHOD
AttributeChanged(PRInt32 aNameSpaceID
,
155 nsresult
GetText(nsString
& aText
);
157 NS_IMETHOD
PeekOffset(nsPeekOffsetStruct
*aPos
);
161 // Temp reference to scriptrunner
162 // We could make these auto-Revoking via the "delete" entry for safety
163 NS_DECLARE_FRAME_PROPERTY(TextControlInitializer
, nullptr)
167 * Launch the reflow on the child frames - see nsTextControlFrame::Reflow()
169 void ReflowTextControlChild(nsIFrame
* aFrame
,
170 nsPresContext
* aPresContext
,
171 const nsHTMLReflowState
& aReflowState
,
172 nsReflowStatus
& aStatus
,
173 nsHTMLReflowMetrics
& aParentDesiredSize
);
175 public: //for methods who access nsTextControlFrame directly
176 void SetValueChanged(bool aValueChanged
);
178 // called by the focus listener
179 nsresult
MaybeBeginSecureKeyboardInput();
180 void MaybeEndSecureKeyboardInput();
182 NS_STACK_CLASS
class ValueSetter
{
184 ValueSetter(nsIEditor
* aEditor
)
190 // To protect against a reentrant call to SetValue, we check whether
191 // another SetValue is already happening for this frame. If it is,
192 // we must wait until we unwind to re-enable oninput events.
193 mEditor
->GetSuppressDispatchingInputEvent(&mOuterTransaction
);
199 mEditor
->SetSuppressDispatchingInputEvent(true);
202 mEditor
->SetSuppressDispatchingInputEvent(mOuterTransaction
);
210 nsCOMPtr
<nsIEditor
> mEditor
;
211 bool mOuterTransaction
;
214 friend class ValueSetter
;
216 #define DEFINE_TEXTCTRL_FORWARDER(type, name) \
218 nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \
219 NS_ASSERTION(txtCtrl, "Content not a text control element"); \
220 return txtCtrl->name(); \
222 #define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name) \
223 type name() const { \
224 nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \
225 NS_ASSERTION(txtCtrl, "Content not a text control element"); \
226 return txtCtrl->name(); \
229 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl
)
230 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea
)
231 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPlainTextControl
)
232 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl
)
233 DEFINE_TEXTCTRL_FORWARDER(PRInt32
, GetCols
)
234 DEFINE_TEXTCTRL_FORWARDER(PRInt32
, GetWrapCols
)
235 DEFINE_TEXTCTRL_FORWARDER(PRInt32
, GetRows
)
237 #undef DEFINE_TEXTCTRL_CONST_FORWARDER
238 #undef DEFINE_TEXTCTRL_FORWARDER
241 class EditorInitializer
;
242 friend class EditorInitializer
;
243 friend class nsTextEditorState
; // needs access to UpdateValueDisplay
245 class EditorInitializer
: public nsRunnable
{
247 EditorInitializer(nsTextControlFrame
* aFrame
) :
252 // need to block script to avoid bug 669767
253 nsAutoScriptBlocker scriptBlocker
;
255 nsCOMPtr
<nsIPresShell
> shell
=
256 mFrame
->PresContext()->GetPresShell();
257 bool observes
= shell
->ObservesNativeAnonMutationsForPrint();
258 shell
->ObserveNativeAnonMutationsForPrint(true);
259 // This can cause the frame to be destroyed (and call Revoke())
260 mFrame
->EnsureEditorInitialized();
261 shell
->ObserveNativeAnonMutationsForPrint(observes
);
263 // The frame can *still* be destroyed even though we have a scriptblocker
266 return NS_ERROR_FAILURE
;
268 mFrame
->FinishedInitializer();
273 // avoids use of nsWeakFrame
279 nsTextControlFrame
* mFrame
;
282 class ScrollOnFocusEvent
;
283 friend class ScrollOnFocusEvent
;
285 class ScrollOnFocusEvent
: public nsRunnable
{
287 ScrollOnFocusEvent(nsTextControlFrame
* aFrame
) :
297 nsTextControlFrame
* mFrame
;
300 nsresult
OffsetToDOMPoint(PRInt32 aOffset
, nsIDOMNode
** aResult
, PRInt32
* aPosition
);
303 * Find out whether this control is scrollable (i.e. if it is not a single
305 * @return whether this control is scrollable
307 bool IsScrollable() const;
310 * Update the textnode under our anonymous div to show the new
311 * value. This should only be called when we have no editor yet.
312 * @throws NS_ERROR_UNEXPECTED if the div has no text content
314 nsresult
UpdateValueDisplay(bool aNotify
,
315 bool aBeforeEditorInit
= false,
316 const nsAString
*aValue
= nullptr);
319 * Get the maxlength attribute
320 * @param aMaxLength the value of the max length attr
321 * @returns false if attr not defined
323 bool GetMaxLength(PRInt32
* aMaxLength
);
326 * Find out whether an attribute exists on the content or not.
327 * @param aAtt the attribute to determine the existence of
328 * @returns false if it does not exist
330 bool AttributeExists(nsIAtom
*aAtt
) const
331 { return mContent
&& mContent
->HasAttr(kNameSpaceID_None
, aAtt
); }
334 * We call this when we are being destroyed or removed from the PFM.
335 * @param aPresContext the current pres context
339 // Compute our intrinsic size. This does not include any borders, paddings,
340 // etc. Just the size of our actual area for the text (and the scrollbars,
342 nsresult
CalcIntrinsicSize(nsRenderingContext
* aRenderingContext
,
343 nsSize
& aIntrinsicSize
,
344 float aFontSizeInflation
);
346 nsresult
ScrollSelectionIntoView();
350 nsresult
SetSelectionInternal(nsIDOMNode
*aStartNode
, PRInt32 aStartOffset
,
351 nsIDOMNode
*aEndNode
, PRInt32 aEndOffset
,
352 SelectionDirection aDirection
= eNone
);
353 nsresult
SelectAllOrCollapseToEndOfText(bool aSelect
);
354 nsresult
SetSelectionEndPoints(PRInt32 aSelStart
, PRInt32 aSelEnd
,
355 SelectionDirection aDirection
= eNone
);
358 * Return the root DOM element, and implicitly initialize the editor if needed.
360 mozilla::dom::Element
* GetRootNodeAndInitializeEditor();
361 nsresult
GetRootNodeAndInitializeEditor(nsIDOMElement
**aRootElement
);
363 void FinishedInitializer() {
364 Properties().Delete(TextControlInitializer());
368 // these packed bools could instead use the high order bits on mState, saving 4 bytes
371 // Keep track if we have asked a placeholder node creation.
372 bool mUsePlaceholder
;
375 bool mInEditorInitialization
;
376 friend class EditorInitializerEntryTracker
;
379 nsRevocableEventPtr
<ScrollOnFocusEvent
> mScrollEvent
;