Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/forms/nsButtonFrameRenderer.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
#include "nsButtonFrameRenderer.h"
7
#include "nsCSSRendering.h"
8
#include "nsPresContext.h"
9
#include "nsGkAtoms.h"
10
#include "nsCSSPseudoElements.h"
11
#include "nsNameSpaceManager.h"
12
#include "mozilla/ServoStyleSet.h"
13
#include "mozilla/Unused.h"
14
#include "nsDisplayList.h"
15
#include "nsITheme.h"
16
#include "nsFrame.h"
17
#include "mozilla/EventStates.h"
18
#include "mozilla/dom/Element.h"
19
#include "Layers.h"
20
#include "gfxPrefs.h"
21
#include "gfxUtils.h"
22
#include "mozilla/layers/WebRenderLayerManager.h"
23
24
#define ACTIVE   "active"
25
#define HOVER    "hover"
26
#define FOCUS    "focus"
27
28
using namespace mozilla;
29
using namespace mozilla::image;
30
using namespace mozilla::layers;
31
32
nsButtonFrameRenderer::nsButtonFrameRenderer()
33
  : mFrame(nullptr)
34
0
{
35
0
  MOZ_COUNT_CTOR(nsButtonFrameRenderer);
36
0
}
37
38
nsButtonFrameRenderer::~nsButtonFrameRenderer()
39
0
{
40
0
  MOZ_COUNT_DTOR(nsButtonFrameRenderer);
41
0
}
42
43
void
44
nsButtonFrameRenderer::SetFrame(nsFrame* aFrame, nsPresContext* aPresContext)
45
0
{
46
0
  mFrame = aFrame;
47
0
  ReResolveStyles(aPresContext);
48
0
}
49
50
nsIFrame*
51
nsButtonFrameRenderer::GetFrame()
52
0
{
53
0
  return mFrame;
54
0
}
55
56
void
57
nsButtonFrameRenderer::SetDisabled(bool aDisabled, bool aNotify)
58
0
{
59
0
  Element* element = mFrame->GetContent()->AsElement();
60
0
  if (aDisabled)
61
0
    element->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled, EmptyString(),
62
0
                     aNotify);
63
0
  else
64
0
    element->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, aNotify);
65
0
}
66
67
bool
68
nsButtonFrameRenderer::isDisabled()
69
0
{
70
0
  return mFrame->GetContent()->AsElement()->
71
0
    State().HasState(NS_EVENT_STATE_DISABLED);
72
0
}
73
74
class nsDisplayButtonBoxShadowOuter : public nsDisplayItem {
75
public:
76
  nsDisplayButtonBoxShadowOuter(nsDisplayListBuilder* aBuilder,
77
                                nsButtonFrameRenderer* aRenderer)
78
0
    : nsDisplayItem(aBuilder, aRenderer->GetFrame()) {
79
0
    MOZ_COUNT_CTOR(nsDisplayButtonBoxShadowOuter);
80
0
  }
81
#ifdef NS_BUILD_REFCNT_LOGGING
82
  virtual ~nsDisplayButtonBoxShadowOuter() {
83
    MOZ_COUNT_DTOR(nsDisplayButtonBoxShadowOuter);
84
  }
85
#endif
86
87
  virtual bool CreateWebRenderCommands(
88
    mozilla::wr::DisplayListBuilder& aBuilder,
89
    mozilla::wr::IpcResourceUpdateQueue& aResources,
90
    const StackingContextHelper& aSc,
91
    mozilla::layers::WebRenderLayerManager* aManager,
92
    nsDisplayListBuilder* aDisplayListBuilder) override;
93
94
  bool CanBuildWebRenderDisplayItems();
95
96
  virtual void Paint(nsDisplayListBuilder* aBuilder,
97
                     gfxContext* aCtx) override;
98
  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
99
                           bool* aSnap) const override;
100
  NS_DISPLAY_DECL_NAME("ButtonBoxShadowOuter", TYPE_BUTTON_BOX_SHADOW_OUTER)
101
};
102
103
nsRect
104
nsDisplayButtonBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder,
105
                                         bool* aSnap) const
