summaryrefslogtreecommitdiffstats
path: root/widget/gtk/nsNativeBasicThemeGTK.cpp
blob: cf32161c4010395e8a3da34fdd7d376cd1de023b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsNativeBasicThemeGTK.h"

#include "nsLayoutUtils.h"

using namespace mozilla;

static constexpr CSSCoord kGtkMinimumScrollbarSize = 12;
static constexpr CSSCoord kGtkMinimumThinScrollbarSize = 6;
static constexpr CSSCoord kGtkMinimumScrollbarThumbSize = 40;

already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly() {
  static mozilla::StaticRefPtr<nsITheme> gInstance;
  if (MOZ_UNLIKELY(!gInstance)) {
    gInstance = new nsNativeBasicThemeGTK();
    ClearOnShutdown(&gInstance);
  }
  return do_AddRef(gInstance);
}

nsITheme::Transparency nsNativeBasicThemeGTK::GetWidgetTransparency(
    nsIFrame* aFrame, StyleAppearance aAppearance) {
  switch (aAppearance) {
    case StyleAppearance::ScrollbarVertical:
    case StyleAppearance::ScrollbarHorizontal:
      // Make scrollbar tracks opaque on the window's scroll frame to prevent
      // leaf layers from overlapping. See bug 1179780.
      return IsRootScrollbar(aFrame) ? eOpaque : eTransparent;
    default:
      return nsNativeBasicTheme::GetWidgetTransparency(aFrame, aAppearance);
  }
}

NS_IMETHODIMP
nsNativeBasicThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
                                            nsIFrame* aFrame,
                                            StyleAppearance aAppearance,
                                            LayoutDeviceIntSize* aResult,
                                            bool* aIsOverridable) {
  DPIRatio dpiRatio = GetDPIRatio(aFrame);

  switch (aAppearance) {
    case StyleAppearance::ScrollbarVertical:
    case StyleAppearance::ScrollbarHorizontal:
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
    case StyleAppearance::ScrollbarthumbVertical:
    case StyleAppearance::ScrollbarthumbHorizontal:
    case StyleAppearance::ScrollbartrackHorizontal:
    case StyleAppearance::ScrollbartrackVertical:
    case StyleAppearance::Scrollcorner: {
      ComputedStyle* style = nsLayoutUtils::StyleForScrollbar(aFrame);
      if (style->StyleUIReset()->mScrollbarWidth == StyleScrollbarWidth::Thin) {
        aResult->SizeTo(kGtkMinimumThinScrollbarSize * dpiRatio,
                        kGtkMinimumThinScrollbarSize * dpiRatio);
      } else {
        aResult->SizeTo(kGtkMinimumScrollbarSize * dpiRatio,
                        kGtkMinimumScrollbarSize * dpiRatio);
      }
      break;
    }
    default:
      return nsNativeBasicTheme::GetMinimumWidgetSize(
          aPresContext, aFrame, aAppearance, aResult, aIsOverridable);
  }

  switch (aAppearance) {
    case StyleAppearance::ScrollbarthumbHorizontal:
      aResult->width = kGtkMinimumScrollbarThumbSize * dpiRatio;
      break;
    case StyleAppearance::ScrollbarthumbVertical:
      aResult->height = kGtkMinimumScrollbarThumbSize * dpiRatio;
      break;
    default:
      break;
  }

  *aIsOverridable = true;
  return NS_OK;
}

void nsNativeBasicThemeGTK::PaintScrollbarThumb(
    DrawTarget* aDrawTarget, const LayoutDeviceRect& aRect, bool aHorizontal,
    nsIFrame* aFrame, const ComputedStyle& aStyle,
    const EventStates& aElementState, const EventStates& aDocumentState,
    DPIRatio aDpiRatio) {
  sRGBColor thumbColor =
      ComputeScrollbarThumbColor(aFrame, aStyle, aElementState, aDocumentState);
  LayoutDeviceRect thumbRect(aRect);
  thumbRect.Deflate(floorf((aHorizontal ? aRect.height : aRect.width) / 4.0f));
  LayoutDeviceCoord radius =
      (aHorizontal ? thumbRect.height : thumbRect.width) / 2.0f;
  PaintRoundedRectWithRadius(aDrawTarget, thumbRect, thumbColor, sRGBColor(), 0,
                             radius / aDpiRatio, aDpiRatio);
}

void nsNativeBasicThemeGTK::PaintScrollbar(DrawTarget* aDrawTarget,
                                           const LayoutDeviceRect& aRect,
                                           bool aHorizontal, nsIFrame* aFrame,
                                           const ComputedStyle& aStyle,
                                           const EventStates& aDocumentState,
                                           DPIRatio aDpiRatio, bool aIsRoot) {
  auto [trackColor, borderColor] =
      ComputeScrollbarColors(aFrame, aStyle, aDocumentState, aIsRoot);
  Unused << borderColor;
  aDrawTarget->FillRect(aRect.ToUnknownRect(),
                        gfx::ColorPattern(ToDeviceColor(trackColor)));
}

void nsNativeBasicThemeGTK::PaintScrollCorner(
    DrawTarget* aDrawTarget, const LayoutDeviceRect& aRect, nsIFrame* aFrame,
    const ComputedStyle& aStyle, const EventStates& aDocumentState,
    DPIRatio aDpiRatio, bool aIsRoot) {
  auto [trackColor, borderColor] =
      ComputeScrollbarColors(aFrame, aStyle, aDocumentState, aIsRoot);
  Unused << borderColor;
  aDrawTarget->FillRect(aRect.ToUnknownRect(),
                        gfx::ColorPattern(ToDeviceColor(trackColor)));
}