Skip to content

Commit

Permalink
Bug 1699937 - Don't draw focus outlines for box-shadow in the non-nat…
Browse files Browse the repository at this point in the history
…ive theme. r=mstange

This is a relatively easy way to improve the rendering with the
non-native theme while not regressing anything.

In the future, once non-native-theme is shipped and default everywhere,
I think we could provide something like:

  bool nsITheme::GetShadowRect(nsIFrame*, StyleAppearance, LayoutDeviceRect&, RectCornerRadii&)

or such, where we can provide a precise rect + radii, and we would avoid
painting the shadow if the function returned false. That would allow us
to remove the native theme box shadow code path, and avoid WR fallback,
all at once.

Differential Revision: https://phabricator.services.mozilla.com/D109209
  • Loading branch information
emilio committed Mar 20, 2021
1 parent 2ccf297 commit 4cf5ef7
Show file tree
Hide file tree
Showing 15 changed files with 45 additions and 22 deletions.
7 changes: 6 additions & 1 deletion gfx/src/nsITheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,16 @@ class nsITheme : public nsISupports {
* @param aWidgetType the -moz-appearance value to draw
* @param aRect the rectangle defining the area occupied by the widget
* @param aDirtyRect the rectangle that needs to be drawn
* @param DrawOverflow whether outlines, shadows and other such overflowing
* things should be drawn. Honoring this creates better results for
* box-shadow, though it's not a hard requirement.
*/
enum class DrawOverflow { No, Yes };
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aWidgetType,
const nsRect& aRect,
const nsRect& aDirtyRect) = 0;
const nsRect& aDirtyRect,
DrawOverflow = DrawOverflow::Yes) = 0;

/**
* Create WebRender commands for the theme background.
Expand Down
2 changes: 1 addition & 1 deletion layout/painting/nsCSSRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ void nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
nativeRect.IntersectRect(frameRect, nativeRect);
aPresContext->Theme()->DrawWidgetBackground(
shadowContext, aForFrame, styleDisplay->EffectiveAppearance(),
aFrameArea, nativeRect);
aFrameArea, nativeRect, nsITheme::DrawOverflow::No);

blurringArea.DoPaint();
aRenderingContext.Restore();
Expand Down
9 changes: 5 additions & 4 deletions layout/painting/nsDisplayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5117,12 +5117,13 @@ bool nsDisplayBoxShadowOuter::CanBuildWebRenderDisplayItems() {
}

bool hasBorderRadius;
bool nativeTheme =
nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius);

// We don't support native themed things yet like box shadows around
// input buttons.
if (nativeTheme) {
//
// TODO(emilio): The non-native theme could provide the right rect+radius
// instead relatively painlessly, if we find this causes performance issues or
// what not.
if (nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius)) {
return false;
}

Expand Down
3 changes: 2 additions & 1 deletion widget/android/nsNativeThemeAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ nsNativeThemeAndroid::DrawWidgetBackground(gfxContext* aContext,
nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& /* aDirtyRect */) {
const nsRect& /* aDirtyRect */,
DrawOverflow) {
DrawTarget* dt = aContext->GetDrawTarget();
const nscoord twipsPerPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
EventStates eventState = GetContentState(aFrame, aAppearance);
Expand Down
3 changes: 2 additions & 1 deletion widget/android/nsNativeThemeAndroid.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class nsNativeThemeAndroid : private nsNativeTheme, public nsITheme {
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;
/*bool CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBuilder&
aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, const
mozilla::layers::StackingContextHelper& aSc,
Expand Down
3 changes: 2 additions & 1 deletion widget/cocoa/nsNativeThemeCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ class nsNativeThemeCocoa : private nsNativeTheme, public nsITheme {
// The nsITheme interface.
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;
bool CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const mozilla::layers::StackingContextHelper& aSc,
Expand Down
3 changes: 2 additions & 1 deletion widget/cocoa/nsNativeThemeCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2646,7 +2646,8 @@ static bool IsHiDPIContext(nsDeviceContext* aContext) {
NS_IMETHODIMP
nsNativeThemeCocoa::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance, const nsRect& aRect,
const nsRect& aDirtyRect) {
const nsRect& aDirtyRect,
DrawOverflow) {
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;

Maybe<WidgetInfo> widgetInfo = ComputeWidgetInfo(aFrame, aAppearance, aRect);
Expand Down
3 changes: 2 additions & 1 deletion widget/gtk/nsNativeThemeGTK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,8 @@ NS_IMETHODIMP
nsNativeThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) {
const nsRect& aDirtyRect,
DrawOverflow) {
GtkWidgetState state;
WidgetNodeType gtkWidgetType;
GtkTextDirection direction = GetTextDirection(aFrame);
Expand Down
3 changes: 2 additions & 1 deletion widget/gtk/nsNativeThemeGTK.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class nsNativeThemeGTK final : private nsNativeTheme,
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;

bool CreateWebRenderCommandsForWidget(
mozilla::wr::DisplayListBuilder& aBuilder,
Expand Down
3 changes: 2 additions & 1 deletion widget/headless/HeadlessThemeGTK.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ NS_IMETHODIMP
HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) {
const nsRect& aDirtyRect,
DrawOverflow) {
return NS_OK;
}

Expand Down
3 changes: 2 additions & 1 deletion widget/headless/HeadlessThemeGTK.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class HeadlessThemeGTK final : private nsNativeTheme, public nsITheme {
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;

[[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(
nsDeviceContext* aContext, nsIFrame* aFrame,
Expand Down
14 changes: 10 additions & 4 deletions widget/nsNativeBasicTheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,9 +1580,10 @@ NS_IMETHODIMP
nsNativeBasicTheme::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& /* aDirtyRect */) {
const nsRect& /* aDirtyRect */,
DrawOverflow aDrawOverflow) {
if (!DoDrawWidgetBackground(*aContext->GetDrawTarget(), aFrame, aAppearance,
aRect)) {
aRect, aDrawOverflow)) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
Expand All @@ -1598,7 +1599,7 @@ bool nsNativeBasicTheme::CreateWebRenderCommandsForWidget(
return false;
}
WebRenderBackendData data{aBuilder, aResources, aSc, aManager};
return DoDrawWidgetBackground(data, aFrame, aAppearance, aRect);
return DoDrawWidgetBackground(data, aFrame, aAppearance, aRect, DrawOverflow::Yes);
}