106
0
{
107
0
  *aSnap = false;
108
0
  return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
109
0
}
110
111
void
112
nsDisplayButtonBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
113
0
                                     gfxContext* aCtx) {
114
0
  nsRect frameRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
115
0
116
0
  nsCSSRendering::PaintBoxShadowOuter(mFrame->PresContext(), *aCtx, mFrame,
117
0
                                      frameRect, GetPaintRect());
118
0
}
119
120
bool
121
nsDisplayButtonBoxShadowOuter::CanBuildWebRenderDisplayItems()
122
0
{
123
0
  nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
124
0
  if (!shadows) {
125
0
    return false;
126
0
  }
127
0
128
0
  bool hasBorderRadius;
129
0
  bool nativeTheme =
130
0
    nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius);
131
0
132
0
  // We don't support native themed things yet like box shadows around
133
0
  // input buttons.
134
0
  if (nativeTheme) {
135
0
    return false;
136
0
  }
137
0
138
0
  return true;
139
0
}
140
141
bool
142
nsDisplayButtonBoxShadowOuter::CreateWebRenderCommands(
143
  mozilla::wr::DisplayListBuilder& aBuilder,
144
  mozilla::wr::IpcResourceUpdateQueue& aResources,
145
  const StackingContextHelper& aSc,
146
  mozilla::layers::WebRenderLayerManager* aManager,
147
  nsDisplayListBuilder* aDisplayListBuilder)
148
0
{
149
0
  if (!CanBuildWebRenderDisplayItems()) {
150
0
    return false;
151
0
  }
152
0
  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
153
0
  nsRect shadowRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
154
0
  LayoutDeviceRect deviceBox =
155
0
    LayoutDeviceRect::FromAppUnits(shadowRect, appUnitsPerDevPixel);
156
0
  wr::LayoutRect deviceBoxRect = wr::ToRoundedLayoutRect(deviceBox);
157
0
158
0
  LayoutDeviceRect clipRect =
159
0
    LayoutDeviceRect::FromAppUnits(GetPaintRect(), appUnitsPerDevPixel);
160
0
  wr::LayoutRect deviceClipRect = wr::ToRoundedLayoutRect(clipRect);
161
0
162
0
  bool hasBorderRadius;
163
0
  Unused << nsCSSRendering::HasBoxShadowNativeTheme(mFrame, hasBorderRadius);
164
0
165
0
  LayoutDeviceSize zeroSize;
166
0
  wr::BorderRadius borderRadius = wr::ToBorderRadius(zeroSize, zeroSize,
167
0
                                                     zeroSize, zeroSize);
168
0
  if (hasBorderRadius) {
169
0
    mozilla::gfx::RectCornerRadii borderRadii;
170
0
    hasBorderRadius = nsCSSRendering::GetBorderRadii(
171
0
      shadowRect, shadowRect, mFrame, borderRadii);
172
0
    if (hasBorderRadius) {
173
0
      borderRadius = wr::ToBorderRadius(
174
0
        LayoutDeviceSize::FromUnknownSize(borderRadii.TopLeft()),
175
0
        LayoutDeviceSize::FromUnknownSize(borderRadii.TopRight()),
176
0
        LayoutDeviceSize::FromUnknownSize(borderRadii.BottomLeft()),
177
0
        LayoutDeviceSize::FromUnknownSize(borderRadii.BottomRight()));
178
0
    }
179
0
180
0
  }
181
0
182
0
  nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
183
0
  MOZ_ASSERT(shadows);
184
0
185
0
  for (uint32_t i = shadows->Length(); i > 0; i--) {
186
0
    nsCSSShadowItem* shadow = shadows->ShadowAt(i - 1);
187
0
    if (shadow->mInset) {
188
0
      continue;
189
0
    }
190
0
    float blurRadius = float(shadow->mRadius) / float(appUnitsPerDevPixel);
191
0
    gfx::Color shadowColor =
192
0
      nsCSSRendering::GetShadowColor(shadow, mFrame, 1.0);
193
0
194
0
    LayoutDevicePoint shadowOffset = LayoutDevicePoint::FromAppUnits(
195
0
        nsPoint(shadow->mXOffset, shadow->mYOffset),
196
0
        appUnitsPerDevPixel);
197
0
198
0
    float spreadRadius = float(shadow->mSpread) / float(appUnitsPerDevPixel);
199
0
200
0
    aBuilder.PushBoxShadow(deviceBoxRect,
201
0
                           deviceClipRect,
202
0
                           !BackfaceIsHidden(),
203
0
                           deviceBoxRect,
204
0
                           wr::ToLayoutVector2D(shadowOffset),
205
0
                           wr::ToColorF(shadowColor),
206
0
                           blurRadius,
207
0
                           spreadRadius,
208
0
                           borderRadius,
209
0
                           wr::BoxShadowClipMode::Outset);
210
0
  }
211
0
  return true;
212
0
}
213
214
class nsDisplayButtonBorder final : public nsDisplayItem
215
{
216
public:
217
  nsDisplayButtonBorder(nsDisplayListBuilder* aBuilder,
218
                                  nsButtonFrameRenderer* aRenderer)
219
    : nsDisplayItem(aBuilder, aRenderer->GetFrame())
220
    , mBFR(aRenderer)
221
0
  {
222
0
    MOZ_COUNT_CTOR(nsDisplayButtonBorder);
223
0
  }
224
#ifdef NS_BUILD_REFCNT_LOGGING
225
  virtual ~nsDisplayButtonBorder() {
226
    MOZ_COUNT_DTOR(nsDisplayButtonBorder);
227
  }
228
#endif
229
0
  virtual bool MustPaintOnContentSide() const override { return true; }
230
231
  virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
232
                       HitTestState* aState,
233
0
                       nsTArray<nsIFrame*> *aOutFrames) override {
234
0
    aOutFrames->AppendElement(mFrame);
235
0
  }
