nsFormControlFrame.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. #include "nsFormControlFrame.h"
  6. #include "nsGkAtoms.h"
  7. #include "nsLayoutUtils.h"
  8. #include "nsIDOMHTMLInputElement.h"
  9. #include "mozilla/EventStateManager.h"
  10. #include "mozilla/LookAndFeel.h"
  11. #include "nsDeviceContext.h"
  12. #include "nsIContent.h"
  13. using namespace mozilla;
  14. //#define FCF_NOISY
  15. nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext)
  16. : nsAtomicContainerFrame(aContext)
  17. {
  18. }
  19. nsFormControlFrame::~nsFormControlFrame()
  20. {
  21. }
  22. nsIAtom*
  23. nsFormControlFrame::GetType() const
  24. {
  25. return nsGkAtoms::formControlFrame;
  26. }
  27. void
  28. nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
  29. {
  30. // Unregister the access key registered in reflow
  31. nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
  32. nsAtomicContainerFrame::DestroyFrom(aDestructRoot);
  33. }
  34. NS_QUERYFRAME_HEAD(nsFormControlFrame)
  35. NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
  36. NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
  37. /* virtual */ nscoord
  38. nsFormControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)
  39. {
  40. nscoord result;
  41. DISPLAY_MIN_WIDTH(this, result);
  42. result = GetIntrinsicISize();
  43. return result;
  44. }
  45. /* virtual */ nscoord
  46. nsFormControlFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
  47. {
  48. nscoord result;
  49. DISPLAY_PREF_WIDTH(this, result);
  50. result = GetIntrinsicISize();
  51. return result;
  52. }
  53. /* virtual */
  54. LogicalSize
  55. nsFormControlFrame::ComputeAutoSize(nsRenderingContext* aRenderingContext,
  56. WritingMode aWM,
  57. const LogicalSize& aCBSize,
  58. nscoord aAvailableISize,
  59. const LogicalSize& aMargin,
  60. const LogicalSize& aBorder,
  61. const LogicalSize& aPadding,
  62. ComputeSizeFlags aFlags)
  63. {
  64. const WritingMode wm = GetWritingMode();
  65. LogicalSize result(wm, GetIntrinsicISize(), GetIntrinsicBSize());
  66. return result.ConvertTo(aWM, wm);
  67. }
  68. nscoord
  69. nsFormControlFrame::GetIntrinsicISize()
  70. {
  71. // Provide a reasonable default for sites that use an "auto" height.
  72. // Note that if you change this, you should change the values in forms.css
  73. // as well. This is the 13px default width minus the 2px default border.
  74. return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2);
  75. }
  76. nscoord
  77. nsFormControlFrame::GetIntrinsicBSize()
  78. {
  79. // Provide a reasonable default for sites that use an "auto" height.
  80. // Note that if you change this, you should change the values in forms.css
  81. // as well. This is the 13px default width minus the 2px default border.
  82. return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2);
  83. }
  84. nscoord
  85. nsFormControlFrame::GetLogicalBaseline(WritingMode aWritingMode) const
  86. {
  87. NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
  88. "frame must not be dirty");
  89. // Treat radio buttons and checkboxes as having an intrinsic baseline
  90. // at the block-end of the control (use the block-end content edge rather
  91. // than the margin edge).
  92. // For "inverted" lines (typically in writing-mode:vertical-lr), use the
  93. // block-start end instead.
  94. return aWritingMode.IsLineInverted()
  95. ? GetLogicalUsedBorderAndPadding(aWritingMode).BStart(aWritingMode)
  96. : BSize(aWritingMode) -
  97. GetLogicalUsedBorderAndPadding(aWritingMode).BEnd(aWritingMode);
  98. }
  99. void
  100. nsFormControlFrame::Reflow(nsPresContext* aPresContext,
  101. ReflowOutput& aDesiredSize,
  102. const ReflowInput& aReflowInput,
  103. nsReflowStatus& aStatus)
  104. {
  105. MarkInReflow();
  106. DO_GLOBAL_REFLOW_COUNT("nsFormControlFrame");
  107. DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
  108. NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
  109. ("enter nsFormControlFrame::Reflow: aMaxSize=%d,%d",
  110. aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
  111. if (mState & NS_FRAME_FIRST_REFLOW) {
  112. RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
  113. }
  114. aStatus = NS_FRAME_COMPLETE;
  115. aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
  116. aReflowInput.ComputedSizeWithBorderPadding());
  117. if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
  118. float inflation = nsLayoutUtils::FontSizeInflationFor(this);
  119. aDesiredSize.Width() *= inflation;
  120. aDesiredSize.Height() *= inflation;
  121. }
  122. NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
  123. ("exit nsFormControlFrame::Reflow: size=%d,%d",
  124. aDesiredSize.Width(), aDesiredSize.Height()));
  125. NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
  126. aDesiredSize.SetOverflowAreasToDesiredBounds();
  127. FinishAndStoreOverflow(&aDesiredSize);
  128. }
  129. nsresult
  130. nsFormControlFrame::RegUnRegAccessKey(nsIFrame * aFrame, bool aDoReg)
  131. {
  132. NS_ENSURE_ARG_POINTER(aFrame);
  133. nsPresContext* presContext = aFrame->PresContext();
  134. NS_ASSERTION(presContext, "aPresContext is NULL in RegUnRegAccessKey!");
  135. nsAutoString accessKey;
  136. nsIContent* content = aFrame->GetContent();
  137. content->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
  138. if (!accessKey.IsEmpty()) {
  139. EventStateManager* stateManager = presContext->EventStateManager();
  140. if (aDoReg) {
  141. stateManager->RegisterAccessKey(content, (uint32_t)accessKey.First());
  142. } else {
  143. stateManager->UnregisterAccessKey(content, (uint32_t)accessKey.First());
  144. }
  145. return NS_OK;
  146. }
  147. return NS_ERROR_FAILURE;
  148. }
  149. void
  150. nsFormControlFrame::SetFocus(bool aOn, bool aRepaint)
  151. {
  152. }
  153. nsresult
  154. nsFormControlFrame::HandleEvent(nsPresContext* aPresContext,
  155. WidgetGUIEvent* aEvent,
  156. nsEventStatus* aEventStatus)
  157. {
  158. // Check for user-input:none style
  159. const nsStyleUserInterface* uiStyle = StyleUserInterface();
  160. if (uiStyle->mUserInput == StyleUserInput::None ||
  161. uiStyle->mUserInput == StyleUserInput::Disabled) {
  162. return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
  163. }
  164. return NS_OK;
  165. }
  166. void
  167. nsFormControlFrame::GetCurrentCheckState(bool *aState)
  168. {
  169. nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
  170. if (inputElement) {
  171. inputElement->GetChecked(aState);
  172. }
  173. }
  174. nsresult
  175. nsFormControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
  176. {
  177. return NS_OK;
  178. }
  179. // static
  180. nsRect
  181. nsFormControlFrame::GetUsableScreenRect(nsPresContext* aPresContext)
  182. {
  183. nsRect screen;
  184. nsDeviceContext *context = aPresContext->DeviceContext();
  185. int32_t dropdownCanOverlapOSBar =
  186. LookAndFeel::GetInt(LookAndFeel::eIntID_MenusCanOverlapOSBar, 0);
  187. if ( dropdownCanOverlapOSBar )
  188. context->GetRect(screen);
  189. else
  190. context->GetClientRect(screen);
  191. return screen;
  192. }