summaryrefslogtreecommitdiffstats
path: root/gfx/src/nsITheme.h
blob: 48f563751fc7e94d0524a874e3001dab6efadc36 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

/* service providing platform-specific native rendering for widgets */

#ifndef nsITheme_h_
#define nsITheme_h_

#include "mozilla/AlreadyAddRefed.h"
#include "nsISupports.h"
#include "nsID.h"
#include "nscore.h"
#include "Units.h"

struct nsRect;
class gfxContext;
class nsAttrValue;
class nsPresContext;
class nsDeviceContext;
class nsIFrame;
class nsAtom;
class nsIWidget;

namespace mozilla {
class ComputedStyle;
enum class StyleAppearance : uint8_t;
enum class StyleScrollbarWidth : uint8_t;
namespace layers {
class StackingContextHelper;
class RenderRootStateManager;
}  // namespace layers
namespace widget {
class Theme;
}  // namespace widget
namespace wr {
class DisplayListBuilder;
class IpcResourceUpdateQueue;
}  // namespace wr
}  // namespace mozilla

// IID for the nsITheme interface
// {7329f760-08cb-450f-8225-dae729096dec}
#define NS_ITHEME_IID                                \
  {                                                  \
    0x7329f760, 0x08cb, 0x450f, {                    \
      0x82, 0x25, 0xda, 0xe7, 0x29, 0x09, 0x6d, 0xec \
    }                                                \
  }

/**
 * nsITheme is a service that provides platform-specific native
 * rendering for widgets.  In other words, it provides the necessary
 * operations to draw a rendering object (an nsIFrame) as a native
 * widget.
 *
 * All the methods on nsITheme take a rendering context or device
 * context, a frame (the rendering object), and a widget type (one of
 * the constants in nsThemeConstants.h).
 */