236
  virtual void Paint(nsDisplayListBuilder* aBuilder,
237
                     gfxContext* aCtx) override;
238
  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
239
                           bool* aSnap) const override;
240
  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
241
  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
242
                                         const nsDisplayItemGeometry* aGeometry,
243
                                         nsRegion *aInvalidRegion) const override;
244
  virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
245
                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
246
                                       const StackingContextHelper& aSc,
247
                                       mozilla::layers::WebRenderLayerManager* aManager,
248
                                       nsDisplayListBuilder* aDisplayListBuilder) override;
249
  NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
250
private:
251
  nsButtonFrameRenderer* mBFR;
252
};
253
254
nsDisplayItemGeometry*
255
nsDisplayButtonBorder::AllocateGeometry(nsDisplayListBuilder* aBuilder)
256
0
{
257
0
  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
258
0
}
259
260
bool
261
nsDisplayButtonBorder::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
262
                                               mozilla::wr::IpcResourceUpdateQueue& aResources,
263
                                               const StackingContextHelper& aSc,
264
                                               mozilla::layers::WebRenderLayerManager* aManager,
265
                                               nsDisplayListBuilder* aDisplayListBuilder)
266
0
{
267
0
  // This is really a combination of paint box shadow inner +
268
0
  // paint border.
269
0
  nsRect buttonRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
270
0
  bool snap;
271
0
  nsRegion visible = GetBounds(aDisplayListBuilder, &snap);
272
0
  nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(aBuilder,
273
0
                                                                 aSc,
274
0
                                                                 visible,
275
0
                                                                 mFrame,
276
0
                                                                 buttonRect);
277
0
278
0
  bool borderIsEmpty = false;
279
0
  Maybe<nsCSSBorderRenderer> br =
280
0
  nsCSSRendering::CreateBorderRenderer(mFrame->PresContext(),
281
0
                                       nullptr,
282
0
                                       mFrame,
283
0
                                       nsRect(),
284
0
                                       nsRect(ToReferenceFrame(), mFrame->GetSize()),
285
0
                                       mFrame->Style(),
286
0
                                       &borderIsEmpty,
287
0
                                       mFrame->GetSkipSides());
288
0
  if (!br) {
289
0
    return borderIsEmpty;
290
0
  }
291
0
292
0
  br->CreateWebRenderCommands(this, aBuilder, aResources, aSc);
293
0
294
0
  return true;
295
0
}
296
297
void
298
nsDisplayButtonBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
299
                                                 const nsDisplayItemGeometry* aGeometry,
