summaryrefslogtreecommitdiffstats
path: root/layout/forms/nsHTMLButtonControlFrame.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:14:29 +0000
commitfbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 (patch)
tree4c1ccaf5486d4f2009f9a338a98a83e886e29c97 /layout/forms/nsHTMLButtonControlFrame.cpp
parentReleasing progress-linux version 124.0.1-1~progress7.99u1. (diff)
downloadfirefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.tar.xz
firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/forms/nsHTMLButtonControlFrame.cpp')
-rw-r--r--layout/forms/nsHTMLButtonControlFrame.cpp175
1 files changed, 150 insertions, 25 deletions
diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp
index 7a599f093b..cb24ccbfb9 100644
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -10,15 +10,17 @@
#include "mozilla/PresShell.h"
#include "nsIFrameInlines.h"
#include "nsContainerFrame.h"
+#include "nsPresContextInlines.h"
#include "nsIFormControlFrame.h"
#include "nsPresContext.h"
#include "nsLayoutUtils.h"
#include "nsGkAtoms.h"
-#include "nsButtonFrameRenderer.h"
#include "nsDisplayList.h"
+#include "nsCSSRendering.h"
#include <algorithm>
using namespace mozilla;
+using namespace mozilla::image;
nsContainerFrame* NS_NewHTMLButtonControlFrame(PresShell* aPresShell,
ComputedStyle* aStyle) {
@@ -39,7 +41,13 @@ void nsHTMLButtonControlFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
- mRenderer.SetFrame(this, PresContext());
+
+ // get all the styles
+ ServoStyleSet* styleSet = PresContext()->StyleSet();
+
+ // Get styles assigned to -moz-focus-inner (i.e. dotted border on Windows)
+ mInnerFocusStyle = styleSet->ProbePseudoElementStyle(
+ *mContent->AsElement(), PseudoStyleType::mozFocusInner, nullptr, Style());
}
NS_QUERYFRAME_HEAD(nsHTMLButtonControlFrame)
@@ -57,8 +65,8 @@ void nsHTMLButtonControlFrame::SetFocus(bool aOn, bool aRepaint) {}
nsresult nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) {
- // if disabled do nothing
- if (mRenderer.isDisabled()) {
+ if (mContent->AsElement()->IsDisabled()) {
+ // If disabled do nothing
return NS_OK;
}
@@ -67,14 +75,125 @@ nsresult nsHTMLButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
return nsIFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
-bool nsHTMLButtonControlFrame::ShouldClipPaintingToBorderBox() {
+bool nsHTMLButtonControlFrame::ShouldClipPaintingToBorderBox() const {
// FIXME(emilio): probably should account for per-axis clipping...
return StyleDisplay()->mOverflowX != StyleOverflow::Visible;
}
+namespace mozilla {
+
+class nsDisplayButtonForeground final : public nsPaintedDisplayItem {
+ public:
+ nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+ : nsPaintedDisplayItem(aBuilder, aFrame) {
+ MOZ_COUNT_CTOR(nsDisplayButtonForeground);
+ }
+ MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayButtonForeground)
+
+ void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
+ bool CreateWebRenderCommands(
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const StackingContextHelper& aSc,
+ mozilla::layers::RenderRootStateManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder) override;
+ NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND)
+};
+
+void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder,
+ gfxContext* aCtx) {
+ static_cast<nsHTMLButtonControlFrame*>(mFrame)->PaintInnerFocusBorder(
+ aBuilder, *aCtx, GetPaintRect(aBuilder, aCtx),
+ nsRect(ToReferenceFrame(), mFrame->GetSize()));
+}
+
+bool nsDisplayButtonForeground::CreateWebRenderCommands(
+ mozilla::wr::DisplayListBuilder& aBuilder,
+ mozilla::wr::IpcResourceUpdateQueue& aResources,
+ const StackingContextHelper& aSc,
+ mozilla::layers::RenderRootStateManager* aManager,
+ nsDisplayListBuilder* aDisplayListBuilder) {
+ bool borderIsEmpty = false;
+ bool dummy;
+ Maybe<nsCSSBorderRenderer> br =
+ static_cast<nsHTMLButtonControlFrame*>(mFrame)
+ ->CreateInnerFocusBorderRenderer(
+ aDisplayListBuilder, nullptr,
+ GetBounds(aDisplayListBuilder, &dummy),
+ nsRect(ToReferenceFrame(), mFrame->GetSize()), &borderIsEmpty);
+
+ if (!br) {
+ return borderIsEmpty;
+ }
+
+ aBuilder.StartGroup(this);
+ br->CreateWebRenderCommands(this, aBuilder, aResources, aSc);
+ aBuilder.FinishGroup();
+
+ return true;
+}
+
+} // namespace mozilla
+
+static nsRect GetButtonInnerFocusRect(const nsIFrame* aFrame,
+ const ComputedStyle& aFocusStyle,
+ const nsRect& aRect) {
+ nsRect result = aRect;
+ result.Deflate(aFrame->GetUsedBorderAndPadding());
+
+ nsMargin innerFocusPadding;
+ aFocusStyle.StylePadding()->GetPadding(innerFocusPadding);
+
+ nsMargin framePadding = aFrame->GetUsedPadding();
+ innerFocusPadding.top = std::min(innerFocusPadding.top, framePadding.top);
+ innerFocusPadding.right =
+ std::min(innerFocusPadding.right, framePadding.right);
+ innerFocusPadding.bottom =
+ std::min(innerFocusPadding.bottom, framePadding.bottom);
+ innerFocusPadding.left = std::min(innerFocusPadding.left, framePadding.left);
+
+ result.Inflate(innerFocusPadding);
+ return result;
+}
+
+void nsHTMLButtonControlFrame::PaintInnerFocusBorder(
+ nsDisplayListBuilder* aBuilder, gfxContext& aRenderingContext,
+ const nsRect& aDirtyRect, const nsRect& aRect) {
+ if (!mInnerFocusStyle) {
+ return;
+ }
+
+ // we draw the -moz-focus-inner border just inside the button's
+ // normal border and padding, to match Windows themes.
+ PaintBorderFlags flags = aBuilder->ShouldSyncDecodeImages()
+ ? PaintBorderFlags::SyncDecodeImages
+ : PaintBorderFlags();
+
+ nsRect rect = GetButtonInnerFocusRect(this, *mInnerFocusStyle, aRect);
+ // We don't paint border images here, so the ImgDrawResult is useless.
+ Unused << nsCSSRendering::PaintBorder(PresContext(), aRenderingContext, this,
+ aDirtyRect, rect, mInnerFocusStyle,
+ flags);
+}
+
+Maybe<nsCSSBorderRenderer>
+nsHTMLButtonControlFrame::CreateInnerFocusBorderRenderer(
+ nsDisplayListBuilder* aBuilder, gfxContext* aRenderingContext,
+ const nsRect& aDirtyRect, const nsRect& aRect, bool* aBorderIsEmpty) {
+ if (!mInnerFocusStyle) {
+ return Nothing();
+ }
+
+ nsRect rect = GetButtonInnerFocusRect(this, *mInnerFocusStyle, aRect);
+ gfx::DrawTarget* dt =
+ aRenderingContext ? aRenderingContext->GetDrawTarget() : nullptr;
+ return nsCSSRendering::CreateBorderRenderer(PresContext(), dt, this,
+ aDirtyRect, rect,
+ mInnerFocusStyle, aBorderIsEmpty);
+}
+
void nsHTMLButtonControlFrame::BuildDisplayList(
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) {
- nsDisplayList onTop(aBuilder);
if (IsVisibleForPainting()) {
// Clip the button itself to its border area for event hit testing.
Maybe<DisplayListClipState::AutoSaveRestore> eventClipState;
@@ -87,11 +206,9 @@ void nsHTMLButtonControlFrame::BuildDisplayList(
rect, hasRadii ? radii : nullptr);
}
- mRenderer.DisplayButton(aBuilder, aLists.BorderBackground(), &onTop);
+ DisplayBorderBackgroundOutline(aBuilder, aLists);
}
- nsDisplayListCollection set(aBuilder);
-
{
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
@@ -100,22 +217,23 @@ void nsHTMLButtonControlFrame::BuildDisplayList(
nsRect rect(aBuilder->ToReferenceFrame(this), GetSize());
rect.Deflate(border);
nscoord radii[8];
- bool hasRadii = GetPaddingBoxBorderRadii(radii);
+ const bool hasRadii = GetPaddingBoxBorderRadii(radii);
clipState.ClipContainingBlockDescendants(rect,
hasRadii ? radii : nullptr);
}
- BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), set,
+ BuildDisplayListForChild(aBuilder, mFrames.FirstChild(), aLists,
DisplayChildFlag::ForcePseudoStackingContext);
}
- // Put the foreground outline and focus rects on top of the children
- set.Content()->AppendToTop(&onTop);
- set.MoveTo(aLists);
-
- DisplayOutline(aBuilder, aLists);
+ // Put the foreground outline on top of the children.
+ if (IsVisibleForPainting() && mInnerFocusStyle &&
+ mInnerFocusStyle->StyleBorder()->HasBorder() && IsThemed() &&
+ PresContext()->Theme()->ThemeWantsButtonInnerFocusRing()) {
+ aLists.Content()->AppendNewToTop<nsDisplayButtonForeground>(aBuilder, this);
+ }
- // to draw border when selected in editor
+ // To draw border when selected in editor
DisplaySelectionOverlay(aBuilder, aLists.Content());
}
@@ -237,12 +355,14 @@ void nsHTMLButtonControlFrame::ReflowButtonContents(
// Button has a fixed block-size -- that's its content-box bSize.
buttonContentBox.BSize(wm) = aButtonReflowInput.ComputedBSize();
} else {
- // Button is intrinsically sized -- it should shrinkwrap the
- // button-contents' bSize. But if it has size containment in block axis,
- // ignore the contents and use contain-intrinsic-block-size.
- nscoord bSize = aButtonReflowInput.mFrame->ContainIntrinsicBSize().valueOr(
- contentsDesiredSize.BSize(wm));
-
+ // Button is intrinsically sized -- it should shrinkwrap the contents'
+ // bSize.
+ // If we have size containment in block axis, ignore the contents and use
+ // contain-intrinsic-block-size. The combobox content size with no content
+ // is one line-height, not zero.
+ const Maybe<nscoord> containBSize = ContainIntrinsicBSize(
+ IsComboboxControlFrame() ? aButtonReflowInput.GetLineHeight() : 0);
+ const nscoord bSize = containBSize.valueOr(contentsDesiredSize.BSize(wm));
// Make sure we obey min/max-bSize in the case when we're doing intrinsic
// sizing (we get it for free when we have a non-intrinsic
// aButtonReflowInput.ComputedBSize()). Note that we do this before
@@ -359,12 +479,17 @@ nsresult nsHTMLButtonControlFrame::SetFormProperty(nsAtom* aName,
ComputedStyle* nsHTMLButtonControlFrame::GetAdditionalComputedStyle(
int32_t aIndex) const {
- return mRenderer.GetComputedStyle(aIndex);
+ if (aIndex == 0) {
+ return mInnerFocusStyle;
+ }
+ return nullptr;
}
void nsHTMLButtonControlFrame::SetAdditionalComputedStyle(
int32_t aIndex, ComputedStyle* aComputedStyle) {
- mRenderer.SetComputedStyle(aIndex, aComputedStyle);
+ if (aIndex == 0) {
+ mInnerFocusStyle = aComputedStyle;
+ }
}
void nsHTMLButtonControlFrame::AppendDirectlyOwnedAnonBoxes(