static LayoutDeviceRect ToSnappedRect(const nsRect& aRect,
Expand Down Expand Up @@ -1626,7 +1627,8 @@ template <typename PaintBackendData>
bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect) {
const nsRect& aRect,
DrawOverflow aDrawOverflow) {
static_assert(std::is_same_v<PaintBackendData, DrawTarget> ||
std::is_same_v<PaintBackendData, WebRenderBackendData>);

Expand All @@ -1649,6 +1651,10 @@ bool nsNativeBasicTheme::DoDrawWidgetBackground(PaintBackendData& aPaintData,
}
}

if (aDrawOverflow == DrawOverflow::No) {
eventState &= ~NS_EVENT_STATE_FOCUSRING;
}

// Hack to avoid skia fuzziness: Add a dummy clip if the widget doesn't
// overflow devPxRect.
Maybe<AutoClipRect> maybeClipRect;
Expand Down
5 changes: 3 additions & 2 deletions widget/nsNativeBasicTheme.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
// The nsITheme interface.
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame*,
StyleAppearance, const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;

struct WebRenderBackendData {
mozilla::wr::DisplayListBuilder& mBuilder;
Expand All @@ -135,7 +136,7 @@ class nsNativeBasicTheme : protected nsNativeTheme, public nsITheme {
// given back-end.
template <typename PaintBackendData>
bool DoDrawWidgetBackground(PaintBackendData&, nsIFrame*, StyleAppearance,
const nsRect& aRect);
const nsRect&, DrawOverflow);

[[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext,
nsIFrame*,
Expand Down
3 changes: 2 additions & 1 deletion widget/windows/nsNativeThemeWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,8 @@ NS_IMETHODIMP
nsNativeThemeWin::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) {
const nsRect& aDirtyRect,
DrawOverflow) {
if (IsWidgetScrollbarPart(aAppearance)) {
if (MayDrawCustomScrollbarPart(aContext, aFrame, aAppearance, aRect,
aDirtyRect)) {
Expand Down
3 changes: 2 additions & 1 deletion widget/windows/nsNativeThemeWin.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class nsNativeThemeWin : private nsNativeTheme, public nsITheme {
NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
StyleAppearance aAppearance,
const nsRect& aRect,
const nsRect& aDirtyRect) override;
const nsRect& aDirtyRect,
DrawOverflow) override;

[[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(
nsDeviceContext* aContext, nsIFrame* aFrame,
Expand Down

0 comments on commit 4cf5ef7

Please sign in to comment.