300
                                                 nsRegion *aInvalidRegion) const
301
0
{
302
0
  auto geometry =
303
0
    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
304
0
305
0
  if (aBuilder->ShouldSyncDecodeImages() &&
306
0
      geometry->ShouldInvalidateToSyncDecodeImages()) {
307
0
    bool snap;
308
0
    aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
309
0
  }
310
0
311
0
  nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
312
0
}
313
314
void
315
nsDisplayButtonBorder::Paint(nsDisplayListBuilder* aBuilder,
316
                             gfxContext* aCtx)
317
0
{
318
0
  NS_ASSERTION(mFrame, "No frame?");
319
0
  nsPresContext* pc = mFrame->PresContext();
320
0
  nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
321
0
322
0
  // draw the border and background inside the focus and outline borders
323
0
  ImgDrawResult result =
324
0
    mBFR->PaintBorder(aBuilder, pc, *aCtx, GetPaintRect(), r);
325
0
326
0
  nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
327
0
}
328
329
nsRect
330
nsDisplayButtonBorder::GetBounds(nsDisplayListBuilder* aBuilder,
331
                                 bool* aSnap) const
332
0
{
333
0
  *aSnap = false;
334
0
  return aBuilder->IsForEventDelivery() ? nsRect(ToReferenceFrame(), mFrame->GetSize())
335
0
          : mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
336
0
}
337
338
class nsDisplayButtonForeground final : public nsDisplayItem
339
{
340
public:
341
  nsDisplayButtonForeground(nsDisplayListBuilder* aBuilder,
342
                            nsButtonFrameRenderer* aRenderer)
343
0
    : nsDisplayItem(aBuilder, aRenderer->GetFrame()), mBFR(aRenderer) {
344
0
    MOZ_COUNT_CTOR(nsDisplayButtonForeground);
345
0
  }
346
#ifdef NS_BUILD_REFCNT_LOGGING
347
  virtual ~nsDisplayButtonForeground() {
348
    MOZ_COUNT_DTOR(nsDisplayButtonForeground);
349
  }
350
#endif
351
352
  nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override;
353
  void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
354
                                 const nsDisplayItemGeometry* aGeometry,
355
                                 nsRegion *aInvalidRegion) const override;
356
  virtual void Paint(nsDisplayListBuilder* aBuilder,
357
                     gfxContext* aCtx) override;
358
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
359
                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
360
                                        const StackingContextHelper& aSc,
361
                                        mozilla::layers::WebRenderLayerManager* aManager,
362
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
363
  NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND)
364
private:
365
  nsButtonFrameRenderer* mBFR;
366
};
367
368
nsDisplayItemGeometry*
369
nsDisplayButtonForeground::AllocateGeometry(nsDisplayListBuilder* aBuilder)
370
0
{
371
0
  return new nsDisplayItemGenericImageGeometry(this, aBuilder);
372
0
}
373
374
void
375
nsDisplayButtonForeground::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
376
                                                     const nsDisplayItemGeometry* aGeometry,
377
                                                     nsRegion* aInvalidRegion) const
378
0
{
379
0
  auto geometry =
380
0
    static_cast<const nsDisplayItemGenericImageGeometry*>(aGeometry);
381
0
382
0
  if (aBuilder->ShouldSyncDecodeImages() &&
383
0
      geometry->ShouldInvalidateToSyncDecodeImages()) {
384
0
    bool snap;
385
0
    aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
386
0
  }
387
0
388
0
  nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
389
0
}
390
391
void nsDisplayButtonForeground::Paint(nsDisplayListBuilder* aBuilder,
392
                                      gfxContext* aCtx)
393
0
{
394
0
  nsPresContext *presContext = mFrame->PresContext();
395
0
  const nsStyleDisplay *disp = mFrame->StyleDisplay();
396
0
  if (!mFrame->IsThemed(disp) ||
397
0
      !presContext->GetTheme()->ThemeDrawsFocusForWidget(disp->mAppearance)) {
398
0
    nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
399
0
400
0
    // Draw the -moz-focus-inner border
401
0
    ImgDrawResult result =
402
0
      mBFR->PaintInnerFocusBorder(aBuilder, presContext, *aCtx, GetPaintRect(), r);
403
0
404
0
    nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
405
0
  }
406
0
}
407
408
bool
409
nsDisplayButtonForeground::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
410
                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
