1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsNativeThemeCocoa_h_ 7 #define nsNativeThemeCocoa_h_ 8 9 #import <Carbon/Carbon.h> 10 #import <Cocoa/Cocoa.h> 11 12 #include "mozilla/Variant.h" 13 14 #include "nsITheme.h" 15 #include "ThemeCocoa.h" 16 17 @class MOZCellDrawWindow; 18 @class MOZCellDrawView; 19 @class MOZSearchFieldCell; 20 @class NSProgressBarCell; 21 class nsDeviceContext; 22 struct SegmentedControlRenderSettings; 23 24 namespace mozilla { 25 class EventStates; 26 namespace gfx { 27 class DrawTarget; 28 } // namespace gfx 29 } // namespace mozilla 30 31 class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa { 32 using ThemeCocoa = mozilla::widget::ThemeCocoa; 33 34 public: 35 enum class MenuIcon : uint8_t { 36 eCheckmark, 37 eMenuArrow, 38 eMenuDownScrollArrow, 39 eMenuUpScrollArrow 40 }; 41 42 enum class CheckboxOrRadioState : uint8_t { eOff, eOn, eIndeterminate }; 43 44 enum class ButtonType : uint8_t { 45 eRegularPushButton, 46 eDefaultPushButton, 47 eSquareBezelPushButton, 48 eArrowButton, 49 eHelpButton, 50 eTreeTwistyPointingRight, 51 eTreeTwistyPointingDown, 52 eDisclosureButtonClosed, 53 eDisclosureButtonOpen 54 }; 55 56 enum class SpinButton : uint8_t { eUp, eDown }; 57 58 enum class SegmentType : uint8_t { eToolbarButton, eTab }; 59 60 enum class OptimumState : uint8_t { eOptimum, eSubOptimum, eSubSubOptimum }; 61 62 struct ControlParams { ControlParamsControlParams63 ControlParams() 64 : disabled(false), insideActiveWindow(false), pressed(false), focused(false), rtl(false) {} 65 66 bool disabled : 1; 67 bool insideActiveWindow : 1; 68 bool pressed : 1; 69 bool focused : 1; 70 bool rtl : 1; 71 }; 72 73 struct MenuIconParams { 74 MenuIcon icon = MenuIcon::eCheckmark; 75 bool disabled = false; 76 bool insideActiveMenuItem = false; 77 bool centerHorizontally = false; 78 bool rtl = false; 79 }; 80 81 struct MenuItemParams { 82 bool checked = false; 83 bool disabled = false; 84 bool selected = false; 85 bool rtl = false; 86 }; 87 88 struct CheckboxOrRadioParams { 89 ControlParams controlParams; 90 CheckboxOrRadioState state = CheckboxOrRadioState::eOff; 91 float verticalAlignFactor = 0.5f; 92 }; 93 94 struct ButtonParams { 95 ControlParams controlParams; 96 ButtonType button = ButtonType::eRegularPushButton; 97 }; 98 99 struct DropdownParams { 100 ControlParams controlParams; 101 bool pullsDown = false; 102 bool editable = false; 103 }; 104 105 struct SpinButtonParams { 106 mozilla::Maybe<SpinButton> pressedButton; 107 bool disabled = false; 108 bool insideActiveWindow = false; 109 }; 110 111 struct SegmentParams { 112 SegmentType segmentType = SegmentType::eToolbarButton; 113 bool insideActiveWindow = false; 114 bool pressed = false; 115 bool selected = false; 116 bool focused = false; 117 bool atLeftEnd = false; 118 bool atRightEnd = false; 119 bool drawsLeftSeparator = false; 120 bool drawsRightSeparator = false; 121 bool rtl = false; 122 }; 123 124 struct TextFieldParams { 125 float verticalAlignFactor = 0.5f; 126 bool insideToolbar = false; 127 bool disabled = false; 128 bool focused = false; 129 bool rtl = false; 130 }; 131 132 struct ProgressParams { 133 double value = 0.0; 134 double max = 0.0; 135 float verticalAlignFactor = 0.5f; 136 bool insideActiveWindow = false; 137 bool indeterminate = false; 138 bool horizontal = false; 139 bool rtl = false; 140 }; 141 142 struct MeterParams { 143 double value = 0; 144 double min = 0; 145 double max = 0; 146 OptimumState optimumState = OptimumState::eOptimum; 147 float verticalAlignFactor = 0.5f; 148 bool horizontal = true; 149 bool rtl = false; 150 }; 151 152 struct TreeHeaderCellParams { 153 ControlParams controlParams; 154 TreeSortDirection sortDirection = eTreeSortDirection_Natural; 155 bool lastTreeHeaderCell = false; 156 }; 157 158 struct ScaleParams { 159 int32_t value = 0; 160 int32_t min = 0; 161 int32_t max = 0; 162 bool insideActiveWindow = false; 163 bool disabled = false; 164 bool focused = false; 165 bool horizontal = true; 166 bool reverse = false; 167 }; 168 169 enum Widget : uint8_t { 170 eColorFill, // mozilla::gfx::sRGBColor 171 eMenuIcon, // MenuIconParams 172 eMenuItem, // MenuItemParams 173 eMenuSeparator, // MenuItemParams 174 eCheckbox, // CheckboxOrRadioParams 175 eRadio, // CheckboxOrRadioParams 176 eButton, // ButtonParams 177 eDropdown, // DropdownParams 178 eFocusOutline, 179 eSpinButtons, // SpinButtonParams 180 eSpinButtonUp, // SpinButtonParams 181 eSpinButtonDown, // SpinButtonParams 182 eSegment, // SegmentParams 183 eSeparator, 184 eToolbar, // bool 185 eStatusBar, // bool 186 eGroupBox, 187 eTextField, // TextFieldParams 188 eSearchField, // TextFieldParams 189 eProgressBar, // ProgressParams 190 eMeter, // MeterParams 191 eTreeHeaderCell, // TreeHeaderCellParams 192 eScale, // ScaleParams 193 eMultilineTextField, // bool 194 eListBox, 195 eActiveSourceListSelection, // bool 196 eInactiveSourceListSelection, // bool 197 eTabPanel, 198 eResizer 199 }; 200 201 struct WidgetInfo { ColorFillWidgetInfo202 static WidgetInfo ColorFill(const mozilla::gfx::sRGBColor& aParams) { 203 return WidgetInfo(Widget::eColorFill, aParams); 204 } MenuIconWidgetInfo205 static WidgetInfo MenuIcon(const MenuIconParams& aParams) { 206 return WidgetInfo(Widget::eMenuIcon, aParams); 207 } MenuItemWidgetInfo208 static WidgetInfo MenuItem(const MenuItemParams& aParams) { 209 return WidgetInfo(Widget::eMenuItem, aParams); 210 } MenuSeparatorWidgetInfo211 static WidgetInfo MenuSeparator(const MenuItemParams& aParams) { 212 return WidgetInfo(Widget::eMenuSeparator, aParams); 213 } CheckboxWidgetInfo214 static WidgetInfo Checkbox(const CheckboxOrRadioParams& aParams) { 215 return WidgetInfo(Widget::eCheckbox, aParams); 216 } RadioWidgetInfo217 static WidgetInfo Radio(const CheckboxOrRadioParams& aParams) { 218 return WidgetInfo(Widget::eRadio, aParams); 219 } ButtonWidgetInfo220 static WidgetInfo Button(const ButtonParams& aParams) { 221 return WidgetInfo(Widget::eButton, aParams); 222 } DropdownWidgetInfo223 static WidgetInfo Dropdown(const DropdownParams& aParams) { 224 return WidgetInfo(Widget::eDropdown, aParams); 225 } FocusOutlineWidgetInfo226 static WidgetInfo FocusOutline() { return WidgetInfo(Widget::eFocusOutline, false); } SpinButtonsWidgetInfo227 static WidgetInfo SpinButtons(const SpinButtonParams& aParams) { 228 return WidgetInfo(Widget::eSpinButtons, aParams); 229 } SpinButtonUpWidgetInfo230 static WidgetInfo SpinButtonUp(const SpinButtonParams& aParams) { 231 return WidgetInfo(Widget::eSpinButtonUp, aParams); 232 } SpinButtonDownWidgetInfo233 static WidgetInfo SpinButtonDown(const SpinButtonParams& aParams) { 234 return WidgetInfo(Widget::eSpinButtonDown, aParams); 235 } SegmentWidgetInfo236 static WidgetInfo Segment(const SegmentParams& aParams) { 237 return WidgetInfo(Widget::eSegment, aParams); 238 } SeparatorWidgetInfo239 static WidgetInfo Separator() { return WidgetInfo(Widget::eSeparator, false); } ToolbarWidgetInfo240 static WidgetInfo Toolbar(bool aParams) { return WidgetInfo(Widget::eToolbar, aParams); } StatusBarWidgetInfo241 static WidgetInfo StatusBar(bool aParams) { return WidgetInfo(Widget::eStatusBar, aParams); } GroupBoxWidgetInfo242 static WidgetInfo GroupBox() { return WidgetInfo(Widget::eGroupBox, false); } TextFieldWidgetInfo243 static WidgetInfo TextField(const TextFieldParams& aParams) { 244 return WidgetInfo(Widget::eTextField, aParams); 245 } SearchFieldWidgetInfo246 static WidgetInfo SearchField(const TextFieldParams& aParams) { 247 return WidgetInfo(Widget::eSearchField, aParams); 248 } ProgressBarWidgetInfo249 static WidgetInfo ProgressBar(const ProgressParams& aParams) { 250 return WidgetInfo(Widget::eProgressBar, aParams); 251 } MeterWidgetInfo252 static WidgetInfo Meter(const MeterParams& aParams) { 253 return WidgetInfo(Widget::eMeter, aParams); 254 } TreeHeaderCellWidgetInfo255 static WidgetInfo TreeHeaderCell(const TreeHeaderCellParams& aParams) { 256 return WidgetInfo(Widget::eTreeHeaderCell, aParams); 257 } ScaleWidgetInfo258 static WidgetInfo Scale(const ScaleParams& aParams) { 259 return WidgetInfo(Widget::eScale, aParams); 260 } MultilineTextFieldWidgetInfo261 static WidgetInfo MultilineTextField(bool aParams) { 262 return WidgetInfo(Widget::eMultilineTextField, aParams); 263 } ListBoxWidgetInfo264 static WidgetInfo ListBox() { return WidgetInfo(Widget::eListBox, false); } ActiveSourceListSelectionWidgetInfo265 static WidgetInfo ActiveSourceListSelection(bool aParams) { 266 return WidgetInfo(Widget::eActiveSourceListSelection, aParams); 267 } InactiveSourceListSelectionWidgetInfo268 static WidgetInfo InactiveSourceListSelection(bool aParams) { 269 return WidgetInfo(Widget::eInactiveSourceListSelection, aParams); 270 } TabPanelWidgetInfo271 static WidgetInfo TabPanel(bool aParams) { return WidgetInfo(Widget::eTabPanel, aParams); } ResizerWidgetInfo272 static WidgetInfo Resizer(bool aParams) { return WidgetInfo(Widget::eResizer, aParams); } 273 274 template <typename T> ParamsWidgetInfo275 T Params() const { 276 MOZ_RELEASE_ASSERT(mVariant.is<T>()); 277 return mVariant.as<T>(); 278 } 279 WidgetWidgetInfo280 enum Widget Widget() const { return mWidget; } 281 282 private: 283 template <typename T> WidgetInfoWidgetInfo284 WidgetInfo(enum Widget aWidget, const T& aParams) : mVariant(aParams), mWidget(aWidget) {} 285 286 mozilla::Variant<mozilla::gfx::sRGBColor, MenuIconParams, MenuItemParams, CheckboxOrRadioParams, 287 ButtonParams, DropdownParams, SpinButtonParams, SegmentParams, TextFieldParams, 288 ProgressParams, MeterParams, TreeHeaderCellParams, ScaleParams, bool> 289 mVariant; 290 291 enum Widget mWidget; 292 }; 293 294 explicit nsNativeThemeCocoa(); 295 296 NS_DECL_ISUPPORTS_INHERITED 297 298 // The nsITheme interface. 299 NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame, 300 StyleAppearance aAppearance, const nsRect& aRect, 301 const nsRect& aDirtyRect, DrawOverflow) override; 302 bool CreateWebRenderCommandsForWidget(mozilla::wr::DisplayListBuilder& aBuilder, 303 mozilla::wr::IpcResourceUpdateQueue& aResources, 304 const mozilla::layers::StackingContextHelper& aSc, 305 mozilla::layers::RenderRootStateManager* aManager, 306 nsIFrame* aFrame, StyleAppearance aAppearance, 307 const nsRect& aRect) override; 308 [[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, 309 StyleAppearance aAppearance) override; 310 311 bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame* aFrame, StyleAppearance aAppearance, 312 LayoutDeviceIntMargin* aResult) override; 313 314 virtual bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame* aFrame, 315 StyleAppearance aAppearance, nsRect* aOverflowRect) override; 316 317 NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aFrame, 318 StyleAppearance aAppearance, 319 mozilla::LayoutDeviceIntSize* aResult, 320 bool* aIsOverridable) override; 321 NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, StyleAppearance aAppearance, nsAtom* aAttribute, 322 bool* aShouldRepaint, const nsAttrValue* aOldValue) override; 323 NS_IMETHOD ThemeChanged() override; 324 bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, 325 StyleAppearance aAppearance) override; 326 bool WidgetIsContainer(StyleAppearance aAppearance) override; 327 bool ThemeDrawsFocusForWidget(nsIFrame*, StyleAppearance) override; 328 bool ThemeNeedsComboboxDropmarker() override; 329 virtual bool WidgetAppearanceDependsOnWindowFocus(StyleAppearance aAppearance) override; 330 virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame, 331 StyleAppearance aAppearance) override; 332 virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, 333 StyleAppearance aAppearance) override; 334 mozilla::Maybe<WidgetInfo> ComputeWidgetInfo(nsIFrame* aFrame, StyleAppearance aAppearance, 335 const nsRect& aRect); 336 void DrawProgress(CGContextRef context, const HIRect& inBoxRect, const ProgressParams& aParams); 337 338 protected: 339 virtual ~nsNativeThemeCocoa(); 340 341 LayoutDeviceIntMargin DirectionAwareMargin(const LayoutDeviceIntMargin& aMargin, 342 nsIFrame* aFrame); 343 nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter); 344 ControlParams ComputeControlParams(nsIFrame* aFrame, mozilla::EventStates aEventState); 345 MenuIconParams ComputeMenuIconParams(nsIFrame* aParams, mozilla::EventStates aEventState, 346 MenuIcon aIcon); 347 MenuItemParams ComputeMenuItemParams(nsIFrame* aFrame, mozilla::EventStates aEventState, 348 bool aIsChecked); 349 SegmentParams ComputeSegmentParams(nsIFrame* aFrame, mozilla::EventStates aEventState, 350 SegmentType aSegmentType); 351 TextFieldParams ComputeTextFieldParams(nsIFrame* aFrame, mozilla::EventStates aEventState); 352 ProgressParams ComputeProgressParams(nsIFrame* aFrame, mozilla::EventStates aEventState, 353 bool aIsHorizontal); 354 MeterParams ComputeMeterParams(nsIFrame* aFrame); 355 TreeHeaderCellParams ComputeTreeHeaderCellParams(nsIFrame* aFrame, 356 mozilla::EventStates aEventState); 357 mozilla::Maybe<ScaleParams> ComputeHTMLScaleParams(nsIFrame* aFrame, 358 mozilla::EventStates aEventState); 359 360 // HITheme drawing routines 361 void DrawMeter(CGContextRef context, const HIRect& inBoxRect, const MeterParams& aParams); 362 void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, const SegmentParams& aParams); 363 void DrawSegmentBackground(CGContextRef cgContext, const HIRect& inBoxRect, 364 const SegmentParams& aParams); 365 void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, bool aIsInsideActiveWindow); 366 void DrawScale(CGContextRef context, const HIRect& inBoxRect, const ScaleParams& aParams); 367 void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, const HIRect& inBoxRect, 368 const CheckboxOrRadioParams& aParams); 369 void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, 370 const TextFieldParams& aParams); 371 void DrawTextField(CGContextRef cgContext, const HIRect& inBoxRect, 372 const TextFieldParams& aParams); 373 void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, ButtonType aButtonType, 374 ControlParams aControlParams); 375 void DrawSquareBezelPushButton(CGContextRef cgContext, const HIRect& inBoxRect, 376 ControlParams aControlParams); 377 void DrawHelpButton(CGContextRef cgContext, const HIRect& inBoxRect, 378 ControlParams aControlParams); 379 void DrawDisclosureButton(CGContextRef cgContext, const HIRect& inBoxRect, 380 ControlParams aControlParams, NSCellStateValue aState); 381 NSString* GetMenuIconName(const MenuIconParams& aParams); 382 NSSize GetMenuIconSize(MenuIcon aIcon); 383 void DrawMenuIcon(CGContextRef cgContext, const CGRect& aRect, const MenuIconParams& aParams); 384 void DrawMenuItem(CGContextRef cgContext, const CGRect& inBoxRect, const MenuItemParams& aParams); 385 void DrawMenuSeparator(CGContextRef cgContext, const CGRect& inBoxRect, 386 const MenuItemParams& aParams); 387 void DrawHIThemeButton(CGContextRef cgContext, const HIRect& aRect, ThemeButtonKind aKind, 388 ThemeButtonValue aValue, ThemeDrawState aState, 389 ThemeButtonAdornment aAdornment, const ControlParams& aParams); 390 void DrawButton(CGContextRef context, const HIRect& inBoxRect, const ButtonParams& aParams); 391 void DrawTreeHeaderCell(CGContextRef context, const HIRect& inBoxRect, 392 const TreeHeaderCellParams& aParams); 393 void DrawFocusOutline(CGContextRef cgContext, const HIRect& inBoxRect); 394 void DrawDropdown(CGContextRef context, const HIRect& inBoxRect, const DropdownParams& aParams); 395 HIThemeButtonDrawInfo SpinButtonDrawInfo(ThemeButtonKind aKind, const SpinButtonParams& aParams); 396 void DrawSpinButtons(CGContextRef context, const HIRect& inBoxRect, 397 const SpinButtonParams& aParams); 398 void DrawSpinButton(CGContextRef context, const HIRect& inBoxRect, SpinButton aDrawnButton, 399 const SpinButtonParams& aParams); 400 void DrawToolbar(CGContextRef cgContext, const CGRect& inBoxRect, bool aIsMain); 401 void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, bool aIsMain); 402 void DrawResizer(CGContextRef cgContext, const HIRect& aRect, bool aIsRTL); 403 void DrawMultilineTextField(CGContextRef cgContext, const CGRect& inBoxRect, bool aIsFocused); 404 void DrawSourceListSelection(CGContextRef aContext, const CGRect& aRect, bool aWindowIsActive, 405 bool aSelectionIsActive); 406 407 void RenderWidget(const WidgetInfo& aWidgetInfo, mozilla::ColorScheme, 408 mozilla::gfx::DrawTarget& aDrawTarget, const mozilla::gfx::Rect& aWidgetRect, 409 const mozilla::gfx::Rect& aDirtyRect, float aScale); 410 411 private: 412 NSButtonCell* mDisclosureButtonCell; 413 NSButtonCell* mHelpButtonCell; 414 NSButtonCell* mPushButtonCell; 415 NSButtonCell* mRadioButtonCell; 416 NSButtonCell* mCheckboxCell; 417 NSTextFieldCell* mTextFieldCell; 418 MOZSearchFieldCell* mSearchFieldCell; 419 NSPopUpButtonCell* mDropdownCell; 420 NSComboBoxCell* mComboBoxCell; 421 NSProgressBarCell* mProgressBarCell; 422 NSLevelIndicatorCell* mMeterBarCell; 423 NSTableHeaderCell* mTreeHeaderCell; 424 MOZCellDrawWindow* mCellDrawWindow = nil; 425 MOZCellDrawView* mCellDrawView; 426 }; 427 428 #endif // nsNativeThemeCocoa_h_ 429