class nsITheme : public nsISupports {
 protected:
  using LayoutDeviceIntMargin = mozilla::LayoutDeviceIntMargin;
  using LayoutDeviceIntSize = mozilla::LayoutDeviceIntSize;
  using LayoutDeviceIntCoord = mozilla::LayoutDeviceIntCoord;
  using StyleAppearance = mozilla::StyleAppearance;
  using StyleScrollbarWidth = mozilla::StyleScrollbarWidth;
  using ComputedStyle = mozilla::ComputedStyle;

 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITHEME_IID)

  /**
   * Draw the actual theme background.
   * @param aContext the context to draw into
   * @param aFrame the frame for the widget that we're drawing
   * @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,
                                  DrawOverflow = DrawOverflow::Yes) = 0;

  /**
   * Create WebRender commands for the theme background.
   * @return true if the theme knows how to create WebRender commands for the
   *         given widget type, false if DrawWidgetBackground need sto be called
   *         instead.
   */
  virtual bool CreateWebRenderCommandsForWidget(
      mozilla::wr::DisplayListBuilder& aBuilder,
      mozilla::wr::IpcResourceUpdateQueue& aResources,
      const mozilla::layers::StackingContextHelper& aSc,
      mozilla::layers::RenderRootStateManager* aManager, nsIFrame* aFrame,
      StyleAppearance aWidgetType, const nsRect& aRect) {
    return false;
  }

  /**
   * Returns the minimum widths of a scrollbar for a given style, that is, the
   * minimum width for a vertical scrollbar, and the minimum height of a
   * horizontal scrollbar.
   */
  enum class Overlay { No, Yes };
  virtual LayoutDeviceIntCoord GetScrollbarSize(const nsPresContext*,
                                                StyleScrollbarWidth,
                                                Overlay) = 0;

  /**
   * Return the border for the widget, in device pixels.
   */
  [[nodiscard]] virtual LayoutDeviceIntMargin GetWidgetBorder(
      nsDeviceContext* aContext, nsIFrame* aFrame,
      StyleAppearance aWidgetType) = 0;

  /**
   * This method can return false to indicate that the CSS padding
   * value should be used.  Otherwise, it will fill in aResult with the
   * computed padding, in pixels, and return true.
   *
   * XXXldb This ought to be required to return true for non-containers
   * so that we don't let specified padding that has no effect change
   * the computed padding and potentially the size.
   */
  virtual bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame* aFrame,
                                StyleAppearance aWidgetType,
                                LayoutDeviceIntMargin* aResult) = 0;

  /**
   * On entry, *aResult is positioned at 0,0 and sized to the new size
   * of aFrame (aFrame->GetSize() may be stale and should not be used).
   * This method can return false to indicate that no special
   * overflow area is required by the native widget. Otherwise it will
   * fill in aResult with the desired overflow area, in appunits, relative
   * to the frame origin, and return true.
   *
   * This overflow area is used to determine what area needs to be
   * repainted when the widget changes.  However, it does not affect the
   * widget's size or what area is reachable by scrollbars.  (In other
   * words, in layout terms, it affects ink overflow but not
   * scrollable overflow.)
   */
  virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame,
                                 StyleAppearance aWidgetType,
                                 /*INOUT*/ nsRect* aOverflowRect) {
    return false;
  }

  /**
   * Get the preferred content-box size of a checkbox / radio button, in app
   * units.  Historically 9px.
   */
  virtual nscoord GetCheckboxRadioPrefSize() {
    return mozilla::CSSPixel::ToAppUnits(9);
  }

  /**
   * Get the minimum border-box size of a widget, in device pixels.
   */
  virtual mozilla::LayoutDeviceIntSize GetMinimumWidgetSize(
      nsPresContext* aPresContext, nsIFrame* aFrame,
      StyleAppearance aWidgetType) = 0;

  enum Transparency { eOpaque = 0, eTransparent, eUnknownTransparency };

  /**
   * Returns what we know about the transparency of the widget.
   */
  virtual Transparency GetWidgetTransparency(nsIFrame* aFrame,
                                             StyleAppearance aWidgetType) {
    return eUnknownTransparency;
  }

  /**
   * Sets |*aShouldRepaint| to indicate whether an attribute or content state
   * change should trigger a repaint.  Call with null |aAttribute| (and
   * null |aOldValue|) for content state changes.
   */
  NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, StyleAppearance aWidgetType,
                                nsAtom* aAttribute, bool* aShouldRepaint,
                                const nsAttrValue* aOldValue) = 0;

  NS_IMETHOD ThemeChanged() = 0;

  virtual bool WidgetAppearanceDependsOnWindowFocus(
      StyleAppearance aWidgetType) {
    return false;
  }

  /**
   * ThemeGeometryType values are used for describing themed nsIFrames in
   * calls to nsIWidget::UpdateThemeGeometries. We don't simply pass the
   * -moz-appearance value ("widget type") of the frame because the widget may
   * want to treat different frames with the same -moz-appearance differently
   * based on other properties of the frame. So we give the theme a first look
   * at the frame in nsITheme::ThemeGeometryTypeForWidget and pass the
   * returned ThemeGeometryType along to the widget.
   * Each theme backend defines the ThemeGeometryType values it needs in its
   * own nsITheme subclass. eThemeGeometryTypeUnknown is the only value that's
   * shared between backends.
   */
  typedef uint8_t ThemeGeometryType;
  enum { eThemeGeometryTypeUnknown = 0 };

  /**
   * Returns the theme geometry type that should be used in the ThemeGeometry
   * array that's passed to the widget using nsIWidget::UpdateThemeGeometries.
   * A return value of eThemeGeometryTypeUnknown means that this frame will
   * not be included in the ThemeGeometry array.
   */
  virtual ThemeGeometryType ThemeGeometryTypeForWidget(
      nsIFrame* aFrame, StyleAppearance aWidgetType) {
    return eThemeGeometryTypeUnknown;
  }

  /**
   * Can the nsITheme implementation handle this widget?
   */
  virtual bool ThemeSupportsWidget(nsPresContext* aPresContext,
                                   nsIFrame* aFrame,
                                   StyleAppearance aWidgetType) = 0;

  virtual bool WidgetIsContainer(StyleAppearance aWidgetType) = 0;

  /**
   * Does the nsITheme implementation draw its own focus ring for this widget?
   */
  virtual bool ThemeDrawsFocusForWidget(nsIFrame*, StyleAppearance) = 0;

  // Whether we want an inner focus ring for buttons and menulists.
  virtual bool ThemeWantsButtonInnerFocusRing() { return false; }

  /**
   * Should we insert a dropmarker inside of combobox button?
   */
  virtual bool ThemeNeedsComboboxDropmarker() = 0;

  virtual bool ThemeSupportsScrollbarButtons() = 0;
};

NS_DEFINE_STATIC_IID_ACCESSOR(nsITheme, NS_ITHEME_IID)

// Singleton accessor functions, these should never return null.
//
// Do not use directly, use nsPresContext::Theme instead.
extern already_AddRefed<nsITheme> do_GetNativeThemeDoNotUseDirectly();
extern already_AddRefed<nsITheme> do_GetBasicNativeThemeDoNotUseDirectly();
extern already_AddRefed<nsITheme> do_GetRDMThemeDoNotUseDirectly();

// Native theme creation function, these should never return null.
extern already_AddRefed<mozilla::widget::Theme>
do_CreateNativeThemeDoNotUseDirectly();

#endif