411
                                                   const StackingContextHelper& aSc,
412
                                                   mozilla::layers::WebRenderLayerManager* aManager,
413
                                                   nsDisplayListBuilder* aDisplayListBuilder)
414
0
{
415
0
  Maybe<nsCSSBorderRenderer> br;
416
0
  bool borderIsEmpty = false;
417
0
  nsPresContext *presContext = mFrame->PresContext();
418
0
  const nsStyleDisplay *disp = mFrame->StyleDisplay();
419
0
  if (!mFrame->IsThemed(disp) ||
420
0
      !presContext->GetTheme()->ThemeDrawsFocusForWidget(disp->mAppearance)) {
421
0
    nsRect r = nsRect(ToReferenceFrame(), mFrame->GetSize());
422
0
    br = mBFR->CreateInnerFocusBorderRenderer(aDisplayListBuilder, presContext, nullptr,
423
0
                                              GetPaintRect(), r, &borderIsEmpty);
424
0
  }
425
0
426
0
  if (!br) {
427
0
    return borderIsEmpty;
428
0
  }
429
0
430
0
  br->CreateWebRenderCommands(this, aBuilder, aResources, aSc);
431
0
  return true;
432
0
}
433
434
nsresult
435
nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
436
                                     nsDisplayList* aBackground,
437
                                     nsDisplayList* aForeground)
438
0
{
439
0
  if (mFrame->StyleEffects()->mBoxShadow) {
440
0
    aBackground->AppendToTop(
441
0
      MakeDisplayItem<nsDisplayButtonBoxShadowOuter>(aBuilder, this));
442
0
  }
443
0
444
0
  nsRect buttonRect = mFrame->GetRectRelativeToSelf();
445
0
446
0
  nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
447
0
    aBuilder, mFrame, buttonRect, aBackground);
448
0
449
0
  aBackground->AppendToTop(
450
0
    MakeDisplayItem<nsDisplayButtonBorder>(aBuilder, this));
451
0
452
0
  // Only display focus rings if we actually have them. Since at most one
453
0
  // button would normally display a focus ring, most buttons won't have them.
454
0
  if (mInnerFocusStyle && mInnerFocusStyle->StyleBorder()->HasBorder()) {
455
0
    aForeground->AppendToTop(
456
0
      MakeDisplayItem<nsDisplayButtonForeground>(aBuilder, this));
457
0
  }
458
0
  return NS_OK;
459
0
}
460
461
void
462
nsButtonFrameRenderer::GetButtonInnerFocusRect(const nsRect& aRect, nsRect& aResult)
463
0
{
464
0
  aResult = aRect;
465
0
  aResult.Deflate(mFrame->GetUsedBorderAndPadding());
466
0
467
0
  if (mInnerFocusStyle) {
468
0
    nsMargin innerFocusPadding(0,0,0,0);
469
0
    mInnerFocusStyle->StylePadding()->GetPadding(innerFocusPadding);
470
0
471
0
    nsMargin framePadding = mFrame->GetUsedPadding();
472
0
473
0
    innerFocusPadding.top = std::min(innerFocusPadding.top,
474
0
                                     framePadding.top);
475
0
    innerFocusPadding.right = std::min(innerFocusPadding.right,
476
0
                                       framePadding.right);
477
0
    innerFocusPadding.bottom = std::min(innerFocusPadding.bottom,
478
0
                                        framePadding.bottom);
479
0
    innerFocusPadding.left = std::min(innerFocusPadding.left,
480
0
                                      framePadding.left);
481
0
482
0
    aResult.Inflate(innerFocusPadding);
483
0
  }
484
0
}
485
486
ImgDrawResult
487
nsButtonFrameRenderer::PaintInnerFocusBorder(
488
  nsDisplayListBuilder* aBuilder,
489
  nsPresContext* aPresContext,
490
  gfxContext& aRenderingContext,
491
  const nsRect& aDirtyRect,
492
  const nsRect& aRect)
