LCOV - code coverage report
Current view: top level - layout/forms - nsHTMLButtonControlFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 175 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

          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             : #include "nsHTMLButtonControlFrame.h"
       7             : 
       8             : #include "nsContainerFrame.h"
       9             : #include "nsIFormControlFrame.h"
      10             : #include "nsPresContext.h"
      11             : #include "nsGkAtoms.h"
      12             : #include "nsButtonFrameRenderer.h"
      13             : #include "nsCSSAnonBoxes.h"
      14             : #include "nsFormControlFrame.h"
      15             : #include "nsNameSpaceManager.h"
      16             : #include "nsDisplayList.h"
      17             : #include <algorithm>
      18             : 
      19             : using namespace mozilla;
      20             : 
      21             : nsContainerFrame*
      22           0 : NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      23             : {
      24           0 :   return new (aPresShell) nsHTMLButtonControlFrame(aContext);
      25             : }
      26             : 
      27           0 : NS_IMPL_FRAMEARENA_HELPERS(nsHTMLButtonControlFrame)
      28             : 
      29           0 : nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsStyleContext* aContext,
      30           0 :                                                    nsIFrame::ClassID aID)
      31           0 :   : nsContainerFrame(aContext, aID)
      32             : {
      33           0 : }
      34             : 
      35           0 : nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
      36             : {
      37           0 : }
      38             : 
      39             : void
      40           0 : nsHTMLButtonControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
      41             : {
      42           0 :   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
      43           0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
      44           0 : }
      45             : 
      46             : void
      47           0 : nsHTMLButtonControlFrame::Init(nsIContent*       aContent,
      48             :                                nsContainerFrame* aParent,
      49             :                                nsIFrame*         aPrevInFlow)
      50             : {
      51           0 :   nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
      52           0 :   mRenderer.SetFrame(this, PresContext());
      53           0 : }
      54             : 
      55           0 : NS_QUERYFRAME_HEAD(nsHTMLButtonControlFrame)
      56           0 :   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
      57           0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      58             : 
      59             : #ifdef ACCESSIBILITY
      60             : a11y::AccType
      61           0 : nsHTMLButtonControlFrame::AccessibleType()
      62             : {
      63           0 :   return a11y::eHTMLButtonType;
      64             : }
      65             : #endif
      66             : 
      67             : void
      68           0 : nsHTMLButtonControlFrame::SetFocus(bool aOn, bool aRepaint)
      69             : {
      70           0 : }
      71             : 
      72             : nsresult
      73           0 : nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
      74             :                                       WidgetGUIEvent* aEvent,
      75             :                                       nsEventStatus* aEventStatus)
      76             : {
      77             :   // if disabled do nothing
      78           0 :   if (mRenderer.isDisabled()) {
      79           0 :     return NS_OK;
      80             :   }
      81             : 
      82             :   // mouse clicks are handled by content
      83             :   // we don't want our children to get any events. So just pass it to frame.
      84           0 :   return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
      85             : }
      86             : 
      87             : bool
      88           0 : nsHTMLButtonControlFrame::ShouldClipPaintingToBorderBox()
      89             : {
      90           0 :   return IsInput() || StyleDisplay()->mOverflowX != NS_STYLE_OVERFLOW_VISIBLE;
      91             : }
      92             : 
      93             : void
      94           0 : nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
      95             :                                            const nsRect&           aDirtyRect,
      96             :                                            const nsDisplayListSet& aLists)
      97             : {
      98             :   // Clip to our border area for event hit testing.
      99           0 :   Maybe<DisplayListClipState::AutoSaveRestore> eventClipState;
     100           0 :   const bool isForEventDelivery = aBuilder->IsForEventDelivery();
     101           0 :   if (isForEventDelivery) {
     102           0 :     eventClipState.emplace(aBuilder);
     103           0 :     nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
     104             :     nscoord radii[8];
     105           0 :     bool hasRadii = GetBorderRadii(radii);
     106           0 :     eventClipState->ClipContainingBlockDescendants(rect, hasRadii ? radii : nullptr);
     107             :   }
     108             : 
     109           0 :   nsDisplayList onTop;
     110           0 :   if (IsVisibleForPainting(aBuilder)) {
     111           0 :     mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
     112             :   }
     113             : 
     114           0 :   nsDisplayListCollection set;
     115             : 
     116             :   // Do not allow the child subtree to receive events.
     117           0 :   if (!isForEventDelivery) {
     118           0 :     DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     119             : 
     120           0 :     if (ShouldClipPaintingToBorderBox()) {
     121           0 :       nsMargin border = StyleBorder()->GetComputedBorder();
     122           0 :       nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
     123           0 :       rect.Deflate(border);
     124             :       nscoord radii[8];
     125           0 :       bool hasRadii = GetPaddingBoxBorderRadii(radii);
     126           0 :       clipState.ClipContainingBlockDescendants(rect, hasRadii ? radii : nullptr);
     127             :     }
     128             : 
     129           0 :     BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aDirtyRect, set,
     130           0 :                              DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
     131             :     // That should put the display items in set.Content()
     132             :   }
     133             : 
     134             :   // Put the foreground outline and focus rects on top of the children
     135           0 :   set.Content()->AppendToTop(&onTop);
     136           0 :   set.MoveTo(aLists);
     137             : 
     138           0 :   DisplayOutline(aBuilder, aLists);
     139             : 
     140             :   // to draw border when selected in editor
     141           0 :   DisplaySelectionOverlay(aBuilder, aLists.Content());
     142           0 : }
     143             : 
     144             : nscoord
     145           0 : nsHTMLButtonControlFrame::GetMinISize(gfxContext* aRenderingContext)
     146             : {
     147             :   nscoord result;
     148           0 :   DISPLAY_MIN_WIDTH(this, result);
     149             : 
     150           0 :   nsIFrame* kid = mFrames.FirstChild();
     151           0 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     152             :                                                 kid,
     153             :                                                 nsLayoutUtils::MIN_ISIZE);
     154             : 
     155           0 :   return result;
     156             : }
     157             : 
     158             : nscoord
     159           0 : nsHTMLButtonControlFrame::GetPrefISize(gfxContext* aRenderingContext)
     160             : {
     161             :   nscoord result;
     162           0 :   DISPLAY_PREF_WIDTH(this, result);
     163             : 
     164           0 :   nsIFrame* kid = mFrames.FirstChild();
     165           0 :   result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     166             :                                                 kid,
     167             :                                                 nsLayoutUtils::PREF_ISIZE);
     168             : 
     169           0 :   return result;
     170             : }
     171             : 
     172             : void
     173           0 : nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
     174             :                                  ReflowOutput& aDesiredSize,
     175             :                                  const ReflowInput& aReflowInput,
     176             :                                  nsReflowStatus& aStatus)
     177             : {
     178           0 :   MarkInReflow();
     179           0 :   DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame");
     180           0 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     181             : 
     182           0 :   if (mState & NS_FRAME_FIRST_REFLOW) {
     183           0 :     nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
     184             :   }
     185             : 
     186             :   // Reflow the child
     187           0 :   nsIFrame* firstKid = mFrames.FirstChild();
     188             : 
     189           0 :   MOZ_ASSERT(firstKid, "Button should have a child frame for its contents");
     190           0 :   MOZ_ASSERT(!firstKid->GetNextSibling(),
     191             :              "Button should have exactly one child frame");
     192           0 :   MOZ_ASSERT(firstKid->StyleContext()->GetPseudo() ==
     193             :              nsCSSAnonBoxes::buttonContent,
     194             :              "Button's child frame has unexpected pseudo type!");
     195             : 
     196             :   // XXXbz Eventually we may want to check-and-bail if
     197             :   // !aReflowInput.ShouldReflowAllKids() &&
     198             :   // !NS_SUBTREE_DIRTY(firstKid).
     199             :   // We'd need to cache our ascent for that, of course.
     200             : 
     201             :   // Reflow the contents of the button.
     202             :   // (This populates our aDesiredSize, too.)
     203             :   ReflowButtonContents(aPresContext, aDesiredSize,
     204           0 :                        aReflowInput, firstKid);
     205             : 
     206           0 :   if (!ShouldClipPaintingToBorderBox()) {
     207           0 :     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, firstKid);
     208             :   }
     209             :   // else, we ignore child overflow -- anything that overflows beyond our
     210             :   // own border-box will get clipped when painting.
     211             : 
     212           0 :   aStatus.Reset();
     213           0 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize,
     214           0 :                                  aReflowInput, aStatus);
     215             : 
     216             :   // We're always complete and we don't support overflow containers
     217             :   // so we shouldn't have a next-in-flow ever.
     218           0 :   aStatus.Reset();
     219           0 :   MOZ_ASSERT(!GetNextInFlow());
     220             : 
     221           0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     222           0 : }
     223             : 
     224             : void
     225           0 : nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
     226             :                                                ReflowOutput& aButtonDesiredSize,
     227             :                                                const ReflowInput& aButtonReflowInput,
     228             :                                                nsIFrame* aFirstKid)
     229             : {
     230           0 :   WritingMode wm = GetWritingMode();
     231           0 :   LogicalSize availSize = aButtonReflowInput.ComputedSize(wm);
     232           0 :   availSize.BSize(wm) = NS_INTRINSICSIZE;
     233             : 
     234             :   // shorthand for a value we need to use in a bunch of places
     235           0 :   const LogicalMargin& clbp = aButtonReflowInput.ComputedLogicalBorderPadding();
     236             : 
     237           0 :   LogicalPoint childPos(wm);
     238           0 :   childPos.I(wm) = clbp.IStart(wm);
     239           0 :   availSize.ISize(wm) = std::max(availSize.ISize(wm), 0);
     240             : 
     241             :   ReflowInput contentsReflowInput(aPresContext, aButtonReflowInput,
     242           0 :                                   aFirstKid, availSize);
     243             : 
     244           0 :   nsReflowStatus contentsReflowStatus;
     245           0 :   ReflowOutput contentsDesiredSize(aButtonReflowInput);
     246           0 :   childPos.B(wm) = 0; // This will be set properly later, after reflowing the
     247             :                       // child to determine its size.
     248             : 
     249             :   // We just pass a dummy containerSize here, as the child will be
     250             :   // repositioned later by FinishReflowChild.
     251           0 :   nsSize dummyContainerSize;
     252           0 :   ReflowChild(aFirstKid, aPresContext,
     253             :               contentsDesiredSize, contentsReflowInput,
     254           0 :               wm, childPos, dummyContainerSize, 0, contentsReflowStatus);
     255           0 :   MOZ_ASSERT(contentsReflowStatus.IsComplete(),
     256             :              "We gave button-contents frame unconstrained available height, "
     257             :              "so it should be complete");
     258             : 
     259             :   // Compute the button's content-box size:
     260           0 :   LogicalSize buttonContentBox(wm);
     261           0 :   if (aButtonReflowInput.ComputedBSize() != NS_INTRINSICSIZE) {
     262             :     // Button has a fixed block-size -- that's its content-box bSize.
     263           0 :     buttonContentBox.BSize(wm) = aButtonReflowInput.ComputedBSize();
     264             :   } else {
     265             :     // Button is intrinsically sized -- it should shrinkwrap the
     266             :     // button-contents' bSize:
     267           0 :     buttonContentBox.BSize(wm) = contentsDesiredSize.BSize(wm);
     268             : 
     269             :     // Make sure we obey min/max-bSize in the case when we're doing intrinsic
     270             :     // sizing (we get it for free when we have a non-intrinsic
     271             :     // aButtonReflowInput.ComputedBSize()).  Note that we do this before
     272             :     // adjusting for borderpadding, since mComputedMaxBSize and
     273             :     // mComputedMinBSize are content bSizes.
     274           0 :     buttonContentBox.BSize(wm) =
     275           0 :       NS_CSS_MINMAX(buttonContentBox.BSize(wm),
     276             :                     aButtonReflowInput.ComputedMinBSize(),
     277             :                     aButtonReflowInput.ComputedMaxBSize());
     278             :   }
     279           0 :   if (aButtonReflowInput.ComputedISize() != NS_INTRINSICSIZE) {
     280           0 :     buttonContentBox.ISize(wm) = aButtonReflowInput.ComputedISize();
     281             :   } else {
     282           0 :     buttonContentBox.ISize(wm) = contentsDesiredSize.ISize(wm);
     283           0 :     buttonContentBox.ISize(wm) =
     284           0 :       NS_CSS_MINMAX(buttonContentBox.ISize(wm),
     285             :                     aButtonReflowInput.ComputedMinISize(),
     286             :                     aButtonReflowInput.ComputedMaxISize());
     287             :   }
     288             : 
     289             :   // Center child in the block-direction in the button
     290             :   // (technically, inside of the button's focus-padding area)
     291           0 :   nscoord extraSpace = buttonContentBox.BSize(wm) -
     292           0 :                        contentsDesiredSize.BSize(wm);
     293             : 
     294           0 :   childPos.B(wm) = std::max(0, extraSpace / 2);
     295             : 
     296             :   // Adjust childPos.B() to be in terms of the button's frame-rect:
     297           0 :   childPos.B(wm) += clbp.BStart(wm);
     298             : 
     299             :   nsSize containerSize =
     300           0 :     (buttonContentBox + clbp.Size(wm)).GetPhysicalSize(wm);
     301             : 
     302             :   // Place the child
     303             :   FinishReflowChild(aFirstKid, aPresContext,
     304             :                     contentsDesiredSize, &contentsReflowInput,
     305           0 :                     wm, childPos, containerSize, 0);
     306             : 
     307             :   // Make sure we have a useful 'ascent' value for the child
     308           0 :   if (contentsDesiredSize.BlockStartAscent() ==
     309             :       ReflowOutput::ASK_FOR_BASELINE) {
     310           0 :     WritingMode wm = aButtonReflowInput.GetWritingMode();
     311           0 :     contentsDesiredSize.SetBlockStartAscent(aFirstKid->GetLogicalBaseline(wm));
     312             :   }
     313             : 
     314             :   // OK, we're done with the child frame.
     315             :   // Use what we learned to populate the button frame's reflow metrics.
     316             :   //  * Button's height & width are content-box size + border-box contribution:
     317           0 :   aButtonDesiredSize.SetSize(wm,
     318           0 :     LogicalSize(wm, aButtonReflowInput.ComputedISize() + clbp.IStartEnd(wm),
     319           0 :                     buttonContentBox.BSize(wm) + clbp.BStartEnd(wm)));
     320             : 
     321             :   //  * Button's ascent is its child's ascent, plus the child's block-offset
     322             :   // within our frame... unless it's orthogonal, in which case we'll use the
     323             :   // contents inline-size as an approximation for now.
     324             :   // XXX is there a better strategy? should we include border-padding?
     325           0 :   if (aButtonDesiredSize.GetWritingMode().IsOrthogonalTo(wm)) {
     326           0 :     aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.ISize(wm));
     327             :   } else {
     328           0 :     aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.BlockStartAscent() +
     329           0 :                                            childPos.B(wm));
     330             :   }
     331             : 
     332           0 :   aButtonDesiredSize.SetOverflowAreasToDesiredBounds();
     333           0 : }
     334             : 
     335             : bool
     336           0 : nsHTMLButtonControlFrame::GetVerticalAlignBaseline(mozilla::WritingMode aWM,
     337             :                                                    nscoord* aBaseline) const
     338             : {
     339           0 :   nsIFrame* inner = mFrames.FirstChild();
     340           0 :   if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) {
     341           0 :     return false;
     342             :   }
     343           0 :   if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) {
     344             :     // <input type=color> has an empty block frame as inner frame
     345           0 :     *aBaseline = inner->
     346           0 :       SynthesizeBaselineBOffsetFromBorderBox(aWM, BaselineSharingGroup::eFirst);
     347             :   }
     348           0 :   nscoord innerBStart = inner->BStart(aWM, GetSize());
     349           0 :   *aBaseline += innerBStart;
     350           0 :   return true;
     351             : }
     352             : 
     353             : bool
     354           0 : nsHTMLButtonControlFrame::GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
     355             :                                          BaselineSharingGroup aBaselineGroup,
     356             :                                          nscoord* aBaseline) const
     357             : {
     358           0 :   nsIFrame* inner = mFrames.FirstChild();
     359           0 :   if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) {
     360           0 :     return false;
     361             :   }
     362           0 :   if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) {
     363             :     // <input type=color> has an empty block frame as inner frame
     364           0 :     *aBaseline = inner->
     365           0 :       SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup);
     366             :   }
     367           0 :   nscoord innerBStart = inner->BStart(aWM, GetSize());
     368           0 :   if (aBaselineGroup == BaselineSharingGroup::eFirst) {
     369           0 :     *aBaseline += innerBStart;
     370             :   } else {
     371           0 :     *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM));
     372             :   }
     373           0 :   return true;
     374             : }
     375             : 
     376           0 : nsresult nsHTMLButtonControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue)
     377             : {
     378           0 :   if (nsGkAtoms::value == aName) {
     379           0 :     return mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::value,
     380           0 :                              aValue, true);
     381             :   }
     382           0 :   return NS_OK;
     383             : }
     384             : 
     385             : nsStyleContext*
     386           0 : nsHTMLButtonControlFrame::GetAdditionalStyleContext(int32_t aIndex) const
     387             : {
     388           0 :   return mRenderer.GetStyleContext(aIndex);
     389             : }
     390             : 
     391             : void
     392           0 : nsHTMLButtonControlFrame::SetAdditionalStyleContext(int32_t aIndex,
     393             :                                                     nsStyleContext* aStyleContext)
     394             : {
     395           0 :   mRenderer.SetStyleContext(aIndex, aStyleContext);
     396           0 : }
     397             : 
     398             : void
     399           0 : nsHTMLButtonControlFrame::AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult)
     400             : {
     401           0 :   MOZ_ASSERT(mFrames.FirstChild(), "Must have our button-content anon box");
     402           0 :   MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
     403             :              "Must only have our button-content anon box");
     404           0 :   aResult.AppendElement(OwnedAnonBox(mFrames.FirstChild()));
     405           0 : }
     406             : 
     407             : #ifdef DEBUG
     408             : void
     409           0 : nsHTMLButtonControlFrame::AppendFrames(ChildListID     aListID,
     410             :                                        nsFrameList&    aFrameList)
     411             : {
     412           0 :   MOZ_CRASH("unsupported operation");
     413             : }
     414             : 
     415             : void
     416           0 : nsHTMLButtonControlFrame::InsertFrames(ChildListID     aListID,
     417             :                                        nsIFrame*       aPrevFrame,
     418             :                                        nsFrameList&    aFrameList)
     419             : {
     420           0 :   MOZ_CRASH("unsupported operation");
     421             : }
     422             : 
     423             : void
     424           0 : nsHTMLButtonControlFrame::RemoveFrame(ChildListID     aListID,
     425             :                                       nsIFrame*       aOldFrame)
     426             : {
     427           0 :   MOZ_CRASH("unsupported operation");
     428             : }
     429             : #endif

Generated by: LCOV version 1.13