/* -*- Mode: C++; tab-width: 2; 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/. */ #ifndef nsNativeThemeCocoa_h_ #define nsNativeThemeCocoa_h_ #import #import #include "mozilla/Variant.h" #include "nsITheme.h" #include "ThemeCocoa.h" #include "mozilla/dom/RustTypes.h" @class MOZCellDrawWindow; @class MOZCellDrawView; @class MOZSearchFieldCell; @class NSProgressBarCell; class nsDeviceContext; struct SegmentedControlRenderSettings; namespace mozilla { namespace gfx { class DrawTarget; } // namespace gfx } // namespace mozilla class nsNativeThemeCocoa : public mozilla::widget::ThemeCocoa { using ThemeCocoa = mozilla::widget::ThemeCocoa; public: enum class CheckboxOrRadioState : uint8_t { eOff, eOn, eIndeterminate }; enum class ButtonType : uint8_t { eRegularPushButton, eDefaultPushButton, eSquareBezelPushButton, eArrowButton, eHelpButton, eDisclosureButtonClosed, eDisclosureButtonOpen }; enum class SpinButton : uint8_t { eUp, eDown }; enum class SegmentType : uint8_t { eToolbarButton, eTab }; enum class OptimumState : uint8_t { eOptimum, eSubOptimum, eSubSubOptimum }; struct ControlParams { ControlParams() : disabled(false), insideActiveWindow(false), pressed(false), focused(false), rtl(false) {} bool disabled : 1; bool insideActiveWindow : 1; bool pressed : 1; bool focused : 1; bool rtl : 1; }; struct CheckboxOrRadioParams { ControlParams controlParams; CheckboxOrRadioState state = CheckboxOrRadioState::eOff; float verticalAlignFactor = 0.5f; }; struct ButtonParams { ControlParams controlParams; ButtonType button = ButtonType::eRegularPushButton; }; struct DropdownParams { ControlParams controlParams; bool pullsDown = false; bool editable = false; }; struct SpinButtonParams { mozilla::Maybe pressedButton; bool disabled = false; bool insideActiveWindow = false; }; struct SegmentParams { SegmentType segmentType = SegmentType::eToolbarButton; bool insideActiveWindow = false; bool pressed = false; bool selected = false; bool focused = false; bool atLeftEnd = false; bool atRightEnd = false; bool drawsLeftSeparator = false; bool drawsRightSeparator = false; bool rtl = false; }; struct TextFieldParams { float verticalAlignFactor = 0.5f; bool insideToolbar = false; bool disabled = false; bool focused = false; bool rtl = false; }; struct ProgressParams { double value = 0.0; double max = 0.0; float verticalAlignFactor = 0.5f; bool insideActiveWindow = false; bool indeterminate = false; bool horizontal = false; bool rtl = false; }; struct MeterParams { double value = 0; double min = 0; double max = 0; OptimumState optimumState = OptimumState::eOptimum; float verticalAlignFactor = 0.5f; bool horizontal = true; bool rtl = false; }; struct ScaleParams { int32_t value = 0; int32_t min = 0; int32_t max = 0; bool insideActiveWindow = false; bool disabled = false; bool focused = false; bool horizontal = true; bool reverse = false; }; enum Widget : uint8_t { eColorFill, // mozilla::gfx::sRGBColor eCheckbox, // CheckboxOrRadioParams eRadio, // CheckboxOrRadioParams eButton, // ButtonParams eDropdown, // DropdownParams eSpinButtons, // SpinButtonParams eSpinButtonUp, // SpinButtonParams eSpinButtonDown, // SpinButtonParams eSegment, // SegmentParams eSeparator, eStatusBar, // bool eGroupBox, eTextField, // TextFieldParams eSearchField, // TextFieldParams eProgressBar, // ProgressParams eMeter, // MeterParams eScale, // ScaleParams eMultilineTextField, // bool eListBox, eTabPanel, }; struct WidgetInfo { static WidgetInfo ColorFill(const mozilla::gfx::sRGBColor& aParams) { return WidgetInfo(Widget::eColorFill, aParams); } static WidgetInfo Checkbox(const CheckboxOrRadioParams& aParams) { return WidgetInfo(Widget::eCheckbox, aParams); } static WidgetInfo Radio(const CheckboxOrRadioParams& aParams) { return WidgetInfo(Widget::eRadio, aParams); } static WidgetInfo Button(const ButtonParams& aParams) { return WidgetInfo(Widget::eButton, aParams); } static WidgetInfo Dropdown(const DropdownParams& aParams) { return WidgetInfo(Widget::eDropdown, aParams); } static WidgetInfo SpinButtons(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtons, aParams); } static WidgetInfo SpinButtonUp(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtonUp, aParams); } static WidgetInfo SpinButtonDown(const SpinButtonParams& aParams) { return WidgetInfo(Widget::eSpinButtonDown, aParams); } static WidgetInfo Segment(const SegmentParams& aParams) { return WidgetInfo(Widget::eSegment, aParams); } static WidgetInfo Separator() { return WidgetInfo(Widget::eSeparator, false); } static WidgetInfo StatusBar(bool aParams) { return WidgetInfo(Widget::eStatusBar, aParams); } static WidgetInfo GroupBox() { return WidgetInfo(Widget::eGroupBox, false); } static WidgetInfo TextField(const TextFieldParams& aParams) { return WidgetInfo(Widget::eTextField, aParams); } static WidgetInfo SearchField(const TextFieldParams& aParams) { return WidgetInfo(Widget::eSearchField, aParams); } static WidgetInfo ProgressBar(const ProgressParams& aParams) { return WidgetInfo(Widget::eProgressBar, aParams); } static WidgetInfo Meter(const MeterParams& aParams) { return WidgetInfo(Widget::eMeter, aParams); } static WidgetInfo Scale(const ScaleParams& aParams) { return WidgetInfo(Widget::eScale, aParams); } static WidgetInfo MultilineTextField(bool aParams) { return WidgetInfo(Widget::eMultilineTextField, aParams); } static WidgetInfo ListBox() { return WidgetInfo(Widget::eListBox, false); } static WidgetInfo TabPanel(bool aParams) { return WidgetInfo(Widget::eTabPanel, aParams); } template T Params() const { MOZ_RELEASE_ASSERT(mVariant.is()); return mVariant.as(); } enum Widget Widget() const { return mWidget; } private: template WidgetInfo(enum Widget aWidget, const T& aParams) : mVariant(aParams), mWidget(aWidget) {} mozilla::Variant mVariant; enum Widget mWidget; }; explicit nsNativeThemeCocoa(); NS_DECL_ISUPPORTS_INHERITED // The nsITheme interface. NS_IMETHOD DrawWidgetBackground(gfxContext* aContext, nsIFrame*, StyleAppearance, const nsRect& aRect, const nsRect& aDirtyRect, DrawOverflow) override; bool CreateWebRenderCommandsForWidget( mozilla::wr::DisplayListBuilder& aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, const mozilla::layers::StackingContextHelper& aSc, mozilla::layers::RenderRootStateManager* aManager, nsIFrame*, StyleAppearance, const nsRect& aRect) override; [[nodiscard]] LayoutDeviceIntMargin GetWidgetBorder(nsDeviceContext* aContext, nsIFrame*, StyleAppearance) override; bool GetWidgetPadding(nsDeviceContext* aContext, nsIFrame*, StyleAppearance, LayoutDeviceIntMargin* aResult) override; bool GetWidgetOverflow(nsDeviceContext* aContext, nsIFrame*, StyleAppearance, nsRect* aOverflowRect) override; LayoutDeviceIntSize GetMinimumWidgetSize(nsPresContext*, nsIFrame*, StyleAppearance) override; bool WidgetAttributeChangeRequiresRepaint(StyleAppearance, nsAtom* aAttribute) override; NS_IMETHOD ThemeChanged() override; bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame*, StyleAppearance) override; bool WidgetIsContainer(StyleAppearance) override; bool ThemeDrawsFocusForWidget(nsIFrame*, StyleAppearance) override; bool ThemeNeedsComboboxDropmarker() override; bool WidgetAppearanceDependsOnWindowFocus(StyleAppearance) override; ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame*, StyleAppearance) override; Transparency GetWidgetTransparency(nsIFrame*, StyleAppearance) override; mozilla::Maybe ComputeWidgetInfo(nsIFrame*, StyleAppearance, const nsRect& aRect); void DrawProgress(CGContextRef context, const HIRect& inBoxRect, const ProgressParams& aParams); protected: virtual ~nsNativeThemeCocoa(); LayoutDeviceIntMargin DirectionAwareMargin(const LayoutDeviceIntMargin&, nsIFrame*); nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter); ControlParams ComputeControlParams(nsIFrame*, mozilla::dom::ElementState); SegmentParams ComputeSegmentParams(nsIFrame*, mozilla::dom::ElementState, SegmentType); TextFieldParams ComputeTextFieldParams(nsIFrame*, mozilla::dom::ElementState); ProgressParams ComputeProgressParams(nsIFrame*, mozilla::dom::ElementState, bool aIsHorizontal); MeterParams ComputeMeterParams(nsIFrame*); mozilla::Maybe ComputeHTMLScaleParams( nsIFrame*, mozilla::dom::ElementState); // HITheme drawing routines void DrawMeter(CGContextRef context, const HIRect& inBoxRect, const MeterParams& aParams); void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect, const SegmentParams& aParams); void DrawSegmentBackground(CGContextRef cgContext, const HIRect& inBoxRect, const SegmentParams& aParams); void DrawTabPanel(CGContextRef context, const HIRect& inBoxRect, bool aIsInsideActiveWindow); void DrawScale(CGContextRef context, const HIRect& inBoxRect, const ScaleParams& aParams); void DrawCheckboxOrRadio(CGContextRef cgContext, bool inCheckbox, const HIRect& inBoxRect, const CheckboxOrRadioParams& aParams); void DrawSearchField(CGContextRef cgContext, const HIRect& inBoxRect, const TextFieldParams& aParams); void DrawTextField(CGContextRef cgContext, const HIRect& inBoxRect, const TextFieldParams& aParams); void DrawPushButton(CGContextRef cgContext, const HIRect& inBoxRect, ButtonType aButtonType, ControlParams aControlParams); void DrawSquareBezelPushButton(CGContextRef cgContext, const HIRect& inBoxRect, ControlParams aControlParams); void DrawHelpButton(CGContextRef cgContext, const HIRect& inBoxRect, ControlParams aControlParams); void DrawDisclosureButton(CGContextRef cgContext, const HIRect& inBoxRect, ControlParams aControlParams, NSControlStateValue aState); void DrawHIThemeButton(CGContextRef cgContext, const HIRect& aRect, ThemeButtonKind aKind, ThemeButtonValue aValue, ThemeDrawState aState, ThemeButtonAdornment aAdornment, const ControlParams& aParams); void DrawButton(CGContextRef context, const HIRect& inBoxRect, const ButtonParams& aParams); void DrawDropdown(CGContextRef context, const HIRect& inBoxRect, const DropdownParams& aParams); HIThemeButtonDrawInfo SpinButtonDrawInfo(ThemeButtonKind aKind, const SpinButtonParams& aParams); void DrawSpinButtons(CGContextRef context, const HIRect& inBoxRect, const SpinButtonParams& aParams); void DrawSpinButton(CGContextRef context, const HIRect& inBoxRect, SpinButton aDrawnButton, const SpinButtonParams& aParams); void DrawToolbar(CGContextRef cgContext, const CGRect& inBoxRect, bool aIsMain); void DrawStatusBar(CGContextRef cgContext, const HIRect& inBoxRect, bool aIsMain); void DrawMultilineTextField(CGContextRef cgContext, const CGRect& inBoxRect, bool aIsFocused); void RenderWidget(const WidgetInfo& aWidgetInfo, mozilla::ColorScheme, mozilla::gfx::DrawTarget& aDrawTarget, const mozilla::gfx::Rect& aWidgetRect, const mozilla::gfx::Rect& aDirtyRect, float aScale); private: NSButtonCell* mDisclosureButtonCell; NSButtonCell* mHelpButtonCell; NSButtonCell* mPushButtonCell; NSButtonCell* mRadioButtonCell; NSButtonCell* mCheckboxCell; NSTextFieldCell* mTextFieldCell; MOZSearchFieldCell* mSearchFieldCell; NSPopUpButtonCell* mDropdownCell; NSComboBoxCell* mComboBoxCell; NSProgressBarCell* mProgressBarCell; NSLevelIndicatorCell* mMeterBarCell; MOZCellDrawWindow* mCellDrawWindow = nil; MOZCellDrawView* mCellDrawView; }; #endif // nsNativeThemeCocoa_h_