493
0
{
494
0
  // we draw the -moz-focus-inner border just inside the button's
495
0
  // normal border and padding, to match Windows themes.
496
0
497
0
  nsRect rect;
498
0
499
0
  PaintBorderFlags flags = aBuilder->ShouldSyncDecodeImages()
500
0
                         ? PaintBorderFlags::SYNC_DECODE_IMAGES
501
0
                         : PaintBorderFlags();
502
0
503
0
  ImgDrawResult result = ImgDrawResult::SUCCESS;
504
0
505
0
  if (mInnerFocusStyle) {
506
0
    GetButtonInnerFocusRect(aRect, rect);
507
0
508
0
    result &=
509
0
      nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
510
0
                                  aDirtyRect, rect, mInnerFocusStyle, flags);
511
0
  }
512
0
513
0
  return result;
514
0
}
515
516
Maybe<nsCSSBorderRenderer>
517
nsButtonFrameRenderer::CreateInnerFocusBorderRenderer(
518
  nsDisplayListBuilder* aBuilder,
519
  nsPresContext* aPresContext,
520
  gfxContext* aRenderingContext,
521
  const nsRect& aDirtyRect,
522
  const nsRect& aRect,
523
  bool* aBorderIsEmpty)
524
0
{
525
0
  if (mInnerFocusStyle) {
526
0
    nsRect rect;
527
0
    GetButtonInnerFocusRect(aRect, rect);
528
0
529
0
    gfx::DrawTarget* dt = aRenderingContext ? aRenderingContext->GetDrawTarget() : nullptr;
530
0
    return nsCSSRendering::CreateBorderRenderer(aPresContext,
531
0
                                                dt,
532
0
                                                mFrame,
533
0
                                                aDirtyRect,
534
0
                                                rect,
535
0
                                                mInnerFocusStyle,
536
0
                                                aBorderIsEmpty);
537
0
  }
538
0
539
0
  return Nothing();
540
0
}
541
542
ImgDrawResult
543
nsButtonFrameRenderer::PaintBorder(
544
  nsDisplayListBuilder* aBuilder,
545
  nsPresContext* aPresContext,
546
  gfxContext& aRenderingContext,
547
  const nsRect& aDirtyRect,
548
  const nsRect& aRect)
549
0
{
550
0
  // get the button rect this is inside the focus and outline rects
551
0
  nsRect buttonRect = aRect;
552
0
  ComputedStyle* context = mFrame->Style();
553
0
554
0
  PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
555
0
                               ? PaintBorderFlags::SYNC_DECODE_IMAGES
556
0
                               : PaintBorderFlags();
557
0
558
0
  nsCSSRendering::PaintBoxShadowInner(aPresContext, aRenderingContext,
559
0
                                      mFrame, buttonRect);
560
0
561
0
  ImgDrawResult result =
562
0
    nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, mFrame,
563
0
                                aDirtyRect, buttonRect, context, borderFlags);
564
0
565
0
  return result;
566
0
}
567
568
/**
569
 * Call this when styles change
570
 */
571
void
572
nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext)
573
0
{
574
0
  // get all the styles
575
0
  ComputedStyle* context = mFrame->Style();
576
0
  ServoStyleSet* styleSet = aPresContext->StyleSet();
577
0
578
0
  // get styles assigned to -moz-focus-inner (ie dotted border on Windows)
579
0
  mInnerFocusStyle =
580
0
    styleSet->ProbePseudoElementStyle(*mFrame->GetContent()->AsElement(),
581
0
                                      CSSPseudoElementType::mozFocusInner,
582
0
                                      context);
583
0
}
584
585
ComputedStyle*
586
nsButtonFrameRenderer::GetComputedStyle(int32_t aIndex) const
587
0
{
588
0
  switch (aIndex) {
589
0
  case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
590
0
    return mInnerFocusStyle;
591
0
  default:
592
0
    return nullptr;
593
0
  }
594
0
}
595
596
void
597
nsButtonFrameRenderer::SetComputedStyle(int32_t aIndex, ComputedStyle* aComputedStyle)
598
0
{
599
0
  switch (aIndex) {
600
0
  case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
601
0
    mInnerFocusStyle = aComputedStyle;
602
0
    break;
603
0
  }
604
0
}