nsTextControlFrame.h 12 KB

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